diff --git a/.eslintignore b/.eslintignore index 153ac6e24f731e..6f3d86e6bfac8a 100644 --- a/.eslintignore +++ b/.eslintignore @@ -8,5 +8,7 @@ tools/lint-md/lint-md.mjs benchmark/tmp benchmark/fixtures doc/**/*.js +doc/changelogs/CHANGELOG_v1*.md +!doc/changelogs/CHANGELOG_v18.md !doc/api_assets/*.js !.eslintrc.js diff --git a/.eslintrc.js b/.eslintrc.js index 71c772b3be9e5c..b427c9986f679f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -18,7 +18,7 @@ const hacks = [ 'eslint-plugin-jsdoc', 'eslint-plugin-markdown', '@babel/eslint-parser', - '@babel/plugin-syntax-import-assertions', + '@babel/plugin-syntax-import-attributes', ]; Module._findPath = (request, paths, isMain) => { const r = ModuleFindPath(request, paths, isMain); @@ -44,7 +44,10 @@ module.exports = { parserOptions: { babelOptions: { plugins: [ - Module._findPath('@babel/plugin-syntax-import-assertions'), + [ + Module._findPath('@babel/plugin-syntax-import-attributes'), + { deprecatedAssertSyntax: true }, + ], ], }, requireConfigFile: false, @@ -53,10 +56,10 @@ module.exports = { overrides: [ { files: [ - 'test/es-module/test-esm-type-flag.js', - 'test/es-module/test-esm-type-flag-alias.js', '*.mjs', 'test/es-module/test-esm-example-loader.js', + 'test/es-module/test-esm-type-flag.js', + 'test/es-module/test-esm-type-flag-alias.js', ], parserOptions: { sourceType: 'module' }, }, @@ -111,6 +114,22 @@ module.exports = { }, ] }, }, + { + files: [ + 'lib/internal/modules/**/*.js', + ], + rules: { + 'curly': 'error', + }, + }, + { + files: [ + 'lib/internal/test_runner/**/*.js', + ], + rules: { + 'node-core/set-proto-to-null-in-object': 'error', + }, + }, ], rules: { // ESLint built-in rules diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 648efc2da80870..776cad7a4c99ea 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -11,6 +11,8 @@ # tsc /.github/CODEOWNERS @nodejs/tsc +/.github/PULL_REQUEST_TEMPLATE.md @nodejs/tsc +/.github/ISSUE_TEMPLATE/* @nodejs/tsc /CODE_OF_CONDUCT.md @nodejs/tsc /CONTRIBUTING.md @nodejs/tsc /doc/contributing/*.md @nodejs/tsc @@ -18,10 +20,10 @@ /LICENSE @nodejs/tsc /onboarding.md @nodejs/tsc -# website -/doc/api_assets @nodejs/website -/doc/template.html @nodejs/website -/tools/doc @nodejs/website +# nodejs.org website +/doc/api_assets @nodejs/nodejs-website +/doc/template.html @nodejs/nodejs-website +/tools/doc @nodejs/web-infra # streams @@ -85,16 +87,16 @@ # modules, including loaders -/doc/api/esm.md @nodejs/modules @nodejs/loaders -/doc/api/module.md @nodejs/modules @nodejs/loaders -/doc/api/modules.md @nodejs/modules @nodejs/loaders -/doc/api/packages.md @nodejs/modules @nodejs/loaders -/lib/internal/bootstrap/loaders.js @nodejs/modules @nodejs/loaders -/lib/internal/modules/* @nodejs/modules @nodejs/loaders -/lib/internal/process/esm_loader.js @nodejs/modules @nodejs/loaders -/lib/internal/process/execution.js @nodejs/modules @nodejs/loaders -/lib/module.js @nodejs/modules @nodejs/loaders -/src/module_wrap* @nodejs/modules @nodejs/loaders @nodejs/vm +/doc/api/esm.md @nodejs/loaders +/doc/api/module.md @nodejs/loaders +/doc/api/modules.md @nodejs/loaders +/doc/api/packages.md @nodejs/loaders +/lib/internal/bootstrap/realm.js @nodejs/loaders +/lib/internal/modules/* @nodejs/loaders +/lib/internal/process/esm_loader.js @nodejs/loaders +/lib/internal/process/execution.js @nodejs/loaders +/lib/module.js @nodejs/loaders +/src/module_wrap* @nodejs/loaders @nodejs/vm # Node-API @@ -146,6 +148,7 @@ /lib/internal/main/test_runner.js @nodejs/test_runner /lib/internal/test_runner/* @nodejs/test_runner /lib/test.js @nodejs/test_runner +/lib/test/reporters.js @nodejs/test_runner /test/parallel/test-runner-* @nodejs/test_runner # Single Executable Applications diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index fe46bf4deadeb7..936c2a06125795 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,15 +1,18 @@ - -Please look thru your error log for the string `gyp info using node-gyp@` and if the version number is less than the [current release of node-gyp](https://github.com/nodejs/node-gyp/releases) then __please upgrade__ using the instructions at https://github.com/nodejs/node-gyp/blob/master/docs/Updating-npm-bundled-node-gyp.md and try your command again. - -Requests for help with [`node-sass` are very common](https://github.com/nodejs/node-gyp/issues?q=label%3A%22Node+Sass+--%3E+Dart+Sass%22). Please be aware that this package is deprecated, you should seek alternatives and avoid opening new issues about it here. - -* **Node Version**: -* **Platform**: -* **Compiler**: -* **Module**: - -
Verbose output (from npm or node-gyp): - -``` -Paste your log here, between the backticks. It can be: - - npm --verbose output, - - or contents of npm-debug.log, - - or output of node-gyp rebuild --verbose. -Include the command you were trying to run. - -This should look like this: - ->npm --verbose -npm info it worked if it ends with ok -npm verb cli [ -npm verb cli 'C:\\...\\node\\13.9.0\\x64\\node.exe', -npm verb cli 'C:\\...\\node\\13.9.0\\x64\\node_modules\\npm\\bin\\npm-cli.js', -npm verb cli '--verbose' -npm verb cli ] -npm info using npm@6.13.7 -npm info using node@v13.9.0 - -Usage: npm -(...) -``` - -
- - diff --git a/deps/npm/node_modules/node-gyp/.github/PULL_REQUEST_TEMPLATE.md b/deps/npm/node_modules/node-gyp/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index bcc4bb1a048c80..00000000000000 --- a/deps/npm/node_modules/node-gyp/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,17 +0,0 @@ - - -##### Checklist - - -- [ ] `npm install && npm test` passes -- [ ] tests are included -- [ ] documentation is changed or added -- [ ] commit message follows [commit guidelines](https://github.com/googleapis/release-please#how-should-i-write-my-commits) - -##### Description of change - - diff --git a/deps/npm/node_modules/node-gyp/.github/workflows/release-please.yml b/deps/npm/node_modules/node-gyp/.github/workflows/release-please.yml deleted file mode 100644 index c3057c3a3159ae..00000000000000 --- a/deps/npm/node_modules/node-gyp/.github/workflows/release-please.yml +++ /dev/null @@ -1,56 +0,0 @@ -name: release-please - -on: - push: - branches: - - main - -jobs: - release-please: - runs-on: ubuntu-latest - steps: - - uses: google-github-actions/release-please-action@v2 - id: release - with: - package-name: node-gyp - release-type: node - changelog-types: > - [{"type":"feat","section":"Features","hidden":false}, - {"type":"fix","section":"Bug Fixes","hidden":false}, - {"type":"bin","section":"Core","hidden":false}, - {"type":"gyp","section":"Core","hidden":false}, - {"type":"lib","section":"Core","hidden":false}, - {"type":"src","section":"Core","hidden":false}, - {"type":"test","section":"Tests","hidden":false}, - {"type":"build","section":"Core","hidden":false}, - {"type":"clean","section":"Core","hidden":false}, - {"type":"configure","section":"Core","hidden":false}, - {"type":"install","section":"Core","hidden":false}, - {"type":"list","section":"Core","hidden":false}, - {"type":"rebuild","section":"Core","hidden":false}, - {"type":"remove","section":"Core","hidden":false}, - {"type":"deps","section":"Core","hidden":false}, - {"type":"python","section":"Core","hidden":false}, - {"type":"lin","section":"Core","hidden":false}, - {"type":"linux","section":"Core","hidden":false}, - {"type":"mac","section":"Core","hidden":false}, - {"type":"macos","section":"Core","hidden":false}, - {"type":"win","section":"Core","hidden":false}, - {"type":"windows","section":"Core","hidden":false}, - {"type":"zos","section":"Core","hidden":false}, - {"type":"doc","section":"Doc","hidden":false}, - {"type":"docs","section":"Doc","hidden":false}, - {"type":"readme","section":"Doc","hidden":false}, - {"type":"chore","section":"Miscellaneous","hidden":false}, - {"type":"refactor","section":"Miscellaneous","hidden":false}, - {"type":"ci","section":"Miscellaneous","hidden":false}, - {"type":"meta","section":"Miscellaneous","hidden":false}] - - # Standard Conventional Commits: `feat` and `fix` - # node-gyp subdirectories: `bin`, `gyp`, `lib`, `src`, `test` - # node-gyp subcommands: `build`, `clean`, `configure`, `install`, `list`, `rebuild`, `remove` - # Core abstract category: `deps` - # Languages/platforms: `python`, `lin`, `linux`, `mac`, `macos`, `win`, `window`, `zos` - # Documentation: `doc`, `docs`, `readme` - # Standard Conventional Commits: `chore` (under "Miscellaneous") - # Miscellaneous abstract categories: `refactor`, `ci`, `meta` diff --git a/deps/npm/node_modules/node-gyp/.github/workflows/tests.yml b/deps/npm/node_modules/node-gyp/.github/workflows/tests.yml deleted file mode 100644 index 517b2d95a48c6f..00000000000000 --- a/deps/npm/node_modules/node-gyp/.github/workflows/tests.yml +++ /dev/null @@ -1,55 +0,0 @@ -# https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources -# TODO: Line 48, enable pytest --doctest-modules - -name: Tests -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] -jobs: - Lint_Python: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - run: pip install --user ruff - - run: ruff --format=github --select="E,F,PLC,PLE,UP,W,YTT" --ignore="PLC1901,S101,UP031" --target-version=py37 . - Tests: - strategy: - fail-fast: false - max-parallel: 15 - matrix: - node: [16.x, 18.x, 20.x] - python: ["3.8", "3.11"] - os: [macos-latest, ubuntu-latest, windows-latest] - runs-on: ${{ matrix.os }} - steps: - - name: Checkout Repository - uses: actions/checkout@v3 - - name: Use Node.js ${{ matrix.node }} - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node }} - - name: Use Python ${{ matrix.python }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python }} - env: - PYTHON_VERSION: ${{ matrix.python }} # Why do this? - - name: Install Dependencies - run: | - npm install --no-progress - pip install pytest - - name: Set Windows environment - if: startsWith(matrix.os, 'windows') - run: | - echo 'GYP_MSVS_VERSION=2015' >> $Env:GITHUB_ENV - echo 'GYP_MSVS_OVERRIDE_PATH=C:\\Dummy' >> $Env:GITHUB_ENV - - name: Run Python tests - run: python -m pytest - # - name: Run doctests with pytest - # run: python -m pytest --doctest-modules - - name: Environment Information - run: npx envinfo - - name: Run Node tests - run: npm test diff --git a/deps/npm/node_modules/node-gyp/.github/workflows/visual-studio.yml b/deps/npm/node_modules/node-gyp/.github/workflows/visual-studio.yml deleted file mode 100644 index 12125e54479b87..00000000000000 --- a/deps/npm/node_modules/node-gyp/.github/workflows/visual-studio.yml +++ /dev/null @@ -1,33 +0,0 @@ -# https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources - -name: visual-studio -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] -jobs: - visual-studio: - strategy: - fail-fast: false - max-parallel: 8 - matrix: - os: [windows-latest] - msvs-version: [2016, 2019, 2022] # https://github.com/actions/virtual-environments/tree/main/images/win - runs-on: ${{ matrix.os }} - steps: - - name: Checkout Repository - uses: actions/checkout@v3 - - name: Install Dependencies - run: | - npm install --no-progress - # npm audit fix --force - - name: Set Windows environment - if: startsWith(matrix.os, 'windows') - run: | - echo 'GYP_MSVS_VERSION=${{ matrix.msvs-version }}' >> $Env:GITHUB_ENV - echo 'GYP_MSVS_OVERRIDE_PATH=C:\\Dummy' >> $Env:GITHUB_ENV - - name: Environment Information - run: npx envinfo - - name: Run Node tests - run: npm test diff --git a/deps/npm/node_modules/node-gyp/CHANGELOG.md b/deps/npm/node_modules/node-gyp/CHANGELOG.md index 9fb5f11847bb26..98315add5e0d46 100644 --- a/deps/npm/node_modules/node-gyp/CHANGELOG.md +++ b/deps/npm/node_modules/node-gyp/CHANGELOG.md @@ -1,5 +1,83 @@ # Changelog +### [10.0.1](https://www.github.com/nodejs/node-gyp/compare/v10.0.0...v10.0.1) (2023-11-02) + + +### Bug Fixes + +* use local `util` for `findAccessibleSync()` ([b39e681](https://www.github.com/nodejs/node-gyp/commit/b39e6819aa9e2c45107d6e60a4913ca036ebfbfd)) + + +### Miscellaneous + +* add parallel test logging ([7de1f5f](https://www.github.com/nodejs/node-gyp/commit/7de1f5f32d550d26d48fe4f76aed5866744edcba)) +* lint fixes ([4e0ed99](https://www.github.com/nodejs/node-gyp/commit/4e0ed992566f43abc6e988af091ad07fde04acbf)) +* use platform specific timeouts in tests ([a68586a](https://www.github.com/nodejs/node-gyp/commit/a68586a67d0af238300662cc062422b42820044d)) + +## [10.0.0](https://www.github.com/nodejs/node-gyp/compare/v9.4.0...v10.0.0) (2023-10-28) + + +### ⚠ BREAKING CHANGES + +* use .npmignore file to limit which files are published (#2921) +* the `Gyp` class exported is now created using ECMAScript classes and therefore might have small differences to classes that were previously created with `util.inherits`. +* All internal functions have been coverted to return promises and no longer accept callbacks. This is not a breaking change for users but may be breaking to consumers of `node-gyp` if you are requiring internal functions directly. +* `node-gyp` now supports node `^16.14.0 || >=18.0.0` +* update engines.node to ^14.17.0 || ^16.13.0 || >=18.0.0 + +### Features + +* convert all internal functions to async/await ([355622f](https://www.github.com/nodejs/node-gyp/commit/355622f4aac3bd3056b9e03aac5fa2f42a4b3576)) +* convert internal classes from util.inherits to classes ([d52997e](https://www.github.com/nodejs/node-gyp/commit/d52997e975b9da6e0cea3d9b99873e9ddc768679)) +* drop node 14 support ([#2929](https://www.github.com/nodejs/node-gyp/issues/2929)) ([1b3bd34](https://www.github.com/nodejs/node-gyp/commit/1b3bd341b40f384988d03207ce8187e93ba609bc)) +* drop rimraf dependency ([4a50fe3](https://www.github.com/nodejs/node-gyp/commit/4a50fe31574217c4b2a798fc72b19947a64ceea1)) +* **gyp:** update gyp to v0.16.1 ([#2923](https://www.github.com/nodejs/node-gyp/issues/2923)) ([707927c](https://www.github.com/nodejs/node-gyp/commit/707927cd579205ef2b4b17e61c1cce24c056b452)) +* replace npmlog with proc-log ([4a50fe3](https://www.github.com/nodejs/node-gyp/commit/4a50fe31574217c4b2a798fc72b19947a64ceea1)) +* update engines.node to ^14.17.0 || ^16.13.0 || >=18.0.0 ([4a50fe3](https://www.github.com/nodejs/node-gyp/commit/4a50fe31574217c4b2a798fc72b19947a64ceea1)) +* use .npmignore file to limit which files are published ([#2921](https://www.github.com/nodejs/node-gyp/issues/2921)) ([864a979](https://www.github.com/nodejs/node-gyp/commit/864a979930cf0ef5ad64bc887b901fa8955d058f)) + + +### Bug Fixes + +* create Python symlink only during builds, and clean it up after ([#2721](https://www.github.com/nodejs/node-gyp/issues/2721)) ([0f1f667](https://www.github.com/nodejs/node-gyp/commit/0f1f667b737d21905e283df100a2cb639993562a)) +* promisify build command ([4a50fe3](https://www.github.com/nodejs/node-gyp/commit/4a50fe31574217c4b2a798fc72b19947a64ceea1)) +* use fs/promises in favor of fs.promises ([4a50fe3](https://www.github.com/nodejs/node-gyp/commit/4a50fe31574217c4b2a798fc72b19947a64ceea1)) + + +### Tests + +* increase mocha timeout ([#2887](https://www.github.com/nodejs/node-gyp/issues/2887)) ([445c28f](https://www.github.com/nodejs/node-gyp/commit/445c28fabc5fbdf9c3bb3341fb70660a3530f6ad)) +* update expired certs ([#2908](https://www.github.com/nodejs/node-gyp/issues/2908)) ([5746691](https://www.github.com/nodejs/node-gyp/commit/5746691a36f7b37019d4b8d4e9616aec43d20410)) + + +### Doc + +* Add note about Python symlinks (PR 2362) to CHANGELOG.md for 9.1.0 ([#2783](https://www.github.com/nodejs/node-gyp/issues/2783)) ([b3d41ae](https://www.github.com/nodejs/node-gyp/commit/b3d41aeb737ddd54cc292f363abc561dcc0a614e)) +* README.md Do not hardcode the supported versions of Python ([#2880](https://www.github.com/nodejs/node-gyp/issues/2880)) ([bb93b94](https://www.github.com/nodejs/node-gyp/commit/bb93b946a9c74934b59164deb52128cf913c97d5)) +* update applicable GitHub links from master to main ([#2843](https://www.github.com/nodejs/node-gyp/issues/2843)) ([d644ce4](https://www.github.com/nodejs/node-gyp/commit/d644ce48311edf090d0e920ad449e5766c757933)) +* Update windows installation instructions in README.md ([#2882](https://www.github.com/nodejs/node-gyp/issues/2882)) ([c9caa2e](https://www.github.com/nodejs/node-gyp/commit/c9caa2ecf3c7deae68444ce8fabb32d2dca651cd)) + + +### Core + +* find python checks order changed on windows ([#2872](https://www.github.com/nodejs/node-gyp/issues/2872)) ([b030555](https://www.github.com/nodejs/node-gyp/commit/b030555cdb754d9c23906e7e707115cd077bbf76)) +* glob@10.3.10 ([#2926](https://www.github.com/nodejs/node-gyp/issues/2926)) ([4bef1ec](https://www.github.com/nodejs/node-gyp/commit/4bef1ecc7554097d92beb397fbe1a546c5227545)) +* glob@8.0.3 ([4a50fe3](https://www.github.com/nodejs/node-gyp/commit/4a50fe31574217c4b2a798fc72b19947a64ceea1)) +* make-fetch-happen@13.0.0 ([#2927](https://www.github.com/nodejs/node-gyp/issues/2927)) ([059bb6f](https://www.github.com/nodejs/node-gyp/commit/059bb6fd41bb50955a9efbd97887773d60d53221)) +* nopt@^7.0.0 ([4a50fe3](https://www.github.com/nodejs/node-gyp/commit/4a50fe31574217c4b2a798fc72b19947a64ceea1)) +* standard@17.0.0 and fix linting errors ([4a50fe3](https://www.github.com/nodejs/node-gyp/commit/4a50fe31574217c4b2a798fc72b19947a64ceea1)) +* which@3.0.0 ([4a50fe3](https://www.github.com/nodejs/node-gyp/commit/4a50fe31574217c4b2a798fc72b19947a64ceea1)) +* which@4.0.0 ([#2928](https://www.github.com/nodejs/node-gyp/issues/2928)) ([e388255](https://www.github.com/nodejs/node-gyp/commit/e38825531403aabeae7abe58e76867f31b832f36)) + + +### Miscellaneous + +* add check engines script to CI ([#2922](https://www.github.com/nodejs/node-gyp/issues/2922)) ([21a7249](https://www.github.com/nodejs/node-gyp/commit/21a7249b40d8f95e7721e450fd18764adb1648a7)) +* empty commit to add changelog entries from [#2770](https://www.github.com/nodejs/node-gyp/issues/2770) ([4a50fe3](https://www.github.com/nodejs/node-gyp/commit/4a50fe31574217c4b2a798fc72b19947a64ceea1)) +* GitHub Workflows security hardening ([#2740](https://www.github.com/nodejs/node-gyp/issues/2740)) ([26683e9](https://www.github.com/nodejs/node-gyp/commit/26683e993df038fb94d89f2276f3535e4522d79a)) +* misc testing fixes ([#2930](https://www.github.com/nodejs/node-gyp/issues/2930)) ([4e493d4](https://www.github.com/nodejs/node-gyp/commit/4e493d4fb262d12ac52c84979071ccc79e666a1a)) +* run tests after release please PR ([3032e10](https://www.github.com/nodejs/node-gyp/commit/3032e1061cc2b7b49f83c397d385bafddc6b0214)) + ## [9.4.0](https://www.github.com/nodejs/node-gyp/compare/v9.3.1...v9.4.0) (2023-06-12) @@ -98,6 +176,7 @@ ### Core * update due to rename of primary branch ([ca1f068](https://www.github.com/nodejs/node-gyp/commit/ca1f0681a5567ca8cd51acebccd37a633f19bc6a)) +* Add Python symlink to path (for non-Windows OSes only) ([#2362](https://github.com/nodejs/node-gyp/pull/2362)) ([b9ddcd5](https://github.com/nodejs/node-gyp/commit/b9ddcd5bbd93b05b03674836b6ebdae2c2e74c8c)) ### Tests diff --git a/deps/npm/node_modules/node-gyp/CONTRIBUTING.md b/deps/npm/node_modules/node-gyp/CONTRIBUTING.md index c1c50eab4e58b7..5b977898f104b3 100644 --- a/deps/npm/node_modules/node-gyp/CONTRIBUTING.md +++ b/deps/npm/node_modules/node-gyp/CONTRIBUTING.md @@ -3,7 +3,7 @@ ## Code of Conduct Please read the -[Code of Conduct](https://github.com/nodejs/admin/blob/master/CODE_OF_CONDUCT.md) +[Code of Conduct](https://github.com/nodejs/admin/blob/main/CODE_OF_CONDUCT.md) which explains the minimum behavior expectations for node-gyp contributors. diff --git a/deps/npm/node_modules/node-gyp/README.md b/deps/npm/node_modules/node-gyp/README.md index 99494a38d09b38..f46ee06308db1e 100644 --- a/deps/npm/node_modules/node-gyp/README.md +++ b/deps/npm/node_modules/node-gyp/README.md @@ -1,12 +1,13 @@ # `node-gyp` - Node.js native addon build tool -[![Build Status](https://github.com/nodejs/node-gyp/workflows/Tests/badge.svg?branch=master)](https://github.com/nodejs/node-gyp/actions?query=workflow%3ATests+branch%3Amaster) +[![Build Status](https://github.com/nodejs/node-gyp/workflows/Tests/badge.svg?branch=main)](https://github.com/nodejs/node-gyp/actions?query=workflow%3ATests+branch%3Amain) ![npm](https://img.shields.io/npm/dm/node-gyp) `node-gyp` is a cross-platform command-line tool written in Node.js for compiling native addon modules for Node.js. It contains a vendored copy of the [gyp-next](https://github.com/nodejs/gyp-next) project that was previously used -by the Chromium team, extended to support the development of Node.js native addons. +by the Chromium team and extended to support the development of Node.js native +addons. Note that `node-gyp` is _not_ used to build Node.js itself. @@ -31,27 +32,26 @@ Depending on your operating system, you will need to install: ### On Unix - * Python v3.7, v3.8, v3.9, or v3.10 + * [A supported version of Python](https://devguide.python.org/versions/) * `make` * A proper C/C++ compiler toolchain, like [GCC](https://gcc.gnu.org) ### On macOS -**ATTENTION**: If your Mac has been _upgraded_ to macOS Catalina (10.15) or higher, please read [macOS_Catalina.md](macOS_Catalina.md). - - * Python v3.7, v3.8, v3.9, or v3.10 - * `XCode Command Line Tools` which will install `clang`, `clang++`, and `make`. - * Install the `XCode Command Line Tools` standalone by running `xcode-select --install`. -- OR -- + * [A supported version of Python](https://devguide.python.org/versions/) + * `Xcode Command Line Tools` which will install `clang`, `clang++`, and `make`. + * Install the `Xcode Command Line Tools` standalone by running `xcode-select --install`. -- OR -- * Alternatively, if you already have the [full Xcode installed](https://developer.apple.com/xcode/download/), you can install the Command Line Tools under the menu `Xcode -> Open Developer Tool -> More Developer Tools...`. ### On Windows -Install the current version of Python from the [Microsoft Store package](https://www.microsoft.com/en-us/p/python-310/9pjpw5ldxlz5). +Install the current [version of Python](https://devguide.python.org/versions/) from the +[Microsoft Store](https://apps.microsoft.com/store/search?publisher=Python+Software+Foundation). Install tools and configuration manually: * Install Visual C++ Build Environment: [Visual Studio Build Tools](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools) - (using "Visual C++ build tools" workload) or [Visual Studio Community](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community) + (using "Visual C++ build tools" if using a version older than VS2019, otherwise use "Desktop development with C++" workload) or [Visual Studio Community](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community) (using the "Desktop development with C++" workload) If the above steps didn't work for you, please visit [Microsoft's Node.js Guidelines for Windows](https://github.com/Microsoft/nodejs-guidelines/blob/master/windows-environment.md#compiling-native-addon-modules) for additional tips. @@ -62,9 +62,9 @@ Install tools and configuration manually: ### Configuring Python Dependency -`node-gyp` requires that you have installed a compatible version of Python, one of: v3.7, v3.8, -v3.9, or v3.10. If you have multiple Python versions installed, you can identify which Python -version `node-gyp` should use in one of the following ways: +`node-gyp` requires that you have installed a [supported version of Python](https://devguide.python.org/versions/). +If you have multiple versions of Python installed, you can identify which version +`node-gyp` should use in one of the following ways: 1. by setting the `--python` command-line option, e.g.: @@ -73,24 +73,28 @@ node-gyp --python /path/to/executable/python ``` 2. If `node-gyp` is called by way of `npm`, *and* you have multiple versions of -Python installed, then you can set `npm`'s 'python' config key to the appropriate -value: - +Python installed, then you can set the `npm_config_python` environment variable +to the appropriate path: ``` bash -npm config set python /path/to/executable/python +export npm_config_python=/path/to/executable/python +``` +    Or on Windows: +```console +py --list-paths # To see the installed Python versions +set npm_config_python=C:\path\to\python.exe ``` 3. If the `PYTHON` environment variable is set to the path of a Python executable, -then that version will be used, if it is a compatible version. +then that version will be used if it is a supported version. 4. If the `NODE_GYP_FORCE_PYTHON` environment variable is set to the path of a Python executable, it will be used instead of any of the other configured or -builtin Python search paths. If it's not a compatible version, no further +built-in Python search paths. If it's not a compatible version, no further searching will be done. ### Build for Third Party Node.js Runtimes -When building modules for third party Node.js runtimes like Electron, which have +When building modules for third-party Node.js runtimes like Electron, which have different build configurations from the official Node.js distribution, you should use `--dist-url` or `--nodedir` flags to specify the headers of the runtime to build for. @@ -106,7 +110,7 @@ to work around configuration errors. ## How to Use -To compile your native addon, first go to its root directory: +To compile your native addon first go to its root directory: ``` bash cd my_node_addon @@ -168,7 +172,7 @@ The **[docs](./docs/)** directory contains additional documentation on specific Some additional resources for Node.js native addons and writing `gyp` configuration files: * ["Going Native" a nodeschool.io tutorial](http://nodeschool.io/#goingnative) - * ["Hello World" node addon example](https://github.com/nodejs/node/tree/master/test/addons/hello-world) + * ["Hello World" node addon example](https://github.com/nodejs/node/tree/main/test/addons/hello-world) * [gyp user documentation](https://gyp.gsrc.io/docs/UserDocumentation.md) * [gyp input format reference](https://gyp.gsrc.io/docs/InputFormatReference.md) * [*"binding.gyp" files out in the wild* wiki page](./docs/binding.gyp-files-in-the-wild.md) @@ -240,7 +244,7 @@ Or this on Windows: set npm_config_devdir=c:\temp\.gyp ``` -### `npm` configuration +### `npm` configuration for npm versions before v9 Use the form `OPTION_NAME` for any of the command options listed above. diff --git a/deps/npm/node_modules/node-gyp/bin/node-gyp.js b/deps/npm/node_modules/node-gyp/bin/node-gyp.js index 8652ea21eceebb..f8317b47b34147 100755 --- a/deps/npm/node_modules/node-gyp/bin/node-gyp.js +++ b/deps/npm/node_modules/node-gyp/bin/node-gyp.js @@ -6,7 +6,7 @@ process.title = 'node-gyp' const envPaths = require('env-paths') const gyp = require('../') -const log = require('npmlog') +const log = require('../lib/log') const os = require('os') /** @@ -14,11 +14,11 @@ const os = require('os') */ const prog = gyp() -var completed = false +let completed = false prog.parseArgv(process.argv) prog.devDir = prog.opts.devdir -var homeDir = os.homedir() +const homeDir = os.homedir() if (prog.devDir) { prog.devDir = prog.devDir.replace(/^~/, homeDir) } else if (homeDir) { @@ -32,9 +32,9 @@ if (prog.devDir) { if (prog.todo.length === 0) { if (~process.argv.indexOf('-v') || ~process.argv.indexOf('--version')) { - console.log('v%s', prog.version) + log.stdout('v%s', prog.version) } else { - console.log('%s', prog.usage()) + log.stdout('%s', prog.usage()) } process.exit(0) } @@ -48,11 +48,11 @@ log.info('using', 'node@%s | %s | %s', process.versions.node, process.platform, * Change dir if -C/--directory was passed. */ -var dir = prog.opts.directory +const dir = prog.opts.directory if (dir) { - var fs = require('fs') + const fs = require('fs') try { - var stat = fs.statSync(dir) + const stat = fs.statSync(dir) if (stat.isDirectory()) { log.info('chdir', dir) process.chdir(dir) @@ -68,8 +68,8 @@ if (dir) { } } -function run () { - var command = prog.todo.shift() +async function run () { + const command = prog.todo.shift() if (!command) { // done! completed = true @@ -77,30 +77,28 @@ function run () { return } - prog.commands[command.name](command.args, function (err) { - if (err) { - log.error(command.name + ' error') - log.error('stack', err.stack) - errorMessage() - log.error('not ok') - return process.exit(1) - } + try { + const args = await prog.commands[command.name](command.args) ?? [] + if (command.name === 'list') { - var versions = arguments[1] - if (versions.length > 0) { - versions.forEach(function (version) { - console.log(version) - }) + if (args.length) { + args.forEach((version) => log.stdout(version)) } else { - console.log('No node development files installed. Use `node-gyp install` to install a version.') + log.stdout('No node development files installed. Use `node-gyp install` to install a version.') } - } else if (arguments.length >= 2) { - console.log.apply(console, [].slice.call(arguments, 1)) + } else if (args.length >= 1) { + log.stdout(...args.slice(1)) } // now run the next command in the queue - process.nextTick(run) - }) + return run() + } catch (err) { + log.error(command.name + ' error') + log.error('stack', err.stack) + errorMessage() + log.error('not ok') + return process.exit(1) + } } process.on('exit', function (code) { @@ -120,7 +118,7 @@ process.on('uncaughtException', function (err) { function errorMessage () { // copied from npm's lib/utils/error-handler.js - var os = require('os') + const os = require('os') log.error('System', os.type() + ' ' + os.release()) log.error('command', process.argv .map(JSON.stringify).join(' ')) diff --git a/deps/npm/node_modules/node-gyp/docs/Error-pre-versions-of-node-cannot-be-installed.md b/deps/npm/node_modules/node-gyp/docs/Error-pre-versions-of-node-cannot-be-installed.md deleted file mode 100644 index c1e1158d70190b..00000000000000 --- a/deps/npm/node_modules/node-gyp/docs/Error-pre-versions-of-node-cannot-be-installed.md +++ /dev/null @@ -1,94 +0,0 @@ -When using `node-gyp` you might see an error like this when attempting to compile/install a node.js native addon: - -``` -$ npm install bcrypt -npm http GET https://registry.npmjs.org/bcrypt/0.7.5 -npm http 304 https://registry.npmjs.org/bcrypt/0.7.5 -npm http GET https://registry.npmjs.org/bindings/1.0.0 -npm http 304 https://registry.npmjs.org/bindings/1.0.0 - -> bcrypt@0.7.5 install /home/ubuntu/public/song-swap/node_modules/bcrypt -> node-gyp rebuild - -gyp ERR! configure error -gyp ERR! stack Error: "pre" versions of node cannot be installed, use the --nodedir flag instead -gyp ERR! stack at install (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/install.js:69:16) -gyp ERR! stack at Object.self.commands.(anonymous function) [as install] (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/node-gyp.js:56:37) -gyp ERR! stack at getNodeDir (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/configure.js:219:20) -gyp ERR! stack at /usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/configure.js:105:9 -gyp ERR! stack at ChildProcess.exithandler (child_process.js:630:7) -gyp ERR! stack at ChildProcess.EventEmitter.emit (events.js:99:17) -gyp ERR! stack at maybeClose (child_process.js:730:16) -gyp ERR! stack at Process.ChildProcess._handle.onexit (child_process.js:797:5) -gyp ERR! System Linux 3.5.0-21-generic -gyp ERR! command "node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild" -gyp ERR! cwd /home/ubuntu/public/song-swap/node_modules/bcrypt -gyp ERR! node -v v0.11.2-pre -gyp ERR! node-gyp -v v0.9.5 -gyp ERR! not ok -npm ERR! bcrypt@0.7.5 install: `node-gyp rebuild` -npm ERR! `sh "-c" "node-gyp rebuild"` failed with 1 -npm ERR! -npm ERR! Failed at the bcrypt@0.7.5 install script. -npm ERR! This is most likely a problem with the bcrypt package, -npm ERR! not with npm itself. -npm ERR! Tell the author that this fails on your system: -npm ERR! node-gyp rebuild -npm ERR! You can get their info via: -npm ERR! npm owner ls bcrypt -npm ERR! There is likely additional logging output above. - -npm ERR! System Linux 3.5.0-21-generic -npm ERR! command "/usr/local/bin/node" "/usr/local/bin/npm" "install" "bcrypt" -npm ERR! cwd /home/ubuntu/public/song-swap -npm ERR! node -v v0.11.2-pre -npm ERR! npm -v 1.2.18 -npm ERR! code ELIFECYCLE -npm ERR! -npm ERR! Additional logging details can be found in: -npm ERR! /home/ubuntu/public/song-swap/npm-debug.log -npm ERR! not ok code 0 -``` - -The main error here is: - -``` -Error: "pre" versions of node cannot be installed, use the --nodedir flag instead -``` - -This error is caused when you attempt to compile a native addon using a version of node.js with `-pre` at the end of the version number: - -``` bash -$ node -v -v0.10.4-pre -``` - -## How to avoid (the short answer) - -To avoid this error completely just use a stable release of node.js. i.e. `v0.10.4`, and __not__ `v0.10.4-pre`. - -## How to fix (the long answer) - -This error happens because `node-gyp` does not know what header files were used to compile your "pre" version of node, and therefore it needs you to specify the node source code directory path using the `--nodedir` flag. - -For example, if I compiled my development ("pre") version of node.js using the source code in `/Users/nrajlich/node`, then I could invoke `node-gyp` like: - -``` bash -$ node-gyp rebuild --nodedir=/Users/nrajlich/node -``` - -Or install an native addon through `npm` like: - -``` bash -$ npm install bcrypt --nodedir=/Users/nrajlich/node -``` - -### Always use `--nodedir` - -__Note:__ This is for advanced users who use `-pre` versions of node more often than tagged releases. - -If you're invoking `node-gyp` through `npm`, then you can leverage `npm`'s configuration system and not have to specify the `--nodedir` flag all the time: - -``` bash -$ npm config set nodedir /Users/nrajlich/node -``` \ No newline at end of file diff --git a/deps/npm/node_modules/node-gyp/docs/Force-npm-to-use-global-node-gyp.md b/deps/npm/node_modules/node-gyp/docs/Force-npm-to-use-global-node-gyp.md deleted file mode 100644 index c6304e490a75d9..00000000000000 --- a/deps/npm/node_modules/node-gyp/docs/Force-npm-to-use-global-node-gyp.md +++ /dev/null @@ -1,47 +0,0 @@ -# Force npm to use global installed node-gyp - -**Note: These instructions only work with npm 6 or older. For a solution that works with npm 8 (or older), see [Updating-npm-bundled-node-gyp.md](Updating-npm-bundled-node-gyp.md).** - -[Many issues](https://github.com/nodejs/node-gyp/labels/ERR%21%20node-gyp%20-v%20%3C%3D%20v5.1.0) are opened by users who are -not running a [current version of node-gyp](https://github.com/nodejs/node-gyp/releases). - -npm bundles its own, internal, copy of node-gyp located at `npm/node_modules`, within npm's private dependencies which are separate from *globally* accessible packages. Therefore this internal copy of node-gyp is independent from any globally installed copy of node-gyp that -may have been installed via `npm install -g node-gyp`. - -So npm's internal copy of node-gyp **isn't** stored inside *global* `node_modules` and thus isn't available for use as a standalone package. npm uses it's *internal* copy of `node-gyp` to automatically build native addons. - -When you install a _new_ version of node-gyp outside of npm, it'll go into your *global* `node_modules`, but not under the `npm/node_modules` (where internal copy of node-gyp is stored). So it will get into your `$PATH` and you will be able to use this globally installed version (**but not internal node-gyp of npm**) as any other globally installed package. - -The catch is that npm **won't** use global version unless you tell it to, it'll keep on using the **internal one**. You need to instruct it to by setting the `node_gyp` config variable (which goes into your `~/.npmrc`). You do this by running the `npm config set` command as below. Then npm will use the command in the path you supply whenever it needs to build a native addon. - -**Important**: You also need to remember to unset this when you upgrade npm with a newer version of node-gyp, or you have to manually keep your globally installed node-gyp to date. See "Undo" below. - -## Linux and macOS -``` -npm install --global node-gyp@latest -npm config set node_gyp $(npm prefix -g)/lib/node_modules/node-gyp/bin/node-gyp.js -``` - -`sudo` may be required for the first command if you get a permission error. - -## Windows - -### Windows Command Prompt -``` -npm install --global node-gyp@latest -for /f "delims=" %P in ('npm prefix -g') do npm config set node_gyp "%P\node_modules\node-gyp\bin\node-gyp.js" -``` - -### Powershell -``` -npm install --global node-gyp@latest -npm prefix -g | % {npm config set node_gyp "$_\node_modules\node-gyp\bin\node-gyp.js"} -``` - -## Undo -**Beware** if you don't unset the `node_gyp` config option, npm will continue to use the globally installed version of node-gyp rather than the one it ships with, which may end up being newer. - -``` -npm config delete node_gyp -npm uninstall --global node-gyp -``` diff --git a/deps/npm/node_modules/node-gyp/docs/Home.md b/deps/npm/node_modules/node-gyp/docs/Home.md deleted file mode 100644 index fe099868b28225..00000000000000 --- a/deps/npm/node_modules/node-gyp/docs/Home.md +++ /dev/null @@ -1,7 +0,0 @@ -Welcome to the node-gyp wiki! - - * [["binding.gyp" files out in the wild]] - * [[Linking to OpenSSL]] - * [[Common Issues]] - * [[Updating npm's bundled node-gyp]] - * [[Error: "pre" versions of node cannot be installed]] diff --git a/deps/npm/node_modules/node-gyp/docs/Linking-to-OpenSSL.md b/deps/npm/node_modules/node-gyp/docs/Linking-to-OpenSSL.md deleted file mode 100644 index 1c17ab8e313667..00000000000000 --- a/deps/npm/node_modules/node-gyp/docs/Linking-to-OpenSSL.md +++ /dev/null @@ -1,86 +0,0 @@ -A handful of native addons require linking to OpenSSL in one way or another. This introduces a small challenge since node will sometimes bundle OpenSSL statically (the default for node >= v0.8.x), or sometimes dynamically link to the system OpenSSL (default for node <= v0.6.x). - -Good native addons should account for both scenarios. It's recommended that you use the `binding.gyp` file provided below as a starting-point for any addon that needs to use OpenSSL: - -``` python -{ - 'variables': { - # node v0.6.x doesn't give us its build variables, - # but on Unix it was only possible to use the system OpenSSL library, - # so default the variable to "true", v0.8.x node and up will overwrite it. - 'node_shared_openssl%': 'true' - }, - 'targets': [ - { - 'target_name': 'binding', - 'sources': [ - 'src/binding.cc' - ], - 'conditions': [ - ['node_shared_openssl=="false"', { - # so when "node_shared_openssl" is "false", then OpenSSL has been - # bundled into the node executable. So we need to include the same - # header files that were used when building node. - 'include_dirs': [ - '<(node_root_dir)/deps/openssl/openssl/include' - ], - "conditions" : [ - ["target_arch=='ia32'", { - "include_dirs": [ "<(node_root_dir)/deps/openssl/config/piii" ] - }], - ["target_arch=='x64'", { - "include_dirs": [ "<(node_root_dir)/deps/openssl/config/k8" ] - }], - ["target_arch=='arm'", { - "include_dirs": [ "<(node_root_dir)/deps/openssl/config/arm" ] - }] - ] - }] - ] - } - ] -} -``` - -This ensures that when OpenSSL is statically linked into `node` then, the bundled OpenSSL headers are included, but when the system OpenSSL is in use, then only those headers will be used. - -## Windows? - -As you can see this baseline `binding.gyp` file only accounts for the Unix scenario. Currently on Windows the situation is a little less ideal. On Windows, OpenSSL is _always_ statically compiled into the `node` executable, so ideally it would be possible to use that copy of OpenSSL when building native addons. - -Unfortunately it doesn't seem like that is possible at the moment, as there would need to be tweaks made to the generated `node.lib` file to include the openssl glue functions, or a new `openssl.lib` file would need to be created during the node build. I'm not sure which is the easiest/most feasible. - -In the meantime, one possible solution is using another copy of OpenSSL, which is what [`node-bcrypt`](https://github.com/ncb000gt/node.bcrypt.js) currently does. Adding something like this to your `binding.gyp` file's `"conditions"` block would enable this: - -``` python - [ 'OS=="win"', { - 'conditions': [ - # "openssl_root" is the directory on Windows of the OpenSSL files. - # Check the "target_arch" variable to set good default values for - # both 64-bit and 32-bit builds of the module. - ['target_arch=="x64"', { - 'variables': { - 'openssl_root%': 'C:/OpenSSL-Win64' - }, - }, { - 'variables': { - 'openssl_root%': 'C:/OpenSSL-Win32' - }, - }], - ], - 'libraries': [ - '-l<(openssl_root)/lib/libeay32.lib', - ], - 'include_dirs': [ - '<(openssl_root)/include', - ], - }] -``` - -Now you can direct your users to install OpenSSL on Windows from here (be sure to tell them to install the 64-bit version if they're compiling against a 64-bit version of node): http://slproweb.com/products/Win32OpenSSL.html - -Also note that both `node-gyp` and `npm` allow you to overwrite that default `openssl_root` variable on the command line: - -``` bash -$ node-gyp rebuild --openssl-root="C:\Users\Nathan\Desktop\openssl" -``` \ No newline at end of file diff --git a/deps/npm/node_modules/node-gyp/docs/README.md b/deps/npm/node_modules/node-gyp/docs/README.md deleted file mode 100644 index 487fb0a57edbfa..00000000000000 --- a/deps/npm/node_modules/node-gyp/docs/README.md +++ /dev/null @@ -1,19 +0,0 @@ -## Versions of `node-gyp` that are earlier than v9.x.x - -Please look thru your error log for the string `gyp info using node-gyp@` and if that version number is less than the [current release of node-gyp](https://github.com/nodejs/node-gyp/releases) then __please upgrade__ using [these instructions](https://github.com/nodejs/node-gyp/blob/master/docs/Updating-npm-bundled-node-gyp.md) and then try your command again. - -## `node-sass` is deprecated - -Please be aware that the package [`node-sass` is deprecated](https://github.com/sass/node-sass#node-sass) so you should actively seek alternatives. You can try: -``` -npm uninstall node-sass -npm install sass --save -# or ... -npm install --global node-sass@latest -``` -`node-sass` projects _may_ work by downgrading to Node.js v14 but [that release is end-of-life](https://github.com/nodejs/release#release-schedule). -But in any case, please avoid opening new `node-sass` issues on this repo because we [cannot help much](https://github.com/nodejs/node-gyp/issues?q=is%3Aissue+label%3A%22Node+Sass+--%3E+Dart+Sass%22+). - -## Issues finding the installed Visual Studio - -In cmd, [`npm config set msvs_version 20xx`](https://github.com/nodejs/node-gyp#on-windows) with ___xx___ matching your locally installed version of Visual Studio. diff --git a/deps/npm/node_modules/node-gyp/docs/Updating-npm-bundled-node-gyp.md b/deps/npm/node_modules/node-gyp/docs/Updating-npm-bundled-node-gyp.md deleted file mode 100644 index 5759add3fee572..00000000000000 --- a/deps/npm/node_modules/node-gyp/docs/Updating-npm-bundled-node-gyp.md +++ /dev/null @@ -1,72 +0,0 @@ -# Updating the npm-bundled version of node-gyp - -**Note: These instructions are (only) tested and known to work with npm 8 and older.** - -**Note: These instructions will be undone if you reinstall or upgrade npm or node! For a more permanent (and simpler) solution, see [Force-npm-to-use-global-node-gyp.md](Force-npm-to-use-global-node-gyp.md). (npm 6 or older only!)** - -[Many issues](https://github.com/nodejs/node-gyp/issues?q=label%3A"ERR!+node-gyp+-v+<%3D+v9.x.x") are opened by users who are -not running a [current version of node-gyp](https://github.com/nodejs/node-gyp/releases). - -`npm` bundles its own, internal, copy of `node-gyp`. This internal copy is independent of any globally installed copy of node-gyp that -may have been installed via `npm install -g node-gyp`. - -This means that while `node-gyp` doesn't get installed into your `$PATH` by default, npm still keeps its own copy to invoke when you -attempt to `npm install` a native add-on. - -Sometimes, you may need to update npm's internal node-gyp to a newer version than what is installed. A simple `npm install -g node-gyp` -_won't_ do the trick since npm will still continue to use its internal copy over the global one. - -So instead: - -## Version of npm - -We need to start by knowing your version of `npm`: -```bash -npm --version -``` - -## Linux, macOS, Solaris, etc. - -Unix is easy. Just run the following command. - -If your npm is version ___7 or 8___, do: -```bash -$ npm explore npm/node_modules/@npmcli/run-script -g -- npm_config_global=false npm install node-gyp@latest -``` - -Else if your npm is version ___less than 7___, do: -```bash -$ npm explore npm/node_modules/npm-lifecycle -g -- npm install node-gyp@latest -``` - -If the command fails with a permissions error, please try `sudo` and then the command. - -## Windows - -Windows is a bit trickier, since `npm` might be installed to the "Program Files" directory, which needs admin privileges in order to -modify on current Windows. Therefore, run the following commands __inside a `cmd.exe` started with "Run as Administrator"__: - -First we need to find the location of `node`. If you don't already know the location that `node.exe` got installed to, then run: -```bash -$ where node -``` - -Now `cd` to the directory that `node.exe` is contained in e.g.: -```bash -$ cd "C:\Program Files\nodejs" -``` - -If your npm version is ___7 or 8___, do: -```bash -cd node_modules\npm\node_modules\@npmcli\run-script -``` - -Else if your npm version is ___less than 7___, do: -```bash -cd node_modules\npm\node_modules\npm-lifecycle -``` - -Finish by running: -```bash -$ npm install node-gyp@latest -``` diff --git a/deps/npm/node_modules/node-gyp/docs/binding.gyp-files-in-the-wild.md b/deps/npm/node_modules/node-gyp/docs/binding.gyp-files-in-the-wild.md deleted file mode 100644 index 78afb32544776f..00000000000000 --- a/deps/npm/node_modules/node-gyp/docs/binding.gyp-files-in-the-wild.md +++ /dev/null @@ -1,49 +0,0 @@ -This page contains links to some examples of existing `binding.gyp` files that other node modules are using. Take a look at them for inspiration. - -To add to this page, just add the link to the project's `binding.gyp` file below: - - * [ons](https://github.com/XadillaX/aliyun-ons/blob/master/binding.gyp) - * [thmclrx](https://github.com/XadillaX/thmclrx/blob/master/binding.gyp) - * [libxmljs](https://github.com/polotek/libxmljs/blob/master/binding.gyp) - * [node-buffertools](https://github.com/bnoordhuis/node-buffertools/blob/master/binding.gyp) - * [node-canvas](https://github.com/LearnBoost/node-canvas/blob/master/binding.gyp) - * [node-ffi](https://github.com/rbranson/node-ffi/blob/master/binding.gyp) + [libffi](https://github.com/rbranson/node-ffi/blob/master/deps/libffi/libffi.gyp) - * [node-time](https://github.com/TooTallNate/node-time/blob/master/binding.gyp) - * [node-sass](https://github.com/sass/node-sass/blob/master/binding.gyp) + [libsass](https://github.com/sass/node-sass/blob/master/src/libsass.gyp) - * [node-serialport](https://github.com/voodootikigod/node-serialport/blob/master/binding.gyp) - * [node-weak](https://github.com/TooTallNate/node-weak/blob/master/binding.gyp) - * [pty.js](https://github.com/chjj/pty.js/blob/master/binding.gyp) - * [ref](https://github.com/TooTallNate/ref/blob/master/binding.gyp) - * [appjs](https://github.com/milani/appjs/blob/master/binding.gyp) - * [nwm](https://github.com/mixu/nwm/blob/master/binding.gyp) - * [bcrypt](https://github.com/ncb000gt/node.bcrypt.js/blob/master/binding.gyp) - * [nk-mysql](https://github.com/mmod/nodamysql/blob/master/binding.gyp) - * [nk-xrm-installer](https://github.com/mmod/nk-xrm-installer/blob/master/binding.gyp) + [includable.gypi](https://github.com/mmod/nk-xrm-installer/blob/master/includable.gypi) + [unpack.py](https://github.com/mmod/nk-xrm-installer/blob/master/unpack.py) + [disburse.py](https://github.com/mmod/nk-xrm-installer/blob/master/disburse.py) - .py files above provide complete reference for examples of fetching source via http, extracting, and moving files. - * [node-memwatch](https://github.com/lloyd/node-memwatch/blob/master/binding.gyp) - * [node-ip2location](https://github.com/bolgovr/node-ip2location/blob/master/binding.gyp) - * [node-midi](https://github.com/justinlatimer/node-midi/blob/master/binding.gyp) - * [node-sqlite3](https://github.com/developmentseed/node-sqlite3/blob/master/binding.gyp) + [libsqlite3](https://github.com/developmentseed/node-sqlite3/blob/master/deps/sqlite3.gyp) - * [node-zipfile](https://github.com/mapbox/node-zipfile/blob/master/binding.gyp) - * [node-mapnik](https://github.com/mapnik/node-mapnik/blob/master/binding.gyp) - * [node-inotify](https://github.com/c4milo/node-inotify/blob/master/binding.gyp) - * [v8-profiler](https://github.com/c4milo/v8-profiler/blob/master/binding.gyp) - * [airtunes](https://github.com/radioline/node_airtunes/blob/master/binding.gyp) - * [node-fann](https://github.com/c4milo/node-fann/blob/master/binding.gyp) - * [node-talib](https://github.com/oransel/node-talib/blob/master/binding.gyp) - * [node-leveldown](https://github.com/rvagg/node-leveldown/blob/master/binding.gyp) + [leveldb.gyp](https://github.com/rvagg/node-leveldown/blob/master/deps/leveldb/leveldb.gyp) + [snappy.gyp](https://github.com/rvagg/node-leveldown/blob/master/deps/snappy/snappy.gyp) - * [node-expat](https://github.com/astro/node-expat/blob/master/binding.gyp) + [libexpat](https://github.com/astro/node-expat/blob/master/deps/libexpat/libexpat.gyp) - * [node-openvg-canvas](https://github.com/luismreis/node-openvg-canvas/blob/master/binding.gyp) + [node-openvg](https://github.com/luismreis/node-openvg/blob/master/binding.gyp) - * [node-cryptopp](https://github.com/BatikhSouri/node-cryptopp/blob/master/binding.gyp) - * [topcube](https://github.com/creationix/topcube/blob/master/binding.gyp) - * [node-osmium](https://github.com/osmcode/node-osmium/blob/master/binding.gyp) - * [node-osrm](https://github.com/DennisOSRM/node-osrm) - * [node-oracle](https://github.com/joeferner/node-oracle/blob/master/binding.gyp) - * [node-process-list](https://github.com/ReklatsMasters/node-process-list/blob/master/binding.gyp) - * [node-nanomsg](https://github.com/nickdesaulniers/node-nanomsg/blob/master/binding.gyp) - * [Ghostscript4JS](https://github.com/NickNaso/ghostscript4js/blob/master/binding.gyp) - * [nodecv](https://github.com/xudafeng/nodecv/blob/master/binding.gyp) - * [magick-cli](https://github.com/NickNaso/magick-cli/blob/master/binding.gyp) - * [sharp](https://github.com/lovell/sharp/blob/master/binding.gyp) - * [krb5](https://github.com/adaltas/node-krb5/blob/master/binding.gyp) - * [node-heapdump](https://github.com/bnoordhuis/node-heapdump/blob/master/binding.gyp) diff --git a/deps/npm/node_modules/node-gyp/gyp/.flake8 b/deps/npm/node_modules/node-gyp/gyp/.flake8 deleted file mode 100644 index ea0c7680ef87b2..00000000000000 --- a/deps/npm/node_modules/node-gyp/gyp/.flake8 +++ /dev/null @@ -1,4 +0,0 @@ -[flake8] -max-complexity = 101 -max-line-length = 88 -extend-ignore = E203 # whitespace before ':' to agree with psf/black diff --git a/deps/npm/node_modules/node-gyp/gyp/.github/workflows/Python_tests.yml b/deps/npm/node_modules/node-gyp/gyp/.github/workflows/Python_tests.yml deleted file mode 100644 index aad135027ce8fc..00000000000000 --- a/deps/npm/node_modules/node-gyp/gyp/.github/workflows/Python_tests.yml +++ /dev/null @@ -1,36 +0,0 @@ -# TODO: Enable os: windows-latest -# TODO: Enable pytest --doctest-modules - -name: Python_tests -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - workflow_dispatch: -jobs: - Python_tests: - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - max-parallel: 8 - matrix: - os: [macos-latest, ubuntu-latest] # , windows-latest] - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11-dev"] - steps: - - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip setuptools - pip install --editable ".[dev]" - - run: ./gyp -V && ./gyp --version && gyp -V && gyp --version - - name: Lint with flake8 - run: flake8 . --ignore=E203,W503 --max-complexity=101 --max-line-length=88 --show-source --statistics - - name: Test with pytest - run: pytest - # - name: Run doctests with pytest - # run: pytest --doctest-modules diff --git a/deps/npm/node_modules/node-gyp/gyp/.github/workflows/node-gyp.yml b/deps/npm/node_modules/node-gyp/gyp/.github/workflows/node-gyp.yml deleted file mode 100644 index 7cc1f9e0754365..00000000000000 --- a/deps/npm/node_modules/node-gyp/gyp/.github/workflows/node-gyp.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: node-gyp integration -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - workflow_dispatch: -jobs: - integration: - strategy: - fail-fast: false - matrix: - os: [macos-latest, ubuntu-latest, windows-latest] - python: ["3.7", "3.10"] - - runs-on: ${{ matrix.os }} - steps: - - name: Clone gyp-next - uses: actions/checkout@v3 - with: - path: gyp-next - - name: Clone nodejs/node-gyp - uses: actions/checkout@v3 - with: - repository: nodejs/node-gyp - path: node-gyp - - uses: actions/setup-node@v3 - with: - node-version: 14.x - - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python }} - - name: Install dependencies - run: | - cd node-gyp - npm install --no-progress - - name: Replace gyp in node-gyp - shell: bash - run: | - rm -rf node-gyp/gyp - cp -r gyp-next node-gyp/gyp - - name: Run tests - run: | - cd node-gyp - npm test diff --git a/deps/npm/node_modules/node-gyp/gyp/.github/workflows/nodejs-windows.yml b/deps/npm/node_modules/node-gyp/gyp/.github/workflows/nodejs-windows.yml deleted file mode 100644 index 4e6c9548ff5c59..00000000000000 --- a/deps/npm/node_modules/node-gyp/gyp/.github/workflows/nodejs-windows.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Node.js Windows integration - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - workflow_dispatch: - -jobs: - build-windows: - runs-on: windows-2019 - steps: - - name: Clone gyp-next - uses: actions/checkout@v3 - with: - path: gyp-next - - name: Clone nodejs/node - uses: actions/checkout@v3 - with: - repository: nodejs/node - path: node - - name: Install deps - run: choco install nasm - - name: Replace gyp in Node.js - run: | - rm -Recurse node/tools/gyp - cp -Recurse gyp-next node/tools/gyp - - name: Build Node.js - run: | - cd node - ./vcbuild.bat diff --git a/deps/npm/node_modules/node-gyp/gyp/.github/workflows/release-please.yml b/deps/npm/node_modules/node-gyp/gyp/.github/workflows/release-please.yml deleted file mode 100644 index 665c4c48fed210..00000000000000 --- a/deps/npm/node_modules/node-gyp/gyp/.github/workflows/release-please.yml +++ /dev/null @@ -1,16 +0,0 @@ -on: - push: - branches: - - main - -name: release-please -jobs: - release-please: - runs-on: ubuntu-latest - steps: - - uses: google-github-actions/release-please-action@v3 - with: - token: ${{ secrets.GITHUB_TOKEN }} - release-type: python - package-name: gyp-next - bump-minor-pre-major: true diff --git a/deps/npm/node_modules/node-gyp/gyp/AUTHORS b/deps/npm/node_modules/node-gyp/gyp/AUTHORS deleted file mode 100644 index f49a357b9ed104..00000000000000 --- a/deps/npm/node_modules/node-gyp/gyp/AUTHORS +++ /dev/null @@ -1,16 +0,0 @@ -# Names should be added to this file like so: -# Name or Organization - -Google Inc. <*@google.com> -Bloomberg Finance L.P. <*@bloomberg.net> -IBM Inc. <*@*.ibm.com> -Yandex LLC <*@yandex-team.ru> - -Steven Knight -Ryan Norton -David J. Sankel -Eric N. Vander Weele -Tom Freudenberg -Julien Brianceau -Refael Ackermann -Ujjwal Sharma diff --git a/deps/npm/node_modules/node-gyp/gyp/CHANGELOG.md b/deps/npm/node_modules/node-gyp/gyp/CHANGELOG.md deleted file mode 100644 index 4b4968f6a4ca8e..00000000000000 --- a/deps/npm/node_modules/node-gyp/gyp/CHANGELOG.md +++ /dev/null @@ -1,233 +0,0 @@ -# Changelog - -## [0.14.0](https://github.com/nodejs/gyp-next/compare/v0.13.0...v0.14.0) (2022-10-08) - - -### Features - -* Add command line argument for `gyp --version` ([#164](https://github.com/nodejs/gyp-next/issues/164)) ([5c9f4d0](https://github.com/nodejs/gyp-next/commit/5c9f4d05678dd855e18ed2327219e5d18e5374db)) -* ninja build for iOS ([#174](https://github.com/nodejs/gyp-next/issues/174)) ([b6f2714](https://github.com/nodejs/gyp-next/commit/b6f271424e0033d7ed54d437706695af2ba7a1bf)) -* **zos:** support IBM Open XL C/C++ & PL/I compilers on z/OS ([#178](https://github.com/nodejs/gyp-next/issues/178)) ([43a7211](https://github.com/nodejs/gyp-next/commit/43a72110ae3fafb13c9625cc7a969624b27cda47)) - - -### Bug Fixes - -* lock windows env ([#163](https://github.com/nodejs/gyp-next/issues/163)) ([44bd0dd](https://github.com/nodejs/gyp-next/commit/44bd0ddc93ea0b5770a44dd326a2e4ae62c21442)) -* move configuration information into pyproject.toml ([#176](https://github.com/nodejs/gyp-next/issues/176)) ([d69d8ec](https://github.com/nodejs/gyp-next/commit/d69d8ece6dbff7af4f2ea073c9fd170baf8cb7f7)) -* node.js debugger adds stderr (but exit code is 0) -> shouldn't throw ([#179](https://github.com/nodejs/gyp-next/issues/179)) ([1a457d9](https://github.com/nodejs/gyp-next/commit/1a457d9ed08cfd30c9fa551bc5cf0d90fb583787)) - -## [0.13.0](https://www.github.com/nodejs/gyp-next/compare/v0.12.1...v0.13.0) (2022-05-11) - - -### Features - -* add PRODUCT_DIR_ABS variable ([#151](https://www.github.com/nodejs/gyp-next/issues/151)) ([80d2626](https://www.github.com/nodejs/gyp-next/commit/80d26263581db829b61b312a7bdb5cc791df7824)) - - -### Bug Fixes - -* execvp: printf: Argument list too long ([#147](https://www.github.com/nodejs/gyp-next/issues/147)) ([c4e14f3](https://www.github.com/nodejs/gyp-next/commit/c4e14f301673fadbac3ab7882d0b5f4d02530cb9)) - -### [0.12.1](https://www.github.com/nodejs/gyp-next/compare/v0.12.0...v0.12.1) (2022-04-06) - - -### Bug Fixes - -* **msvs:** avoid fixing path for arguments with "=" ([#143](https://www.github.com/nodejs/gyp-next/issues/143)) ([7e8f16e](https://www.github.com/nodejs/gyp-next/commit/7e8f16eb165e042e64bec98fa6c2a0232a42c26b)) - -## [0.12.0](https://www.github.com/nodejs/gyp-next/compare/v0.11.0...v0.12.0) (2022-04-04) - - -### Features - -* support building shared libraries on z/OS ([#137](https://www.github.com/nodejs/gyp-next/issues/137)) ([293bcfa](https://www.github.com/nodejs/gyp-next/commit/293bcfa4c25c6adb743377adafc45a80fee492c6)) - -## [0.11.0](https://www.github.com/nodejs/gyp-next/compare/v0.10.1...v0.11.0) (2022-03-04) - - -### Features - -* Add proper support for IBM i ([#140](https://www.github.com/nodejs/gyp-next/issues/140)) ([fdda4a3](https://www.github.com/nodejs/gyp-next/commit/fdda4a3038b8a7042ad960ce7a223687c24a21b1)) - -### [0.10.1](https://www.github.com/nodejs/gyp-next/compare/v0.10.0...v0.10.1) (2021-11-24) - - -### Bug Fixes - -* **make:** only generate makefile for multiple toolsets if requested ([#133](https://www.github.com/nodejs/gyp-next/issues/133)) ([f463a77](https://www.github.com/nodejs/gyp-next/commit/f463a77705973289ea38fec1b244c922ac438e26)) - -## [0.10.0](https://www.github.com/nodejs/gyp-next/compare/v0.9.6...v0.10.0) (2021-08-26) - - -### Features - -* **msvs:** add support for Visual Studio 2022 ([#124](https://www.github.com/nodejs/gyp-next/issues/124)) ([4bd9215](https://www.github.com/nodejs/gyp-next/commit/4bd9215c44d300f06e916aec1d6327c22b78272d)) - -### [0.9.6](https://www.github.com/nodejs/gyp-next/compare/v0.9.5...v0.9.6) (2021-08-23) - - -### Bug Fixes - -* align flake8 test ([#122](https://www.github.com/nodejs/gyp-next/issues/122)) ([f1faa8d](https://www.github.com/nodejs/gyp-next/commit/f1faa8d3081e1a47e917ff910892f00dff16cf8a)) -* **msvs:** fix paths again in action command arguments ([#121](https://www.github.com/nodejs/gyp-next/issues/121)) ([7159dfb](https://www.github.com/nodejs/gyp-next/commit/7159dfbc5758c9ec717e215f2c36daf482c846a1)) - -### [0.9.5](https://www.github.com/nodejs/gyp-next/compare/v0.9.4...v0.9.5) (2021-08-18) - - -### Bug Fixes - -* add python 3.6 to node-gyp integration test ([3462d4c](https://www.github.com/nodejs/gyp-next/commit/3462d4ce3c31cce747513dc7ca9760c81d57c60e)) -* revert for windows compatibility ([d078e7d](https://www.github.com/nodejs/gyp-next/commit/d078e7d7ae080ddae243188f6415f940376a7368)) -* support msvs_quote_cmd in ninja generator ([#117](https://www.github.com/nodejs/gyp-next/issues/117)) ([46486ac](https://www.github.com/nodejs/gyp-next/commit/46486ac6e9329529d51061e006a5b39631e46729)) - -### [0.9.4](https://www.github.com/nodejs/gyp-next/compare/v0.9.3...v0.9.4) (2021-08-09) - - -### Bug Fixes - -* .S is an extension for asm file on Windows ([#115](https://www.github.com/nodejs/gyp-next/issues/115)) ([d2fad44](https://www.github.com/nodejs/gyp-next/commit/d2fad44ef3a79ca8900f1307060153ded57053fc)) - -### [0.9.3](https://www.github.com/nodejs/gyp-next/compare/v0.9.2...v0.9.3) (2021-07-07) - - -### Bug Fixes - -* build failure with ninja and Python 3 on Windows ([#113](https://www.github.com/nodejs/gyp-next/issues/113)) ([c172d10](https://www.github.com/nodejs/gyp-next/commit/c172d105deff5db4244e583942215918fa80dd3c)) - -### [0.9.2](https://www.github.com/nodejs/gyp-next/compare/v0.9.1...v0.9.2) (2021-05-21) - - -### Bug Fixes - -* add support of utf8 encoding ([#105](https://www.github.com/nodejs/gyp-next/issues/105)) ([4d0f93c](https://www.github.com/nodejs/gyp-next/commit/4d0f93c249286d1f0c0f665f5fe7346119f98cf1)) - -### [0.9.1](https://www.github.com/nodejs/gyp-next/compare/v0.9.0...v0.9.1) (2021-05-14) - - -### Bug Fixes - -* py lint ([3b6a8ee](https://www.github.com/nodejs/gyp-next/commit/3b6a8ee7a66193a8a6867eba9e1d2b70bdf04402)) - -## [0.9.0](https://www.github.com/nodejs/gyp-next/compare/v0.8.1...v0.9.0) (2021-05-13) - - -### Features - -* use LDFLAGS_host for host toolset ([#98](https://www.github.com/nodejs/gyp-next/issues/98)) ([bea5c7b](https://www.github.com/nodejs/gyp-next/commit/bea5c7bd67d6ad32acbdce79767a5481c70675a2)) - - -### Bug Fixes - -* msvs.py: remove overindentation ([#102](https://www.github.com/nodejs/gyp-next/issues/102)) ([3f83e99](https://www.github.com/nodejs/gyp-next/commit/3f83e99056d004d9579ceb786e06b624ddc36529)) -* update gyp.el to change case to cl-case ([#93](https://www.github.com/nodejs/gyp-next/issues/93)) ([13d5b66](https://www.github.com/nodejs/gyp-next/commit/13d5b66aab35985af9c2fb1174fdc6e1c1407ecc)) - -### [0.8.1](https://www.github.com/nodejs/gyp-next/compare/v0.8.0...v0.8.1) (2021-02-18) - - -### Bug Fixes - -* update shebang lines from python to python3 ([#94](https://www.github.com/nodejs/gyp-next/issues/94)) ([a1b0d41](https://www.github.com/nodejs/gyp-next/commit/a1b0d4171a8049a4ab7a614202063dec332f2df4)) - -## [0.8.0](https://www.github.com/nodejs/gyp-next/compare/v0.7.0...v0.8.0) (2021-01-15) - - -### ⚠ BREAKING CHANGES - -* remove support for Python 2 - -### Bug Fixes - -* revert posix build job ([#86](https://www.github.com/nodejs/gyp-next/issues/86)) ([39dc34f](https://www.github.com/nodejs/gyp-next/commit/39dc34f0799c074624005fb9bbccf6e028607f9d)) - - -### gyp - -* Remove support for Python 2 ([#88](https://www.github.com/nodejs/gyp-next/issues/88)) ([22e4654](https://www.github.com/nodejs/gyp-next/commit/22e465426fd892403c95534229af819a99c3f8dc)) - -## [0.7.0](https://www.github.com/nodejs/gyp-next/compare/v0.6.2...v0.7.0) (2020-12-17) - - -### ⚠ BREAKING CHANGES - -* **msvs:** On Windows, arguments passed to the "action" commands are no longer transformed to replace slashes with backslashes. - -### Features - -* **xcode:** --cross-compiling overrides arch-specific settings ([973bae0](https://www.github.com/nodejs/gyp-next/commit/973bae0b7b08be7b680ecae9565fbd04b3e0787d)) - - -### Bug Fixes - -* **msvs:** do not fix paths in action command arguments ([fc22f83](https://www.github.com/nodejs/gyp-next/commit/fc22f8335e2016da4aae4f4233074bd651d2faea)) -* cmake on python 3 ([fd61f5f](https://www.github.com/nodejs/gyp-next/commit/fd61f5faa5275ec8fc98e3c7868c0dd46f109540)) -* ValueError: invalid mode: 'rU' while trying to load binding.gyp ([d0504e6](https://www.github.com/nodejs/gyp-next/commit/d0504e6700ce48f44957a4d5891b142a60be946f)) -* xcode cmake parsing ([eefe8d1](https://www.github.com/nodejs/gyp-next/commit/eefe8d10e99863bc4ac7e2ed32facd608d400d4b)) - -### [0.6.2](https://www.github.com/nodejs/gyp-next/compare/v0.6.1...v0.6.2) (2020-10-16) - - -### Bug Fixes - -* do not rewrite absolute paths to avoid long paths ([#74](https://www.github.com/nodejs/gyp-next/issues/74)) ([c2ccc1a](https://www.github.com/nodejs/gyp-next/commit/c2ccc1a81f7f94433a94f4d01a2e820db4c4331a)) -* only include MARMASM when toolset is target ([5a2794a](https://www.github.com/nodejs/gyp-next/commit/5a2794aefb58f0c00404ff042b61740bc8b8d5cd)) - -### [0.6.1](https://github.com/nodejs/gyp-next/compare/v0.6.0...v0.6.1) (2020-10-14) - - -### Bug Fixes - -* Correctly rename object files for absolute paths in MSVS generator. - -## [0.6.0](https://github.com/nodejs/gyp-next/compare/v0.5.0...v0.6.0) (2020-10-13) - - -### Features - -* The Makefile generator will now output shared libraries directly to the product directory on all platforms (previously only macOS). - -## [0.5.0](https://github.com/nodejs/gyp-next/compare/v0.4.0...v0.5.0) (2020-09-30) - - -### Features - -* Extended compile_commands_json generator to consider more file extensions than just `c` and `cc`. `cpp` and `cxx` are now supported. -* Source files with duplicate basenames are now supported. - -### Removed - -* The `--no-duplicate-basename-check` option was removed. -* The `msvs_enable_marmasm` configuration option was removed in favor of auto-inclusion of the "marmasm" sections for Windows on ARM. - -## [0.4.0](https://github.com/nodejs/gyp-next/compare/v0.3.0...v0.4.0) (2020-07-14) - - -### Features - -* Added support for passing arbitrary architectures to Xcode builds, enables `arm64` builds. - -### Bug Fixes - -* Fixed a bug on Solaris where copying archives failed. - -## [0.3.0](https://github.com/nodejs/gyp-next/compare/v0.2.1...v0.3.0) (2020-06-06) - - -### Features - -* Added support for MSVC cross-compilation. This allows compilation on x64 for a Windows ARM target. - -### Bug Fixes - -* Fixed XCode CLT version detection on macOS Catalina. - -### [0.2.1](https://github.com/nodejs/gyp-next/compare/v0.2.0...v0.2.1) (2020-05-05) - - -### Bug Fixes - -* Relicensed to Node.js contributors. -* Fixed Windows bug introduced in v0.2.0. - -## [0.2.0](https://github.com/nodejs/gyp-next/releases/tag/v0.2.0) (2020-04-06) - -This is the first release of this project, based on https://chromium.googlesource.com/external/gyp with changes made over the years in Node.js and node-gyp. diff --git a/deps/npm/node_modules/node-gyp/gyp/CODE_OF_CONDUCT.md b/deps/npm/node_modules/node-gyp/gyp/CODE_OF_CONDUCT.md deleted file mode 100644 index d724027fd9aadb..00000000000000 --- a/deps/npm/node_modules/node-gyp/gyp/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,4 +0,0 @@ -# Code of Conduct - -* [Node.js Code of Conduct](https://github.com/nodejs/admin/blob/HEAD/CODE_OF_CONDUCT.md) -* [Node.js Moderation Policy](https://github.com/nodejs/admin/blob/HEAD/Moderation-Policy.md) diff --git a/deps/npm/node_modules/node-gyp/gyp/CONTRIBUTING.md b/deps/npm/node_modules/node-gyp/gyp/CONTRIBUTING.md deleted file mode 100644 index 1a0bcde2b48d8e..00000000000000 --- a/deps/npm/node_modules/node-gyp/gyp/CONTRIBUTING.md +++ /dev/null @@ -1,32 +0,0 @@ -# Contributing to gyp-next - -## Code of Conduct - -This project is bound to the [Node.js Code of Conduct](https://github.com/nodejs/admin/blob/HEAD/CODE_OF_CONDUCT.md). - - -## Developer's Certificate of Origin 1.1 - -By making a contribution to this project, I certify that: - -* (a) The contribution was created in whole or in part by me and I - have the right to submit it under the open source license - indicated in the file; or - -* (b) The contribution is based upon previous work that, to the best - of my knowledge, is covered under an appropriate open source - license and I have the right under that license to submit that - work with modifications, whether created in whole or in part - by me, under the same open source license (unless I am - permitted to submit under a different license), as indicated - in the file; or - -* (c) The contribution was provided directly to me by some other - person who certified (a), (b) or (c) and I have not modified - it. - -* (d) I understand and agree that this project and the contribution - are public and that a record of the contribution (including all - personal information I submit with it, including my sign-off) is - maintained indefinitely and may be redistributed consistent with - this project or the open source license(s) involved. diff --git a/deps/npm/node_modules/node-gyp/gyp/README.md b/deps/npm/node_modules/node-gyp/gyp/README.md index 9ffc2b21e81b8b..be1d7b9ebf6611 100644 --- a/deps/npm/node_modules/node-gyp/gyp/README.md +++ b/deps/npm/node_modules/node-gyp/gyp/README.md @@ -5,3 +5,26 @@ Documents are available at [gyp.gsrc.io](https://gyp.gsrc.io), or you can check __gyp-next__ is [released](https://github.com/nodejs/gyp-next/releases) to the [__Python Packaging Index__](https://pypi.org/project/gyp-next) (PyPI) and can be installed with the command: * `python3 -m pip install gyp-next` + +When used as a command line utility, __gyp-next__ can also be installed with [pipx](https://pypa.github.io/pipx): +* `pipx install gyp-next` +``` +Installing to a new venv 'gyp-next' + installed package gyp-next 0.13.0, installed using Python 3.10.6 + These apps are now globally available + - gyp +done! ✨ 🌟 ✨ +``` + +Or to run __gyp-next__ directly without installing it: +* `pipx run gyp-next --help` +``` +NOTE: running app 'gyp' from 'gyp-next' +usage: usage: gyp [options ...] [build_file ...] + +options: + -h, --help show this help message and exit + --build CONFIGS configuration for build after project generation + --check check format of gyp files + [ ... ] +``` diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py index d6b189760cef99..bc0e93d07f8900 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py @@ -285,19 +285,17 @@ def Write(self, writer=gyp.common.WriteOnDiff): "\tEndProjectSection\r\n" ) - if isinstance(e, MSVSFolder): - if e.items: - f.write("\tProjectSection(SolutionItems) = preProject\r\n") - for i in e.items: - f.write(f"\t\t{i} = {i}\r\n") - f.write("\tEndProjectSection\r\n") - - if isinstance(e, MSVSProject): - if e.dependencies: - f.write("\tProjectSection(ProjectDependencies) = postProject\r\n") - for d in e.dependencies: - f.write(f"\t\t{d.get_guid()} = {d.get_guid()}\r\n") - f.write("\tEndProjectSection\r\n") + if isinstance(e, MSVSFolder) and e.items: + f.write("\tProjectSection(SolutionItems) = preProject\r\n") + for i in e.items: + f.write(f"\t\t{i} = {i}\r\n") + f.write("\tEndProjectSection\r\n") + + if isinstance(e, MSVSProject) and e.dependencies: + f.write("\tProjectSection(ProjectDependencies) = postProject\r\n") + for d in e.dependencies: + f.write(f"\t\t{d.get_guid()} = {d.get_guid()}\r\n") + f.write("\tEndProjectSection\r\n") f.write("EndProject\r\n") @@ -353,7 +351,7 @@ def Write(self, writer=gyp.common.WriteOnDiff): # Folder mappings # Omit this section if there are no folders - if any([e.entries for e in all_entries if isinstance(e, MSVSFolder)]): + if any(e.entries for e in all_entries if isinstance(e, MSVSFolder)): f.write("\tGlobalSection(NestedProjects) = preSolution\r\n") for e in all_entries: if not isinstance(e, MSVSFolder): diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py index f0cfabe8349099..629f3f61b4819d 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py @@ -79,7 +79,7 @@ def __init__(self, project_path, version, name, guid=None, platforms=None): self.files_section = ["Files"] # Keep a dict keyed on filename to speed up access. - self.files_dict = dict() + self.files_dict = {} def AddToolFile(self, path): """Adds a tool file to the project. diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py index e89a971a3bb4fd..93633dbca133c7 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py @@ -141,7 +141,7 @@ class _Boolean(_Type): """Boolean settings, can have the values 'false' or 'true'.""" def _Validate(self, value): - if value != "true" and value != "false": + if value not in {"true", "false"}: raise ValueError("expected bool; got %r" % value) def ValidateMSVS(self, value): diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/__init__.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/__init__.py index 2aa39d0318860f..d6cc01307d997c 100755 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/__init__.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/__init__.py @@ -108,7 +108,9 @@ def Load( if default_variables["GENERATOR"] == "ninja": default_variables.setdefault( "PRODUCT_DIR_ABS", - os.path.join(output_dir, "out", default_variables["build_type"]), + os.path.join( + output_dir, "out", default_variables.get("build_type", "default") + ), ) else: default_variables.setdefault( @@ -622,7 +624,7 @@ def gyp_main(args): if options.generator_flags: gen_flags += options.generator_flags generator_flags = NameValueListToDict(gen_flags) - if DEBUG_GENERAL in gyp.debug.keys(): + if DEBUG_GENERAL in gyp.debug: DebugOutput(DEBUG_GENERAL, "generator_flags: %s", generator_flags) # Generate all requested formats (use a set in case we got one format request diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/common.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/common.py index d77adee8afd55d..b73a0c55b1e349 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/common.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/common.py @@ -144,20 +144,16 @@ def RelativePath(path, relative_to, follow_path_symlink=True): # symlink, this option has no effect. # Convert to normalized (and therefore absolute paths). - if follow_path_symlink: - path = os.path.realpath(path) - else: - path = os.path.abspath(path) + path = os.path.realpath(path) if follow_path_symlink else os.path.abspath(path) relative_to = os.path.realpath(relative_to) # On Windows, we can't create a relative path to a different drive, so just # use the absolute path. - if sys.platform == "win32": - if ( - os.path.splitdrive(path)[0].lower() - != os.path.splitdrive(relative_to)[0].lower() - ): - return path + if sys.platform == "win32" and ( + os.path.splitdrive(path)[0].lower() + != os.path.splitdrive(relative_to)[0].lower() + ): + return path # Split the paths into components. path_split = path.split(os.path.sep) @@ -277,10 +273,7 @@ def EncodePOSIXShellArgument(argument): if not isinstance(argument, str): argument = str(argument) - if _quote.search(argument): - quote = '"' - else: - quote = "" + quote = '"' if _quote.search(argument) else "" encoded = quote + re.sub(_escape, r"\\\1", argument) + quote diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py index bda1a47468ae2b..02567b251446d7 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py @@ -121,7 +121,11 @@ def WriteXmlIfChanged(content, path, encoding="utf-8", pretty=False, if win32 and os.linesep != "\r\n": xml_string = xml_string.replace("\n", "\r\n") - default_encoding = locale.getdefaultlocale()[1] + try: # getdefaultlocale() was removed in Python 3.11 + default_encoding = locale.getdefaultlocale()[1] + except AttributeError: + default_encoding = locale.getencoding() + if default_encoding and default_encoding.upper() != encoding.upper(): xml_string = xml_string.encode(encoding) diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py index 342f693a329d26..2d9b15210dc126 100755 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py @@ -76,6 +76,8 @@ def test_EasyXml_complex(self): '\'Debug|Win32\'" Label="Configuration">' "Application" "Unicode" + "SpectreLoadCF" + "14.36.32532" "" "" ) @@ -99,6 +101,8 @@ def test_EasyXml_complex(self): }, ["ConfigurationType", "Application"], ["CharacterSet", "Unicode"], + ["SpectreMitigation", "SpectreLoadCF"], + ["VCToolsVersion", "14.36.32532"], ], ] ) diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py index f15df00c36373e..1334f2fca9967c 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py @@ -379,7 +379,7 @@ def _GenerateTargets(data, target_list, target_dicts, toplevel_dir, files, build target.is_executable = target_type == "executable" target.is_static_library = target_type == "static_library" target.is_or_has_linked_ancestor = ( - target_type == "executable" or target_type == "shared_library" + target_type in {"executable", "shared_library"} ) build_file = gyp.common.ParseQualifiedTarget(target_name)[0] @@ -433,14 +433,14 @@ def _GetUnqualifiedToTargetMapping(all_targets, to_find): if not to_find: return {}, [] to_find = set(to_find) - for target_name in all_targets.keys(): + for target_name in all_targets: extracted = gyp.common.ParseQualifiedTarget(target_name) if len(extracted) > 1 and extracted[1] in to_find: to_find.remove(extracted[1]) result[extracted[1]] = all_targets[target_name] if not to_find: return result, [] - return result, [x for x in to_find] + return result, list(to_find) def _DoesTargetDependOnMatchingTargets(target): @@ -451,8 +451,8 @@ def _DoesTargetDependOnMatchingTargets(target): if target.match_status == MATCH_STATUS_DOESNT_MATCH: return False if ( - target.match_status == MATCH_STATUS_MATCHES - or target.match_status == MATCH_STATUS_MATCHES_BY_DEPENDENCY + target.match_status in {MATCH_STATUS_MATCHES, + MATCH_STATUS_MATCHES_BY_DEPENDENCY} ): return True for dep in target.deps: @@ -683,11 +683,9 @@ def find_matching_test_target_names(self): ) test_target_names_contains_all = "all" in self._test_target_names if test_target_names_contains_all: - test_targets = [ - x for x in (set(test_targets_no_all) | set(self._root_targets)) - ] + test_targets = list(set(test_targets_no_all) | set(self._root_targets)) else: - test_targets = [x for x in test_targets_no_all] + test_targets = list(test_targets_no_all) print("supplied test_targets") for target_name in self._test_target_names: print("\t", target_name) @@ -702,9 +700,9 @@ def find_matching_test_target_names(self): if matching_test_targets_contains_all: # Remove any of the targets for all that were not explicitly supplied, # 'all' is subsequentely added to the matching names below. - matching_test_targets = [ - x for x in (set(matching_test_targets) & set(test_targets_no_all)) - ] + matching_test_targets = list( + set(matching_test_targets) & set(test_targets_no_all) + ) print("matched test_targets") for target in matching_test_targets: print("\t", target.name) @@ -729,9 +727,7 @@ def find_matching_compile_target_names(self): self._supplied_target_names_no_all(), self._unqualified_mapping ) if "all" in self._supplied_target_names(): - supplied_targets = [ - x for x in (set(supplied_targets) | set(self._root_targets)) - ] + supplied_targets = list(set(supplied_targets) | set(self._root_targets)) print("Supplied test_targets & compile_targets") for target in supplied_targets: print("\t", target.name) diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py index cdf1a4832cf1ad..d3c97c666db077 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py @@ -697,7 +697,7 @@ def ComputeOutputParts(self, spec): target, ) - if self.type != "static_library" and self.type != "shared_library": + if self.type not in {"static_library", "shared_library"}: target_prefix = spec.get("product_prefix", target_prefix) target = spec.get("product_name", target) product_ext = spec.get("product_extension") diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py index c95d18415cdb37..320a891aa8adc9 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py @@ -103,7 +103,7 @@ def NormjoinPathForceCMakeSource(base_path, rel_path): """ if os.path.isabs(rel_path): return rel_path - if any([rel_path.startswith(var) for var in FULL_PATH_VARS]): + if any(rel_path.startswith(var) for var in FULL_PATH_VARS): return rel_path # TODO: do we need to check base_path for absolute variables as well? return os.path.join( @@ -328,7 +328,7 @@ def WriteActions(target_name, actions, extra_sources, extra_deps, path_to_gyp, o def NormjoinRulePathForceCMakeSource(base_path, rel_path, rule_source): if rel_path.startswith(("${RULE_INPUT_PATH}", "${RULE_INPUT_DIRNAME}")): - if any([rule_source.startswith(var) for var in FULL_PATH_VARS]): + if any(rule_source.startswith(var) for var in FULL_PATH_VARS): return rel_path return NormjoinPathForceCMakeSource(base_path, rel_path) @@ -929,10 +929,7 @@ def WriteTarget( product_prefix = spec.get("product_prefix", default_product_prefix) product_name = spec.get("product_name", default_product_name) product_ext = spec.get("product_extension") - if product_ext: - product_ext = "." + product_ext - else: - product_ext = default_product_ext + product_ext = "." + product_ext if product_ext else default_product_ext SetTargetProperty(output, cmake_target_name, "PREFIX", product_prefix) SetTargetProperty( diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/compile_commands_json.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/compile_commands_json.py index f330a04dea4c53..0ffa3bb5980fe9 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/compile_commands_json.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/compile_commands_json.py @@ -34,7 +34,7 @@ def IsMac(params): - return "mac" == gyp.common.GetFlavor(params) + return gyp.common.GetFlavor(params) == "mac" def CalculateVariables(default_variables, params): @@ -93,7 +93,7 @@ def resolve(filename): gyp.common.EncodePOSIXShellArgument(file), ) ) - commands.append(dict(command=command, directory=output_dir, file=file)) + commands.append({"command": command, "directory": output_dir, "file": file}) def GenerateOutput(target_list, target_dicts, data, params): @@ -108,7 +108,10 @@ def GenerateOutput(target_list, target_dicts, data, params): cwd = os.path.dirname(build_file) AddCommandsForTarget(cwd, target, params, per_config_commands) - output_dir = params["generator_flags"].get("output_dir", "out") + try: + output_dir = params["options"].generator_output + except (AttributeError, KeyError): + output_dir = params["generator_flags"].get("output_dir", "out") for configuration_name, commands in per_config_commands.items(): filename = os.path.join(output_dir, configuration_name, "compile_commands.json") gyp.common.EnsureDirExists(filename) diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py index a851b4db757eda..52aeae6050990b 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py @@ -248,10 +248,7 @@ def GetAllDefines(target_list, target_dicts, data, config_name, params, compiler continue cpp_line_parts = cpp_line.split(" ", 2) key = cpp_line_parts[1] - if len(cpp_line_parts) >= 3: - val = cpp_line_parts[2] - else: - val = "1" + val = cpp_line_parts[2] if len(cpp_line_parts) >= 3 else "1" all_defines[key] = val return all_defines diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py index f1d01a629d435f..1b9974948e4de5 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py @@ -681,10 +681,7 @@ def WriteRootHeaderSuffixRules(writer): def Compilable(filename): """Return true if the file is compilable (should be in OBJS).""" - for res in (filename.endswith(e) for e in COMPILABLE_EXTENSIONS): - if res: - return True - return False + return any(res for res in (filename.endswith(e) for e in COMPILABLE_EXTENSIONS)) def Linkable(filename): @@ -778,7 +775,7 @@ def __init__(self, generator_flags, flavor): self.suffix_rules_objdir2 = {} # Generate suffix rules for all compilable extensions. - for ext in COMPILABLE_EXTENSIONS.keys(): + for ext in COMPILABLE_EXTENSIONS: # Suffix rules for source folder. self.suffix_rules_srcdir.update( { @@ -1066,7 +1063,7 @@ def WriteActions( # libraries, but until everything is made cross-compile safe, also use # target libraries. # TODO(piman): when everything is cross-compile safe, remove lib.target - if self.flavor == "zos" or self.flavor == "aix": + if self.flavor in {"zos", "aix"}: self.WriteLn( "cmd_%s = LIBPATH=$(builddir)/lib.host:" "$(builddir)/lib.target:$$LIBPATH; " @@ -1992,10 +1989,7 @@ def WriteTarget( and self.toolset == "target" ): # On mac, products are created in install_path immediately. - assert install_path == self.output, "{} != {}".format( - install_path, - self.output, - ) + assert install_path == self.output, f"{install_path} != {self.output}" # Point the target alias to the final binary output. self.WriteMakeRule( @@ -2034,7 +2028,7 @@ def WriteTarget( installable_deps.append( self.GetUnversionedSidedeckFromSidedeck(install_path) ) - if self.output != self.alias and self.alias != self.target: + if self.alias not in (self.output, self.target): self.WriteMakeRule( [self.alias], installable_deps, diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py index fd950057847980..13b0794b4dccc3 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py @@ -164,7 +164,7 @@ def _FixPath(path, separator="\\"): fixpath_prefix and path and not os.path.isabs(path) - and not path[0] == "$" + and path[0] != "$" and not _IsWindowsAbsPath(path) ): path = os.path.join(fixpath_prefix, path) @@ -281,9 +281,9 @@ def _ToolSetOrAppend(tools, tool_name, setting, value, only_if_unset=False): else: value = [i.replace("/", "\\") for i in value] if not tools.get(tool_name): - tools[tool_name] = dict() + tools[tool_name] = {} tool = tools[tool_name] - if "CompileAsWinRT" == setting: + if setting == "CompileAsWinRT": return if tool.get(setting): if only_if_unset: @@ -412,10 +412,7 @@ def _BuildCommandLineForRuleRaw( return input_dir_preamble + cmd else: # Convert cat --> type to mimic unix. - if cmd[0] == "cat": - command = ["type"] - else: - command = [cmd[0].replace("/", "\\")] + command = ["type"] if cmd[0] == "cat" else [cmd[0].replace("/", "\\")] # Add call before command to ensure that commands can be tied together one # after the other without aborting in Incredibuild, since IB makes a bat # file out of the raw command string, and some commands (like python) are @@ -438,6 +435,7 @@ def _BuildCommandLineForRuleRaw( # Support a mode for using cmd directly. # Convert any paths to native form (first element is used directly). # TODO(quote): regularize quoting path names throughout the module + command[1] = '"%s"' % command[1] arguments = ['"%s"' % i for i in arguments] # Collapse into a single command. return input_dir_preamble + " ".join(command + arguments) @@ -687,7 +685,7 @@ def _GenerateExternalRules(rules, output_dir, spec, sources, options, actions_to all_outputs.update(OrderedSet(outputs)) # Only use one target from each rule as the dependency for # 'all' so we don't try to build each rule multiple times. - first_outputs.append(list(outputs)[0]) + first_outputs.append(next(iter(outputs))) # Get the unique output directories for this rule. output_dirs = [os.path.split(i)[0] for i in outputs] for od in output_dirs: @@ -756,7 +754,7 @@ def _EscapeEnvironmentVariableExpansion(s): Returns: The escaped string. - """ # noqa: E731,E123,E501 + """ s = s.replace("%", "%%") return s @@ -1189,7 +1187,7 @@ def _AddConfigurationToMSVSProject(p, spec, config_type, config_name, config): precompiled_header = config.get("msvs_precompiled_header") # Prepare the list of tools as a dictionary. - tools = dict() + tools = {} # Add in user specified msvs_settings. msvs_settings = config.get("msvs_settings", {}) MSVSSettings.ValidateMSVSSettings(msvs_settings) @@ -1384,10 +1382,7 @@ def _GetDefines(config): """ defines = [] for d in config.get("defines", []): - if type(d) == list: - fd = "=".join([str(dpart) for dpart in d]) - else: - fd = str(d) + fd = "=".join([str(dpart) for dpart in d]) if isinstance(d, list) else str(d) defines.append(fd) return defines @@ -1578,10 +1573,10 @@ def _AdjustSourcesAndConvertToFilterHierarchy( # such as ../../src/modules/module1 etc. if version.UsesVcxproj(): while ( - all([isinstance(s, MSVSProject.Filter) for s in sources]) + all(isinstance(s, MSVSProject.Filter) for s in sources) and len({s.name for s in sources}) == 1 ): - assert all([len(s.contents) == 1 for s in sources]) + assert all(len(s.contents) == 1 for s in sources) sources = [s.contents[0] for s in sources] else: while len(sources) == 1 and isinstance(sources[0], MSVSProject.Filter): @@ -1598,10 +1593,7 @@ def _IdlFilesHandledNonNatively(spec, sources): if rule["extension"] == "idl" and int(rule.get("msvs_external_rule", 0)): using_idl = True break - if using_idl: - excluded_idl = [i for i in sources if i.endswith(".idl")] - else: - excluded_idl = [] + excluded_idl = [i for i in sources if i.endswith(".idl")] if using_idl else [] return excluded_idl @@ -1819,7 +1811,7 @@ def _GetPathDict(root, path): parent, folder = os.path.split(path) parent_dict = _GetPathDict(root, parent) if folder not in parent_dict: - parent_dict[folder] = dict() + parent_dict[folder] = {} return parent_dict[folder] @@ -3013,18 +3005,26 @@ def _GetMSBuildConfigurationDetails(spec, build_file): msbuild_attributes = _GetMSBuildAttributes(spec, settings, build_file) condition = _GetConfigurationCondition(name, settings, spec) character_set = msbuild_attributes.get("CharacterSet") + vctools_version = msbuild_attributes.get("VCToolsVersion") config_type = msbuild_attributes.get("ConfigurationType") _AddConditionalProperty(properties, condition, "ConfigurationType", config_type) + spectre_mitigation = msbuild_attributes.get('SpectreMitigation') + if spectre_mitigation: + _AddConditionalProperty(properties, condition, "SpectreMitigation", + spectre_mitigation) if config_type == "Driver": _AddConditionalProperty(properties, condition, "DriverType", "WDM") _AddConditionalProperty( properties, condition, "TargetVersion", _ConfigTargetVersion(settings) ) - if character_set: - if "msvs_enable_winrt" not in spec: - _AddConditionalProperty( - properties, condition, "CharacterSet", character_set - ) + if character_set and "msvs_enable_winrt" not in spec: + _AddConditionalProperty( + properties, condition, "CharacterSet", character_set + ) + if vctools_version and "msvs_enable_winrt" not in spec: + _AddConditionalProperty( + properties, condition, "VCToolsVersion", vctools_version + ) return _GetMSBuildPropertyGroup(spec, "Configuration", properties) @@ -3104,6 +3104,10 @@ def _ConvertMSVSBuildAttributes(spec, config, build_file): msbuild_attributes[a] = _ConvertMSVSCharacterSet(msvs_attributes[a]) elif a == "ConfigurationType": msbuild_attributes[a] = _ConvertMSVSConfigurationType(msvs_attributes[a]) + elif a == "SpectreMitigation": + msbuild_attributes[a] = msvs_attributes[a] + elif a == "VCToolsVersion": + msbuild_attributes[a] = msvs_attributes[a] else: print("Warning: Do not know how to convert MSVS attribute " + a) return msbuild_attributes @@ -3326,15 +3330,14 @@ def _GetMSBuildToolSettingsSections(spec, configurations): for tool_name, tool_settings in sorted(msbuild_settings.items()): # Skip the tool named '' which is a holder of global settings handled # by _GetMSBuildConfigurationGlobalProperties. - if tool_name: - if tool_settings: - tool = [tool_name] - for name, value in sorted(tool_settings.items()): - formatted_value = _GetValueFormattedForMSBuild( - tool_name, name, value - ) - tool.append([name, formatted_value]) - group.append(tool) + if tool_name and tool_settings: + tool = [tool_name] + for name, value in sorted(tool_settings.items()): + formatted_value = _GetValueFormattedForMSBuild( + tool_name, name, value + ) + tool.append([name, formatted_value]) + group.append(tool) groups.append(group) return groups @@ -3462,10 +3465,7 @@ def _GetValueFormattedForMSBuild(tool_name, name, value): "Link": ["AdditionalOptions"], "Lib": ["AdditionalOptions"], } - if tool_name in exceptions and name in exceptions[tool_name]: - char = " " - else: - char = ";" + char = " " if name in exceptions.get(tool_name, []) else ";" formatted_value = char.join( [MSVSSettings.ConvertVCMacrosToMSBuild(i) for i in value] ) diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py index ca04ee13a1c1bf..8ba341e96d3f0d 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py @@ -1815,10 +1815,7 @@ def ComputeOutputFileName(self, spec, type=None): "executable": default_variables["EXECUTABLE_SUFFIX"], } extension = spec.get("product_extension") - if extension: - extension = "." + extension - else: - extension = DEFAULT_EXTENSION.get(type, "") + extension = "." + extension if extension else DEFAULT_EXTENSION.get(type, "") if "product_name" in spec: # If we were given an explicit name, use that. @@ -2533,7 +2530,7 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, config_name description="SOLINK $lib", restat=True, command=mtime_preserving_solink_base - % {"suffix": "@$link_file_list"}, # noqa: E501 + % {"suffix": "@$link_file_list"}, rspfile="$link_file_list", rspfile_content=( "-Wl,--whole-archive $in $solibs -Wl," "--no-whole-archive $libs" diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py index 2f4d17e514e439..1ac672c3876bd9 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py @@ -439,7 +439,7 @@ def Finalize2(self, xcode_targets, xcode_target_to_target_dict): # it opens the project file, which will result in unnecessary diffs. # TODO(mark): This is evil because it relies on internal knowledge of # PBXProject._other_pbxprojects. - for other_pbxproject in self.project._other_pbxprojects.keys(): + for other_pbxproject in self.project._other_pbxprojects: self.project.AddOrGetProjectReference(other_pbxproject) self.project.SortRemoteProductReferences() @@ -1118,10 +1118,7 @@ def GenerateOutput(target_list, target_dicts, data, params): for concrete_output_index, concrete_output in enumerate( concrete_outputs ): - if concrete_output_index == 0: - bol = "" - else: - bol = " " + bol = "" if concrete_output_index == 0 else " " makefile.write(f"{bol}{concrete_output} \\\n") concrete_output_dir = posixpath.dirname(concrete_output) diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/input.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/input.py index d9699a0a502183..8f39519dee51fb 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/input.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/input.py @@ -16,9 +16,9 @@ import sys import threading import traceback -from distutils.version import StrictVersion from gyp.common import GypError from gyp.common import OrderedSet +from packaging.version import Version # A list of types that are treated as linkable. linkable_types = [ @@ -225,7 +225,7 @@ def LoadOneBuildFile(build_file_path, data, aux_data, includes, is_target, check return data[build_file_path] if os.path.exists(build_file_path): - build_file_contents = open(build_file_path, encoding='utf-8').read() + build_file_contents = open(build_file_path, encoding="utf-8").read() else: raise GypError(f"{build_file_path} not found (cwd: {os.getcwd()})") @@ -870,10 +870,7 @@ def ExpandVariables(input, phase, variables, build_file): # This works around actions/rules which have more inputs than will # fit on the command line. if file_list: - if type(contents) is list: - contents_list = contents - else: - contents_list = contents.split(" ") + contents_list = contents if type(contents) is list else contents.split(" ") replacement = contents_list[0] if os.path.isabs(replacement): raise GypError('| cannot handle absolute paths, got "%s"' % replacement) @@ -1183,7 +1180,7 @@ def EvalSingleCondition(cond_expr, true_dict, false_dict, phase, variables, buil else: ast_code = compile(cond_expr_expanded, "", "eval") cached_conditions_asts[cond_expr_expanded] = ast_code - env = {"__builtins__": {}, "v": StrictVersion} + env = {"__builtins__": {}, "v": Version} if eval(ast_code, env, variables): return true_dict return false_dict @@ -1579,14 +1576,12 @@ def ExpandWildcardDependencies(targets, data): continue dependency_target_name = dependency_target_dict["target_name"] if ( - dependency_target != "*" - and dependency_target != dependency_target_name + dependency_target not in {"*", dependency_target_name} ): continue dependency_target_toolset = dependency_target_dict["toolset"] if ( - dependency_toolset != "*" - and dependency_toolset != dependency_target_toolset + dependency_toolset not in {"*", dependency_target_toolset} ): continue dependency = gyp.common.QualifiedTarget( @@ -1630,15 +1625,14 @@ def RemoveSelfDependencies(targets): dependencies = target_dict.get(dependency_key, []) if dependencies: for t in dependencies: - if t == target_name: - if ( - targets[t] - .get("variables", {}) - .get("prune_self_dependency", 0) - ): - target_dict[dependency_key] = Filter( - dependencies, target_name - ) + if t == target_name and ( + targets[t] + .get("variables", {}) + .get("prune_self_dependency", 0) + ): + target_dict[dependency_key] = Filter( + dependencies, target_name + ) def RemoveLinkDependenciesFromNoneTargets(targets): @@ -2238,10 +2232,7 @@ def is_in_set_or_list(x, s, items): singleton = False if type(item) in (str, int): # The cheap and easy case. - if is_paths: - to_item = MakePathRelative(to_file, fro_file, item) - else: - to_item = item + to_item = MakePathRelative(to_file, fro_file, item) if is_paths else item if not (type(item) is str and item.startswith("-")): # Any string that doesn't begin with a "-" is a singleton - it can @@ -2467,10 +2458,7 @@ def SetUpConfigurations(target, target_dict): new_configuration_dict = {} for (key, target_val) in target_dict.items(): key_ext = key[-1:] - if key_ext in key_suffixes: - key_base = key[:-1] - else: - key_base = key + key_base = key[:-1] if key_ext in key_suffixes else key if key_base not in non_configuration_keys: new_configuration_dict[key] = gyp.simple_copy.deepcopy(target_val) @@ -2482,7 +2470,7 @@ def SetUpConfigurations(target, target_dict): merged_configurations[configuration] = new_configuration_dict # Put the new configurations back into the target dict as a configuration. - for configuration in merged_configurations.keys(): + for configuration in merged_configurations: target_dict["configurations"][configuration] = merged_configurations[ configuration ] @@ -2499,19 +2487,16 @@ def SetUpConfigurations(target, target_dict): delete_keys = [] for key in target_dict: key_ext = key[-1:] - if key_ext in key_suffixes: - key_base = key[:-1] - else: - key_base = key + key_base = key[:-1] if key_ext in key_suffixes else key if key_base not in non_configuration_keys: delete_keys.append(key) for key in delete_keys: del target_dict[key] # Check the configurations to see if they contain invalid keys. - for configuration in target_dict["configurations"].keys(): + for configuration in target_dict["configurations"]: configuration_dict = target_dict["configurations"][configuration] - for key in configuration_dict.keys(): + for key in configuration_dict: if key in invalid_configuration_keys: raise GypError( "%s not allowed in the %s configuration, found in " @@ -2554,7 +2539,7 @@ def ProcessListFiltersInDict(name, the_dict): del_lists = [] for key, value in the_dict.items(): operation = key[-1] - if operation != "!" and operation != "/": + if operation not in {"!", "/"}: continue if type(value) is not list: diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py index 5b9c2712e091b4..38fa21dd666697 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py @@ -93,7 +93,7 @@ def _AddPrefix(element, prefix): if element is None: return element # Note, not Iterable because we don't want to handle strings like that. - if isinstance(element, list) or isinstance(element, tuple): + if isinstance(element, (list, tuple)): return [prefix + e for e in element] else: return prefix + element @@ -105,7 +105,7 @@ def _DoRemapping(element, map): if map is not None and element is not None: if not callable(map): map = map.get # Assume it's a dict, otherwise a callable to do the remap. - if isinstance(element, list) or isinstance(element, tuple): + if isinstance(element, (list, tuple)): element = filter(None, [map(elem) for elem in element]) else: element = map(element) @@ -117,7 +117,7 @@ def _AppendOrReturn(append, element): then add |element| to it, adding each item in |element| if it's a list or tuple.""" if append is not None and element is not None: - if isinstance(element, list) or isinstance(element, tuple): + if isinstance(element, (list, tuple)): append.extend(element) else: append.append(element) @@ -183,7 +183,7 @@ def ExtractSharedMSVSSystemIncludes(configs, generator_flags): expanded_system_includes = OrderedSet( [ExpandMacros(include, env) for include in all_system_includes] ) - if any(["$" in include for include in expanded_system_includes]): + if any("$" in include for include in expanded_system_includes): # Some path relies on target-specific variables, bail. return None @@ -255,10 +255,7 @@ def GetVSMacroEnv(self, base_to_build=None, config=None): """Get a dict of variables mapping internal VS macro names to their gyp equivalents.""" target_arch = self.GetArch(config) - if target_arch == "x86": - target_platform = "Win32" - else: - target_platform = target_arch + target_platform = "Win32" if target_arch == "x86" else target_arch target_name = self.spec.get("product_prefix", "") + self.spec.get( "product_name", self.spec["target_name"] ) @@ -738,10 +735,7 @@ def GetLdflags( # TODO(scottmg): This should sort of be somewhere else (not really a flag). ld("AdditionalDependencies", prefix="") - if self.GetArch(config) == "x86": - safeseh_default = "true" - else: - safeseh_default = None + safeseh_default = "true" if self.GetArch(config) == "x86" else None ld( "ImageHasSafeExceptionHandlers", map={"false": ":NO", "true": ""}, @@ -960,15 +954,12 @@ def GetRuleShellFlags(self, rule): def _HasExplicitRuleForExtension(self, spec, extension): """Determine if there's an explicit rule for a particular extension.""" - for rule in spec.get("rules", []): - if rule["extension"] == extension: - return True - return False + return any(rule["extension"] == extension for rule in spec.get("rules", [])) def _HasExplicitIdlActions(self, spec): """Determine if an action should not run midl for .idl files.""" return any( - [action.get("explicit_idl_action", 0) for action in spec.get("actions", [])] + action.get("explicit_idl_action", 0) for action in spec.get("actions", []) ) def HasExplicitIdlRulesOrActions(self, spec): diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py index 638eee40029411..171d7295747fcd 100755 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py @@ -219,11 +219,10 @@ def ExecLinkWithManifests( our_manifest = "%(out)s.manifest" % variables # Load and normalize the manifests. mt.exe sometimes removes whitespace, # and sometimes doesn't unfortunately. - with open(our_manifest) as our_f: - with open(assert_manifest) as assert_f: - translator = str.maketrans('', '', string.whitespace) - our_data = our_f.read().translate(translator) - assert_data = assert_f.read().translate(translator) + with open(our_manifest) as our_f, open(assert_manifest) as assert_f: + translator = str.maketrans("", "", string.whitespace) + our_data = our_f.read().translate(translator) + assert_data = assert_f.read().translate(translator) if our_data != assert_data: os.unlink(out) diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py index a75d8eeab7bda0..29caf1ce7fbb97 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py @@ -685,10 +685,7 @@ def GetCflags(self, configname, arch=None): if platform_root: cflags.append("-F" + platform_root + "/Developer/Library/Frameworks/") - if sdk_root: - framework_root = sdk_root - else: - framework_root = "" + framework_root = sdk_root if sdk_root else "" config = self.spec["configurations"][self.configname] framework_dirs = config.get("mac_framework_dirs", []) for directory in framework_dirs: @@ -1248,10 +1245,7 @@ def _AdjustLibrary(self, library, config_name=None): l_flag = "-framework " + os.path.splitext(os.path.basename(library))[0] else: m = self.library_re.match(library) - if m: - l_flag = "-l" + m.group(1) - else: - l_flag = library + l_flag = "-l" + m.group(1) if m else library sdk_root = self._SdkPath(config_name) if not sdk_root: @@ -1545,7 +1539,7 @@ def CLTVersion(): except GypError: continue - regex = re.compile(r'Command Line Tools for Xcode\s+(?P\S+)') + regex = re.compile(r"Command Line Tools for Xcode\s+(?P\S+)") try: output = GetStdout(["/usr/sbin/softwareupdate", "--history"]) return re.search(regex, output).groupdict()["version"] diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py index 4e0ec5e8828f79..33c667c266bf69 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py @@ -971,7 +971,7 @@ def __init__(self, properties=None, id=None, parent=None): if "path" in self._properties and "name" not in self._properties: path = self._properties["path"] name = posixpath.basename(path) - if name != "" and path != name: + if name not in ("", path): self.SetProperty("name", name) if "path" in self._properties and ( @@ -2355,9 +2355,8 @@ def __init__( # property was supplied, set "productName" if it is not present. Also set # the "PRODUCT_NAME" build setting in each configuration, but only if # the setting is not present in any build configuration. - if "name" in self._properties: - if "productName" not in self._properties: - self.SetProperty("productName", self._properties["name"]) + if "name" in self._properties and "productName" not in self._properties: + self.SetProperty("productName", self._properties["name"]) if "productName" in self._properties: if "buildConfigurationList" in self._properties: @@ -2547,13 +2546,12 @@ def __init__( force_extension = suffix[1:] if ( - self._properties["productType"] - == "com.apple.product-type-bundle.unit.test" - or self._properties["productType"] - == "com.apple.product-type-bundle.ui-testing" - ): - if force_extension is None: - force_extension = suffix[1:] + self._properties["productType"] in { + "com.apple.product-type-bundle.unit.test", + "com.apple.product-type-bundle.ui-testing" + } + ) and force_extension is None: + force_extension = suffix[1:] if force_extension is not None: # If it's a wrapper (bundle), set WRAPPER_EXTENSION. @@ -2636,10 +2634,13 @@ def HeadersPhase(self): # frameworks phases, if any. insert_at = len(self._properties["buildPhases"]) for index, phase in enumerate(self._properties["buildPhases"]): - if ( - isinstance(phase, PBXResourcesBuildPhase) - or isinstance(phase, PBXSourcesBuildPhase) - or isinstance(phase, PBXFrameworksBuildPhase) + if isinstance( + phase, + ( + PBXResourcesBuildPhase, + PBXSourcesBuildPhase, + PBXFrameworksBuildPhase, + ), ): insert_at = index break @@ -2658,9 +2659,7 @@ def ResourcesPhase(self): # phases, if any. insert_at = len(self._properties["buildPhases"]) for index, phase in enumerate(self._properties["buildPhases"]): - if isinstance(phase, PBXSourcesBuildPhase) or isinstance( - phase, PBXFrameworksBuildPhase - ): + if isinstance(phase, (PBXSourcesBuildPhase, PBXFrameworksBuildPhase)): insert_at = index break @@ -2701,8 +2700,10 @@ def AddDependency(self, other): other._properties["productType"] == static_library_type or ( ( - other._properties["productType"] == shared_library_type - or other._properties["productType"] == framework_type + other._properties["productType"] in { + shared_library_type, + framework_type + } ) and ( (not other.HasBuildSetting("MACH_O_TYPE")) diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/LICENSE b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/LICENSE new file mode 100644 index 00000000000000..6f62d44e4ef733 --- /dev/null +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/LICENSE @@ -0,0 +1,3 @@ +This software is made available under the terms of *either* of the licenses +found in LICENSE.APACHE or LICENSE.BSD. Contributions to this software is made +under the terms of *both* these licenses. diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/LICENSE.APACHE b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/LICENSE.APACHE new file mode 100644 index 00000000000000..f433b1a53f5b83 --- /dev/null +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/LICENSE.APACHE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/LICENSE.BSD b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/LICENSE.BSD new file mode 100644 index 00000000000000..42ce7b75c92fb0 --- /dev/null +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/LICENSE.BSD @@ -0,0 +1,23 @@ +Copyright (c) Donald Stufft and individual contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/__init__.py b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/__init__.py new file mode 100644 index 00000000000000..5fd91838316fbe --- /dev/null +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/__init__.py @@ -0,0 +1,15 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +__title__ = "packaging" +__summary__ = "Core utilities for Python packages" +__uri__ = "https://github.com/pypa/packaging" + +__version__ = "23.3.dev0" + +__author__ = "Donald Stufft and individual contributors" +__email__ = "donald@stufft.io" + +__license__ = "BSD-2-Clause or Apache-2.0" +__copyright__ = "2014 %s" % __author__ diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/_elffile.py b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/_elffile.py new file mode 100644 index 00000000000000..6fb19b30bb53c1 --- /dev/null +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/_elffile.py @@ -0,0 +1,108 @@ +""" +ELF file parser. + +This provides a class ``ELFFile`` that parses an ELF executable in a similar +interface to ``ZipFile``. Only the read interface is implemented. + +Based on: https://gist.github.com/lyssdod/f51579ae8d93c8657a5564aefc2ffbca +ELF header: https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html +""" + +import enum +import os +import struct +from typing import IO, Optional, Tuple + + +class ELFInvalid(ValueError): + pass + + +class EIClass(enum.IntEnum): + C32 = 1 + C64 = 2 + + +class EIData(enum.IntEnum): + Lsb = 1 + Msb = 2 + + +class EMachine(enum.IntEnum): + I386 = 3 + S390 = 22 + Arm = 40 + X8664 = 62 + AArc64 = 183 + + +class ELFFile: + """ + Representation of an ELF executable. + """ + + def __init__(self, f: IO[bytes]) -> None: + self._f = f + + try: + ident = self._read("16B") + except struct.error: + raise ELFInvalid("unable to parse identification") + magic = bytes(ident[:4]) + if magic != b"\x7fELF": + raise ELFInvalid(f"invalid magic: {magic!r}") + + self.capacity = ident[4] # Format for program header (bitness). + self.encoding = ident[5] # Data structure encoding (endianness). + + try: + # e_fmt: Format for program header. + # p_fmt: Format for section header. + # p_idx: Indexes to find p_type, p_offset, and p_filesz. + e_fmt, self._p_fmt, self._p_idx = { + (1, 1): ("HHIIIIIHHH", ">IIIIIIII", (0, 1, 4)), # 32-bit MSB. + (2, 1): ("HHIQQQIHHH", ">IIQQQQQQ", (0, 2, 5)), # 64-bit MSB. + }[(self.capacity, self.encoding)] + except KeyError: + raise ELFInvalid( + f"unrecognized capacity ({self.capacity}) or " + f"encoding ({self.encoding})" + ) + + try: + ( + _, + self.machine, # Architecture type. + _, + _, + self._e_phoff, # Offset of program header. + _, + self.flags, # Processor-specific flags. + _, + self._e_phentsize, # Size of section. + self._e_phnum, # Number of sections. + ) = self._read(e_fmt) + except struct.error as e: + raise ELFInvalid("unable to parse machine and section information") from e + + def _read(self, fmt: str) -> Tuple[int, ...]: + return struct.unpack(fmt, self._f.read(struct.calcsize(fmt))) + + @property + def interpreter(self) -> Optional[str]: + """ + The path recorded in the ``PT_INTERP`` section header. + """ + for index in range(self._e_phnum): + self._f.seek(self._e_phoff + self._e_phentsize * index) + try: + data = self._read(self._p_fmt) + except struct.error: + continue + if data[self._p_idx[0]] != 3: # Not PT_INTERP. + continue + self._f.seek(data[self._p_idx[1]]) + return os.fsdecode(self._f.read(data[self._p_idx[2]])).strip("\0") + return None diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/_manylinux.py b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/_manylinux.py new file mode 100644 index 00000000000000..3705d50db9193e --- /dev/null +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/_manylinux.py @@ -0,0 +1,252 @@ +import collections +import contextlib +import functools +import os +import re +import sys +import warnings +from typing import Dict, Generator, Iterator, NamedTuple, Optional, Sequence, Tuple + +from ._elffile import EIClass, EIData, ELFFile, EMachine + +EF_ARM_ABIMASK = 0xFF000000 +EF_ARM_ABI_VER5 = 0x05000000 +EF_ARM_ABI_FLOAT_HARD = 0x00000400 + + +# `os.PathLike` not a generic type until Python 3.9, so sticking with `str` +# as the type for `path` until then. +@contextlib.contextmanager +def _parse_elf(path: str) -> Generator[Optional[ELFFile], None, None]: + try: + with open(path, "rb") as f: + yield ELFFile(f) + except (OSError, TypeError, ValueError): + yield None + + +def _is_linux_armhf(executable: str) -> bool: + # hard-float ABI can be detected from the ELF header of the running + # process + # https://static.docs.arm.com/ihi0044/g/aaelf32.pdf + with _parse_elf(executable) as f: + return ( + f is not None + and f.capacity == EIClass.C32 + and f.encoding == EIData.Lsb + and f.machine == EMachine.Arm + and f.flags & EF_ARM_ABIMASK == EF_ARM_ABI_VER5 + and f.flags & EF_ARM_ABI_FLOAT_HARD == EF_ARM_ABI_FLOAT_HARD + ) + + +def _is_linux_i686(executable: str) -> bool: + with _parse_elf(executable) as f: + return ( + f is not None + and f.capacity == EIClass.C32 + and f.encoding == EIData.Lsb + and f.machine == EMachine.I386 + ) + + +def _have_compatible_abi(executable: str, archs: Sequence[str]) -> bool: + if "armv7l" in archs: + return _is_linux_armhf(executable) + if "i686" in archs: + return _is_linux_i686(executable) + allowed_archs = {"x86_64", "aarch64", "ppc64", "ppc64le", "s390x", "loongarch64"} + return any(arch in allowed_archs for arch in archs) + + +# If glibc ever changes its major version, we need to know what the last +# minor version was, so we can build the complete list of all versions. +# For now, guess what the highest minor version might be, assume it will +# be 50 for testing. Once this actually happens, update the dictionary +# with the actual value. +_LAST_GLIBC_MINOR: Dict[int, int] = collections.defaultdict(lambda: 50) + + +class _GLibCVersion(NamedTuple): + major: int + minor: int + + +def _glibc_version_string_confstr() -> Optional[str]: + """ + Primary implementation of glibc_version_string using os.confstr. + """ + # os.confstr is quite a bit faster than ctypes.DLL. It's also less likely + # to be broken or missing. This strategy is used in the standard library + # platform module. + # https://github.com/python/cpython/blob/fcf1d003bf4f0100c/Lib/platform.py#L175-L183 + try: + # Should be a string like "glibc 2.17". + version_string: str = getattr(os, "confstr")("CS_GNU_LIBC_VERSION") + assert version_string is not None + _, version = version_string.rsplit() + except (AssertionError, AttributeError, OSError, ValueError): + # os.confstr() or CS_GNU_LIBC_VERSION not available (or a bad value)... + return None + return version + + +def _glibc_version_string_ctypes() -> Optional[str]: + """ + Fallback implementation of glibc_version_string using ctypes. + """ + try: + import ctypes + except ImportError: + return None + + # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen + # manpage says, "If filename is NULL, then the returned handle is for the + # main program". This way we can let the linker do the work to figure out + # which libc our process is actually using. + # + # We must also handle the special case where the executable is not a + # dynamically linked executable. This can occur when using musl libc, + # for example. In this situation, dlopen() will error, leading to an + # OSError. Interestingly, at least in the case of musl, there is no + # errno set on the OSError. The single string argument used to construct + # OSError comes from libc itself and is therefore not portable to + # hard code here. In any case, failure to call dlopen() means we + # can proceed, so we bail on our attempt. + try: + process_namespace = ctypes.CDLL(None) + except OSError: + return None + + try: + gnu_get_libc_version = process_namespace.gnu_get_libc_version + except AttributeError: + # Symbol doesn't exist -> therefore, we are not linked to + # glibc. + return None + + # Call gnu_get_libc_version, which returns a string like "2.5" + gnu_get_libc_version.restype = ctypes.c_char_p + version_str: str = gnu_get_libc_version() + # py2 / py3 compatibility: + if not isinstance(version_str, str): + version_str = version_str.decode("ascii") + + return version_str + + +def _glibc_version_string() -> Optional[str]: + """Returns glibc version string, or None if not using glibc.""" + return _glibc_version_string_confstr() or _glibc_version_string_ctypes() + + +def _parse_glibc_version(version_str: str) -> Tuple[int, int]: + """Parse glibc version. + + We use a regexp instead of str.split because we want to discard any + random junk that might come after the minor version -- this might happen + in patched/forked versions of glibc (e.g. Linaro's version of glibc + uses version strings like "2.20-2014.11"). See gh-3588. + """ + m = re.match(r"(?P[0-9]+)\.(?P[0-9]+)", version_str) + if not m: + warnings.warn( + f"Expected glibc version with 2 components major.minor," + f" got: {version_str}", + RuntimeWarning, + ) + return -1, -1 + return int(m.group("major")), int(m.group("minor")) + + +@functools.lru_cache() +def _get_glibc_version() -> Tuple[int, int]: + version_str = _glibc_version_string() + if version_str is None: + return (-1, -1) + return _parse_glibc_version(version_str) + + +# From PEP 513, PEP 600 +def _is_compatible(arch: str, version: _GLibCVersion) -> bool: + sys_glibc = _get_glibc_version() + if sys_glibc < version: + return False + # Check for presence of _manylinux module. + try: + import _manylinux # noqa + except ImportError: + return True + if hasattr(_manylinux, "manylinux_compatible"): + result = _manylinux.manylinux_compatible(version[0], version[1], arch) + if result is not None: + return bool(result) + return True + if version == _GLibCVersion(2, 5): + if hasattr(_manylinux, "manylinux1_compatible"): + return bool(_manylinux.manylinux1_compatible) + if version == _GLibCVersion(2, 12): + if hasattr(_manylinux, "manylinux2010_compatible"): + return bool(_manylinux.manylinux2010_compatible) + if version == _GLibCVersion(2, 17): + if hasattr(_manylinux, "manylinux2014_compatible"): + return bool(_manylinux.manylinux2014_compatible) + return True + + +_LEGACY_MANYLINUX_MAP = { + # CentOS 7 w/ glibc 2.17 (PEP 599) + (2, 17): "manylinux2014", + # CentOS 6 w/ glibc 2.12 (PEP 571) + (2, 12): "manylinux2010", + # CentOS 5 w/ glibc 2.5 (PEP 513) + (2, 5): "manylinux1", +} + + +def platform_tags(archs: Sequence[str]) -> Iterator[str]: + """Generate manylinux tags compatible to the current platform. + + :param archs: Sequence of compatible architectures. + The first one shall be the closest to the actual architecture and be the part of + platform tag after the ``linux_`` prefix, e.g. ``x86_64``. + The ``linux_`` prefix is assumed as a prerequisite for the current platform to + be manylinux-compatible. + + :returns: An iterator of compatible manylinux tags. + """ + if not _have_compatible_abi(sys.executable, archs): + return + # Oldest glibc to be supported regardless of architecture is (2, 17). + too_old_glibc2 = _GLibCVersion(2, 16) + if set(archs) & {"x86_64", "i686"}: + # On x86/i686 also oldest glibc to be supported is (2, 5). + too_old_glibc2 = _GLibCVersion(2, 4) + current_glibc = _GLibCVersion(*_get_glibc_version()) + glibc_max_list = [current_glibc] + # We can assume compatibility across glibc major versions. + # https://sourceware.org/bugzilla/show_bug.cgi?id=24636 + # + # Build a list of maximum glibc versions so that we can + # output the canonical list of all glibc from current_glibc + # down to too_old_glibc2, including all intermediary versions. + for glibc_major in range(current_glibc.major - 1, 1, -1): + glibc_minor = _LAST_GLIBC_MINOR[glibc_major] + glibc_max_list.append(_GLibCVersion(glibc_major, glibc_minor)) + for arch in archs: + for glibc_max in glibc_max_list: + if glibc_max.major == too_old_glibc2.major: + min_minor = too_old_glibc2.minor + else: + # For other glibc major versions oldest supported is (x, 0). + min_minor = -1 + for glibc_minor in range(glibc_max.minor, min_minor, -1): + glibc_version = _GLibCVersion(glibc_max.major, glibc_minor) + tag = "manylinux_{}_{}".format(*glibc_version) + if _is_compatible(arch, glibc_version): + yield f"{tag}_{arch}" + # Handle the legacy manylinux1, manylinux2010, manylinux2014 tags. + if glibc_version in _LEGACY_MANYLINUX_MAP: + legacy_tag = _LEGACY_MANYLINUX_MAP[glibc_version] + if _is_compatible(arch, glibc_version): + yield f"{legacy_tag}_{arch}" diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/_musllinux.py b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/_musllinux.py new file mode 100644 index 00000000000000..86419df9d7087f --- /dev/null +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/_musllinux.py @@ -0,0 +1,83 @@ +"""PEP 656 support. + +This module implements logic to detect if the currently running Python is +linked against musl, and what musl version is used. +""" + +import functools +import re +import subprocess +import sys +from typing import Iterator, NamedTuple, Optional, Sequence + +from ._elffile import ELFFile + + +class _MuslVersion(NamedTuple): + major: int + minor: int + + +def _parse_musl_version(output: str) -> Optional[_MuslVersion]: + lines = [n for n in (n.strip() for n in output.splitlines()) if n] + if len(lines) < 2 or lines[0][:4] != "musl": + return None + m = re.match(r"Version (\d+)\.(\d+)", lines[1]) + if not m: + return None + return _MuslVersion(major=int(m.group(1)), minor=int(m.group(2))) + + +@functools.lru_cache() +def _get_musl_version(executable: str) -> Optional[_MuslVersion]: + """Detect currently-running musl runtime version. + + This is done by checking the specified executable's dynamic linking + information, and invoking the loader to parse its output for a version + string. If the loader is musl, the output would be something like:: + + musl libc (x86_64) + Version 1.2.2 + Dynamic Program Loader + """ + try: + with open(executable, "rb") as f: + ld = ELFFile(f).interpreter + except (OSError, TypeError, ValueError): + return None + if ld is None or "musl" not in ld: + return None + proc = subprocess.run([ld], stderr=subprocess.PIPE, text=True) + return _parse_musl_version(proc.stderr) + + +def platform_tags(archs: Sequence[str]) -> Iterator[str]: + """Generate musllinux tags compatible to the current platform. + + :param archs: Sequence of compatible architectures. + The first one shall be the closest to the actual architecture and be the part of + platform tag after the ``linux_`` prefix, e.g. ``x86_64``. + The ``linux_`` prefix is assumed as a prerequisite for the current platform to + be musllinux-compatible. + + :returns: An iterator of compatible musllinux tags. + """ + sys_musl = _get_musl_version(sys.executable) + if sys_musl is None: # Python not dynamically linked against musl. + return + for arch in archs: + for minor in range(sys_musl.minor, -1, -1): + yield f"musllinux_{sys_musl.major}_{minor}_{arch}" + + +if __name__ == "__main__": # pragma: no cover + import sysconfig + + plat = sysconfig.get_platform() + assert plat.startswith("linux-"), "not linux" + + print("plat:", plat) + print("musl:", _get_musl_version(sys.executable)) + print("tags:", end=" ") + for t in platform_tags(re.sub(r"[.-]", "_", plat.split("-", 1)[-1])): + print(t, end="\n ") diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/_parser.py b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/_parser.py new file mode 100644 index 00000000000000..4576981c2dd755 --- /dev/null +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/_parser.py @@ -0,0 +1,359 @@ +"""Handwritten parser of dependency specifiers. + +The docstring for each __parse_* function contains ENBF-inspired grammar representing +the implementation. +""" + +import ast +from typing import Any, List, NamedTuple, Optional, Tuple, Union + +from ._tokenizer import DEFAULT_RULES, Tokenizer + + +class Node: + def __init__(self, value: str) -> None: + self.value = value + + def __str__(self) -> str: + return self.value + + def __repr__(self) -> str: + return f"<{self.__class__.__name__}('{self}')>" + + def serialize(self) -> str: + raise NotImplementedError + + +class Variable(Node): + def serialize(self) -> str: + return str(self) + + +class Value(Node): + def serialize(self) -> str: + return f'"{self}"' + + +class Op(Node): + def serialize(self) -> str: + return str(self) + + +MarkerVar = Union[Variable, Value] +MarkerItem = Tuple[MarkerVar, Op, MarkerVar] +# MarkerAtom = Union[MarkerItem, List["MarkerAtom"]] +# MarkerList = List[Union["MarkerList", MarkerAtom, str]] +# mypy does not support recursive type definition +# https://github.com/python/mypy/issues/731 +MarkerAtom = Any +MarkerList = List[Any] + + +class ParsedRequirement(NamedTuple): + name: str + url: str + extras: List[str] + specifier: str + marker: Optional[MarkerList] + + +# -------------------------------------------------------------------------------------- +# Recursive descent parser for dependency specifier +# -------------------------------------------------------------------------------------- +def parse_requirement(source: str) -> ParsedRequirement: + return _parse_requirement(Tokenizer(source, rules=DEFAULT_RULES)) + + +def _parse_requirement(tokenizer: Tokenizer) -> ParsedRequirement: + """ + requirement = WS? IDENTIFIER WS? extras WS? requirement_details + """ + tokenizer.consume("WS") + + name_token = tokenizer.expect( + "IDENTIFIER", expected="package name at the start of dependency specifier" + ) + name = name_token.text + tokenizer.consume("WS") + + extras = _parse_extras(tokenizer) + tokenizer.consume("WS") + + url, specifier, marker = _parse_requirement_details(tokenizer) + tokenizer.expect("END", expected="end of dependency specifier") + + return ParsedRequirement(name, url, extras, specifier, marker) + + +def _parse_requirement_details( + tokenizer: Tokenizer, +) -> Tuple[str, str, Optional[MarkerList]]: + """ + requirement_details = AT URL (WS requirement_marker?)? + | specifier WS? (requirement_marker)? + """ + + specifier = "" + url = "" + marker = None + + if tokenizer.check("AT"): + tokenizer.read() + tokenizer.consume("WS") + + url_start = tokenizer.position + url = tokenizer.expect("URL", expected="URL after @").text + if tokenizer.check("END", peek=True): + return (url, specifier, marker) + + tokenizer.expect("WS", expected="whitespace after URL") + + # The input might end after whitespace. + if tokenizer.check("END", peek=True): + return (url, specifier, marker) + + marker = _parse_requirement_marker( + tokenizer, span_start=url_start, after="URL and whitespace" + ) + else: + specifier_start = tokenizer.position + specifier = _parse_specifier(tokenizer) + tokenizer.consume("WS") + + if tokenizer.check("END", peek=True): + return (url, specifier, marker) + + marker = _parse_requirement_marker( + tokenizer, + span_start=specifier_start, + after=( + "version specifier" + if specifier + else "name and no valid version specifier" + ), + ) + + return (url, specifier, marker) + + +def _parse_requirement_marker( + tokenizer: Tokenizer, *, span_start: int, after: str +) -> MarkerList: + """ + requirement_marker = SEMICOLON marker WS? + """ + + if not tokenizer.check("SEMICOLON"): + tokenizer.raise_syntax_error( + f"Expected end or semicolon (after {after})", + span_start=span_start, + ) + tokenizer.read() + + marker = _parse_marker(tokenizer) + tokenizer.consume("WS") + + return marker + + +def _parse_extras(tokenizer: Tokenizer) -> List[str]: + """ + extras = (LEFT_BRACKET wsp* extras_list? wsp* RIGHT_BRACKET)? + """ + if not tokenizer.check("LEFT_BRACKET", peek=True): + return [] + + with tokenizer.enclosing_tokens( + "LEFT_BRACKET", + "RIGHT_BRACKET", + around="extras", + ): + tokenizer.consume("WS") + extras = _parse_extras_list(tokenizer) + tokenizer.consume("WS") + + return extras + + +def _parse_extras_list(tokenizer: Tokenizer) -> List[str]: + """ + extras_list = identifier (wsp* ',' wsp* identifier)* + """ + extras: List[str] = [] + + if not tokenizer.check("IDENTIFIER"): + return extras + + extras.append(tokenizer.read().text) + + while True: + tokenizer.consume("WS") + if tokenizer.check("IDENTIFIER", peek=True): + tokenizer.raise_syntax_error("Expected comma between extra names") + elif not tokenizer.check("COMMA"): + break + + tokenizer.read() + tokenizer.consume("WS") + + extra_token = tokenizer.expect("IDENTIFIER", expected="extra name after comma") + extras.append(extra_token.text) + + return extras + + +def _parse_specifier(tokenizer: Tokenizer) -> str: + """ + specifier = LEFT_PARENTHESIS WS? version_many WS? RIGHT_PARENTHESIS + | WS? version_many WS? + """ + with tokenizer.enclosing_tokens( + "LEFT_PARENTHESIS", + "RIGHT_PARENTHESIS", + around="version specifier", + ): + tokenizer.consume("WS") + parsed_specifiers = _parse_version_many(tokenizer) + tokenizer.consume("WS") + + return parsed_specifiers + + +def _parse_version_many(tokenizer: Tokenizer) -> str: + """ + version_many = (SPECIFIER (WS? COMMA WS? SPECIFIER)*)? + """ + parsed_specifiers = "" + while tokenizer.check("SPECIFIER"): + span_start = tokenizer.position + parsed_specifiers += tokenizer.read().text + if tokenizer.check("VERSION_PREFIX_TRAIL", peek=True): + tokenizer.raise_syntax_error( + ".* suffix can only be used with `==` or `!=` operators", + span_start=span_start, + span_end=tokenizer.position + 1, + ) + if tokenizer.check("VERSION_LOCAL_LABEL_TRAIL", peek=True): + tokenizer.raise_syntax_error( + "Local version label can only be used with `==` or `!=` operators", + span_start=span_start, + span_end=tokenizer.position, + ) + tokenizer.consume("WS") + if not tokenizer.check("COMMA"): + break + parsed_specifiers += tokenizer.read().text + tokenizer.consume("WS") + + return parsed_specifiers + + +# -------------------------------------------------------------------------------------- +# Recursive descent parser for marker expression +# -------------------------------------------------------------------------------------- +def parse_marker(source: str) -> MarkerList: + return _parse_full_marker(Tokenizer(source, rules=DEFAULT_RULES)) + + +def _parse_full_marker(tokenizer: Tokenizer) -> MarkerList: + retval = _parse_marker(tokenizer) + tokenizer.expect("END", expected="end of marker expression") + return retval + + +def _parse_marker(tokenizer: Tokenizer) -> MarkerList: + """ + marker = marker_atom (BOOLOP marker_atom)+ + """ + expression = [_parse_marker_atom(tokenizer)] + while tokenizer.check("BOOLOP"): + token = tokenizer.read() + expr_right = _parse_marker_atom(tokenizer) + expression.extend((token.text, expr_right)) + return expression + + +def _parse_marker_atom(tokenizer: Tokenizer) -> MarkerAtom: + """ + marker_atom = WS? LEFT_PARENTHESIS WS? marker WS? RIGHT_PARENTHESIS WS? + | WS? marker_item WS? + """ + + tokenizer.consume("WS") + if tokenizer.check("LEFT_PARENTHESIS", peek=True): + with tokenizer.enclosing_tokens( + "LEFT_PARENTHESIS", + "RIGHT_PARENTHESIS", + around="marker expression", + ): + tokenizer.consume("WS") + marker: MarkerAtom = _parse_marker(tokenizer) + tokenizer.consume("WS") + else: + marker = _parse_marker_item(tokenizer) + tokenizer.consume("WS") + return marker + + +def _parse_marker_item(tokenizer: Tokenizer) -> MarkerItem: + """ + marker_item = WS? marker_var WS? marker_op WS? marker_var WS? + """ + tokenizer.consume("WS") + marker_var_left = _parse_marker_var(tokenizer) + tokenizer.consume("WS") + marker_op = _parse_marker_op(tokenizer) + tokenizer.consume("WS") + marker_var_right = _parse_marker_var(tokenizer) + tokenizer.consume("WS") + return (marker_var_left, marker_op, marker_var_right) + + +def _parse_marker_var(tokenizer: Tokenizer) -> MarkerVar: + """ + marker_var = VARIABLE | QUOTED_STRING + """ + if tokenizer.check("VARIABLE"): + return process_env_var(tokenizer.read().text.replace(".", "_")) + elif tokenizer.check("QUOTED_STRING"): + return process_python_str(tokenizer.read().text) + else: + tokenizer.raise_syntax_error( + message="Expected a marker variable or quoted string" + ) + + +def process_env_var(env_var: str) -> Variable: + if ( + env_var == "platform_python_implementation" + or env_var == "python_implementation" + ): + return Variable("platform_python_implementation") + else: + return Variable(env_var) + + +def process_python_str(python_str: str) -> Value: + value = ast.literal_eval(python_str) + return Value(str(value)) + + +def _parse_marker_op(tokenizer: Tokenizer) -> Op: + """ + marker_op = IN | NOT IN | OP + """ + if tokenizer.check("IN"): + tokenizer.read() + return Op("in") + elif tokenizer.check("NOT"): + tokenizer.read() + tokenizer.expect("WS", expected="whitespace after 'not'") + tokenizer.expect("IN", expected="'in' after 'not'") + return Op("not in") + elif tokenizer.check("OP"): + return Op(tokenizer.read().text) + else: + return tokenizer.raise_syntax_error( + "Expected marker operator, one of " + "<=, <, !=, ==, >=, >, ~=, ===, in, not in" + ) diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/_structures.py b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/_structures.py new file mode 100644 index 00000000000000..90a6465f9682c8 --- /dev/null +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/_structures.py @@ -0,0 +1,61 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +class InfinityType: + def __repr__(self) -> str: + return "Infinity" + + def __hash__(self) -> int: + return hash(repr(self)) + + def __lt__(self, other: object) -> bool: + return False + + def __le__(self, other: object) -> bool: + return False + + def __eq__(self, other: object) -> bool: + return isinstance(other, self.__class__) + + def __gt__(self, other: object) -> bool: + return True + + def __ge__(self, other: object) -> bool: + return True + + def __neg__(self: object) -> "NegativeInfinityType": + return NegativeInfinity + + +Infinity = InfinityType() + + +class NegativeInfinityType: + def __repr__(self) -> str: + return "-Infinity" + + def __hash__(self) -> int: + return hash(repr(self)) + + def __lt__(self, other: object) -> bool: + return True + + def __le__(self, other: object) -> bool: + return True + + def __eq__(self, other: object) -> bool: + return isinstance(other, self.__class__) + + def __gt__(self, other: object) -> bool: + return False + + def __ge__(self, other: object) -> bool: + return False + + def __neg__(self: object) -> InfinityType: + return Infinity + + +NegativeInfinity = NegativeInfinityType() diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/_tokenizer.py b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/_tokenizer.py new file mode 100644 index 00000000000000..dd0d648d49a7c1 --- /dev/null +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/_tokenizer.py @@ -0,0 +1,192 @@ +import contextlib +import re +from dataclasses import dataclass +from typing import Dict, Iterator, NoReturn, Optional, Tuple, Union + +from .specifiers import Specifier + + +@dataclass +class Token: + name: str + text: str + position: int + + +class ParserSyntaxError(Exception): + """The provided source text could not be parsed correctly.""" + + def __init__( + self, + message: str, + *, + source: str, + span: Tuple[int, int], + ) -> None: + self.span = span + self.message = message + self.source = source + + super().__init__() + + def __str__(self) -> str: + marker = " " * self.span[0] + "~" * (self.span[1] - self.span[0]) + "^" + return "\n ".join([self.message, self.source, marker]) + + +DEFAULT_RULES: "Dict[str, Union[str, re.Pattern[str]]]" = { + "LEFT_PARENTHESIS": r"\(", + "RIGHT_PARENTHESIS": r"\)", + "LEFT_BRACKET": r"\[", + "RIGHT_BRACKET": r"\]", + "SEMICOLON": r";", + "COMMA": r",", + "QUOTED_STRING": re.compile( + r""" + ( + ('[^']*') + | + ("[^"]*") + ) + """, + re.VERBOSE, + ), + "OP": r"(===|==|~=|!=|<=|>=|<|>)", + "BOOLOP": r"\b(or|and)\b", + "IN": r"\bin\b", + "NOT": r"\bnot\b", + "VARIABLE": re.compile( + r""" + \b( + python_version + |python_full_version + |os[._]name + |sys[._]platform + |platform_(release|system) + |platform[._](version|machine|python_implementation) + |python_implementation + |implementation_(name|version) + |extra + )\b + """, + re.VERBOSE, + ), + "SPECIFIER": re.compile( + Specifier._operator_regex_str + Specifier._version_regex_str, + re.VERBOSE | re.IGNORECASE, + ), + "AT": r"\@", + "URL": r"[^ \t]+", + "IDENTIFIER": r"\b[a-zA-Z0-9][a-zA-Z0-9._-]*\b", + "VERSION_PREFIX_TRAIL": r"\.\*", + "VERSION_LOCAL_LABEL_TRAIL": r"\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*", + "WS": r"[ \t]+", + "END": r"$", +} + + +class Tokenizer: + """Context-sensitive token parsing. + + Provides methods to examine the input stream to check whether the next token + matches. + """ + + def __init__( + self, + source: str, + *, + rules: "Dict[str, Union[str, re.Pattern[str]]]", + ) -> None: + self.source = source + self.rules: Dict[str, re.Pattern[str]] = { + name: re.compile(pattern) for name, pattern in rules.items() + } + self.next_token: Optional[Token] = None + self.position = 0 + + def consume(self, name: str) -> None: + """Move beyond provided token name, if at current position.""" + if self.check(name): + self.read() + + def check(self, name: str, *, peek: bool = False) -> bool: + """Check whether the next token has the provided name. + + By default, if the check succeeds, the token *must* be read before + another check. If `peek` is set to `True`, the token is not loaded and + would need to be checked again. + """ + assert ( + self.next_token is None + ), f"Cannot check for {name!r}, already have {self.next_token!r}" + assert name in self.rules, f"Unknown token name: {name!r}" + + expression = self.rules[name] + + match = expression.match(self.source, self.position) + if match is None: + return False + if not peek: + self.next_token = Token(name, match[0], self.position) + return True + + def expect(self, name: str, *, expected: str) -> Token: + """Expect a certain token name next, failing with a syntax error otherwise. + + The token is *not* read. + """ + if not self.check(name): + raise self.raise_syntax_error(f"Expected {expected}") + return self.read() + + def read(self) -> Token: + """Consume the next token and return it.""" + token = self.next_token + assert token is not None + + self.position += len(token.text) + self.next_token = None + + return token + + def raise_syntax_error( + self, + message: str, + *, + span_start: Optional[int] = None, + span_end: Optional[int] = None, + ) -> NoReturn: + """Raise ParserSyntaxError at the given position.""" + span = ( + self.position if span_start is None else span_start, + self.position if span_end is None else span_end, + ) + raise ParserSyntaxError( + message, + source=self.source, + span=span, + ) + + @contextlib.contextmanager + def enclosing_tokens( + self, open_token: str, close_token: str, *, around: str + ) -> Iterator[None]: + if self.check(open_token): + open_position = self.position + self.read() + else: + open_position = None + + yield + + if open_position is None: + return + + if not self.check(close_token): + self.raise_syntax_error( + f"Expected matching {close_token} for {open_token}, after {around}", + span_start=open_position, + ) + + self.read() diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/markers.py b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/markers.py new file mode 100644 index 00000000000000..8b98fca7233be6 --- /dev/null +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/markers.py @@ -0,0 +1,252 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import operator +import os +import platform +import sys +from typing import Any, Callable, Dict, List, Optional, Tuple, Union + +from ._parser import ( + MarkerAtom, + MarkerList, + Op, + Value, + Variable, + parse_marker as _parse_marker, +) +from ._tokenizer import ParserSyntaxError +from .specifiers import InvalidSpecifier, Specifier +from .utils import canonicalize_name + +__all__ = [ + "InvalidMarker", + "UndefinedComparison", + "UndefinedEnvironmentName", + "Marker", + "default_environment", +] + +Operator = Callable[[str, str], bool] + + +class InvalidMarker(ValueError): + """ + An invalid marker was found, users should refer to PEP 508. + """ + + +class UndefinedComparison(ValueError): + """ + An invalid operation was attempted on a value that doesn't support it. + """ + + +class UndefinedEnvironmentName(ValueError): + """ + A name was attempted to be used that does not exist inside of the + environment. + """ + + +def _normalize_extra_values(results: Any) -> Any: + """ + Normalize extra values. + """ + if isinstance(results[0], tuple): + lhs, op, rhs = results[0] + if isinstance(lhs, Variable) and lhs.value == "extra": + normalized_extra = canonicalize_name(rhs.value) + rhs = Value(normalized_extra) + elif isinstance(rhs, Variable) and rhs.value == "extra": + normalized_extra = canonicalize_name(lhs.value) + lhs = Value(normalized_extra) + results[0] = lhs, op, rhs + return results + + +def _format_marker( + marker: Union[List[str], MarkerAtom, str], first: Optional[bool] = True +) -> str: + + assert isinstance(marker, (list, tuple, str)) + + # Sometimes we have a structure like [[...]] which is a single item list + # where the single item is itself it's own list. In that case we want skip + # the rest of this function so that we don't get extraneous () on the + # outside. + if ( + isinstance(marker, list) + and len(marker) == 1 + and isinstance(marker[0], (list, tuple)) + ): + return _format_marker(marker[0]) + + if isinstance(marker, list): + inner = (_format_marker(m, first=False) for m in marker) + if first: + return " ".join(inner) + else: + return "(" + " ".join(inner) + ")" + elif isinstance(marker, tuple): + return " ".join([m.serialize() for m in marker]) + else: + return marker + + +_operators: Dict[str, Operator] = { + "in": lambda lhs, rhs: lhs in rhs, + "not in": lambda lhs, rhs: lhs not in rhs, + "<": operator.lt, + "<=": operator.le, + "==": operator.eq, + "!=": operator.ne, + ">=": operator.ge, + ">": operator.gt, +} + + +def _eval_op(lhs: str, op: Op, rhs: str) -> bool: + try: + spec = Specifier("".join([op.serialize(), rhs])) + except InvalidSpecifier: + pass + else: + return spec.contains(lhs, prereleases=True) + + oper: Optional[Operator] = _operators.get(op.serialize()) + if oper is None: + raise UndefinedComparison(f"Undefined {op!r} on {lhs!r} and {rhs!r}.") + + return oper(lhs, rhs) + + +def _normalize(*values: str, key: str) -> Tuple[str, ...]: + # PEP 685 – Comparison of extra names for optional distribution dependencies + # https://peps.python.org/pep-0685/ + # > When comparing extra names, tools MUST normalize the names being + # > compared using the semantics outlined in PEP 503 for names + if key == "extra": + return tuple(canonicalize_name(v) for v in values) + + # other environment markers don't have such standards + return values + + +def _evaluate_markers(markers: MarkerList, environment: Dict[str, str]) -> bool: + groups: List[List[bool]] = [[]] + + for marker in markers: + assert isinstance(marker, (list, tuple, str)) + + if isinstance(marker, list): + groups[-1].append(_evaluate_markers(marker, environment)) + elif isinstance(marker, tuple): + lhs, op, rhs = marker + + if isinstance(lhs, Variable): + environment_key = lhs.value + lhs_value = environment[environment_key] + rhs_value = rhs.value + else: + lhs_value = lhs.value + environment_key = rhs.value + rhs_value = environment[environment_key] + + lhs_value, rhs_value = _normalize(lhs_value, rhs_value, key=environment_key) + groups[-1].append(_eval_op(lhs_value, op, rhs_value)) + else: + assert marker in ["and", "or"] + if marker == "or": + groups.append([]) + + return any(all(item) for item in groups) + + +def format_full_version(info: "sys._version_info") -> str: + version = "{0.major}.{0.minor}.{0.micro}".format(info) + kind = info.releaselevel + if kind != "final": + version += kind[0] + str(info.serial) + return version + + +def default_environment() -> Dict[str, str]: + iver = format_full_version(sys.implementation.version) + implementation_name = sys.implementation.name + return { + "implementation_name": implementation_name, + "implementation_version": iver, + "os_name": os.name, + "platform_machine": platform.machine(), + "platform_release": platform.release(), + "platform_system": platform.system(), + "platform_version": platform.version(), + "python_full_version": platform.python_version(), + "platform_python_implementation": platform.python_implementation(), + "python_version": ".".join(platform.python_version_tuple()[:2]), + "sys_platform": sys.platform, + } + + +class Marker: + def __init__(self, marker: str) -> None: + # Note: We create a Marker object without calling this constructor in + # packaging.requirements.Requirement. If any additional logic is + # added here, make sure to mirror/adapt Requirement. + try: + self._markers = _normalize_extra_values(_parse_marker(marker)) + # The attribute `_markers` can be described in terms of a recursive type: + # MarkerList = List[Union[Tuple[Node, ...], str, MarkerList]] + # + # For example, the following expression: + # python_version > "3.6" or (python_version == "3.6" and os_name == "unix") + # + # is parsed into: + # [ + # (, ')>, ), + # 'and', + # [ + # (, , ), + # 'or', + # (, , ) + # ] + # ] + except ParserSyntaxError as e: + raise InvalidMarker(str(e)) from e + + def __str__(self) -> str: + return _format_marker(self._markers) + + def __repr__(self) -> str: + return f"" + + def __hash__(self) -> int: + return hash((self.__class__.__name__, str(self))) + + def __eq__(self, other: Any) -> bool: + if not isinstance(other, Marker): + return NotImplemented + + return str(self) == str(other) + + def evaluate(self, environment: Optional[Dict[str, str]] = None) -> bool: + """Evaluate a marker. + + Return the boolean from evaluating the given marker against the + environment. environment is an optional argument to override all or + part of the determined environment. + + The environment is determined from the current Python process. + """ + current_environment = default_environment() + current_environment["extra"] = "" + if environment is not None: + current_environment.update(environment) + # The API used to allow setting extra to None. We need to handle this + # case for backwards compatibility. + if current_environment["extra"] is None: + current_environment["extra"] = "" + + return _evaluate_markers(self._markers, current_environment) diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/metadata.py b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/metadata.py new file mode 100644 index 00000000000000..fb274930799da0 --- /dev/null +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/metadata.py @@ -0,0 +1,825 @@ +import email.feedparser +import email.header +import email.message +import email.parser +import email.policy +import sys +import typing +from typing import ( + Any, + Callable, + Dict, + Generic, + List, + Optional, + Tuple, + Type, + Union, + cast, +) + +from . import requirements, specifiers, utils, version as version_module + +T = typing.TypeVar("T") +if sys.version_info[:2] >= (3, 8): # pragma: no cover + from typing import Literal, TypedDict +else: # pragma: no cover + if typing.TYPE_CHECKING: + from typing_extensions import Literal, TypedDict + else: + try: + from typing_extensions import Literal, TypedDict + except ImportError: + + class Literal: + def __init_subclass__(*_args, **_kwargs): + pass + + class TypedDict: + def __init_subclass__(*_args, **_kwargs): + pass + + +try: + ExceptionGroup +except NameError: # pragma: no cover + + class ExceptionGroup(Exception): # noqa: N818 + """A minimal implementation of :external:exc:`ExceptionGroup` from Python 3.11. + + If :external:exc:`ExceptionGroup` is already defined by Python itself, + that version is used instead. + """ + + message: str + exceptions: List[Exception] + + def __init__(self, message: str, exceptions: List[Exception]) -> None: + self.message = message + self.exceptions = exceptions + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.message!r}, {self.exceptions!r})" + +else: # pragma: no cover + ExceptionGroup = ExceptionGroup + + +class InvalidMetadata(ValueError): + """A metadata field contains invalid data.""" + + field: str + """The name of the field that contains invalid data.""" + + def __init__(self, field: str, message: str) -> None: + self.field = field + super().__init__(message) + + +# The RawMetadata class attempts to make as few assumptions about the underlying +# serialization formats as possible. The idea is that as long as a serialization +# formats offer some very basic primitives in *some* way then we can support +# serializing to and from that format. +class RawMetadata(TypedDict, total=False): + """A dictionary of raw core metadata. + + Each field in core metadata maps to a key of this dictionary (when data is + provided). The key is lower-case and underscores are used instead of dashes + compared to the equivalent core metadata field. Any core metadata field that + can be specified multiple times or can hold multiple values in a single + field have a key with a plural name. See :class:`Metadata` whose attributes + match the keys of this dictionary. + + Core metadata fields that can be specified multiple times are stored as a + list or dict depending on which is appropriate for the field. Any fields + which hold multiple values in a single field are stored as a list. + + """ + + # Metadata 1.0 - PEP 241 + metadata_version: str + name: str + version: str + platforms: List[str] + summary: str + description: str + keywords: List[str] + home_page: str + author: str + author_email: str + license: str + + # Metadata 1.1 - PEP 314 + supported_platforms: List[str] + download_url: str + classifiers: List[str] + requires: List[str] + provides: List[str] + obsoletes: List[str] + + # Metadata 1.2 - PEP 345 + maintainer: str + maintainer_email: str + requires_dist: List[str] + provides_dist: List[str] + obsoletes_dist: List[str] + requires_python: str + requires_external: List[str] + project_urls: Dict[str, str] + + # Metadata 2.0 + # PEP 426 attempted to completely revamp the metadata format + # but got stuck without ever being able to build consensus on + # it and ultimately ended up withdrawn. + # + # However, a number of tools had started emitting METADATA with + # `2.0` Metadata-Version, so for historical reasons, this version + # was skipped. + + # Metadata 2.1 - PEP 566 + description_content_type: str + provides_extra: List[str] + + # Metadata 2.2 - PEP 643 + dynamic: List[str] + + # Metadata 2.3 - PEP 685 + # No new fields were added in PEP 685, just some edge case were + # tightened up to provide better interoptability. + + +_STRING_FIELDS = { + "author", + "author_email", + "description", + "description_content_type", + "download_url", + "home_page", + "license", + "maintainer", + "maintainer_email", + "metadata_version", + "name", + "requires_python", + "summary", + "version", +} + +_LIST_FIELDS = { + "classifiers", + "dynamic", + "obsoletes", + "obsoletes_dist", + "platforms", + "provides", + "provides_dist", + "provides_extra", + "requires", + "requires_dist", + "requires_external", + "supported_platforms", +} + +_DICT_FIELDS = { + "project_urls", +} + + +def _parse_keywords(data: str) -> List[str]: + """Split a string of comma-separate keyboards into a list of keywords.""" + return [k.strip() for k in data.split(",")] + + +def _parse_project_urls(data: List[str]) -> Dict[str, str]: + """Parse a list of label/URL string pairings separated by a comma.""" + urls = {} + for pair in data: + # Our logic is slightly tricky here as we want to try and do + # *something* reasonable with malformed data. + # + # The main thing that we have to worry about, is data that does + # not have a ',' at all to split the label from the Value. There + # isn't a singular right answer here, and we will fail validation + # later on (if the caller is validating) so it doesn't *really* + # matter, but since the missing value has to be an empty str + # and our return value is dict[str, str], if we let the key + # be the missing value, then they'd have multiple '' values that + # overwrite each other in a accumulating dict. + # + # The other potentional issue is that it's possible to have the + # same label multiple times in the metadata, with no solid "right" + # answer with what to do in that case. As such, we'll do the only + # thing we can, which is treat the field as unparseable and add it + # to our list of unparsed fields. + parts = [p.strip() for p in pair.split(",", 1)] + parts.extend([""] * (max(0, 2 - len(parts)))) # Ensure 2 items + + # TODO: The spec doesn't say anything about if the keys should be + # considered case sensitive or not... logically they should + # be case-preserving and case-insensitive, but doing that + # would open up more cases where we might have duplicate + # entries. + label, url = parts + if label in urls: + # The label already exists in our set of urls, so this field + # is unparseable, and we can just add the whole thing to our + # unparseable data and stop processing it. + raise KeyError("duplicate labels in project urls") + urls[label] = url + + return urls + + +def _get_payload(msg: email.message.Message, source: Union[bytes, str]) -> str: + """Get the body of the message.""" + # If our source is a str, then our caller has managed encodings for us, + # and we don't need to deal with it. + if isinstance(source, str): + payload: str = msg.get_payload() + return payload + # If our source is a bytes, then we're managing the encoding and we need + # to deal with it. + else: + bpayload: bytes = msg.get_payload(decode=True) + try: + return bpayload.decode("utf8", "strict") + except UnicodeDecodeError: + raise ValueError("payload in an invalid encoding") + + +# The various parse_FORMAT functions here are intended to be as lenient as +# possible in their parsing, while still returning a correctly typed +# RawMetadata. +# +# To aid in this, we also generally want to do as little touching of the +# data as possible, except where there are possibly some historic holdovers +# that make valid data awkward to work with. +# +# While this is a lower level, intermediate format than our ``Metadata`` +# class, some light touch ups can make a massive difference in usability. + +# Map METADATA fields to RawMetadata. +_EMAIL_TO_RAW_MAPPING = { + "author": "author", + "author-email": "author_email", + "classifier": "classifiers", + "description": "description", + "description-content-type": "description_content_type", + "download-url": "download_url", + "dynamic": "dynamic", + "home-page": "home_page", + "keywords": "keywords", + "license": "license", + "maintainer": "maintainer", + "maintainer-email": "maintainer_email", + "metadata-version": "metadata_version", + "name": "name", + "obsoletes": "obsoletes", + "obsoletes-dist": "obsoletes_dist", + "platform": "platforms", + "project-url": "project_urls", + "provides": "provides", + "provides-dist": "provides_dist", + "provides-extra": "provides_extra", + "requires": "requires", + "requires-dist": "requires_dist", + "requires-external": "requires_external", + "requires-python": "requires_python", + "summary": "summary", + "supported-platform": "supported_platforms", + "version": "version", +} +_RAW_TO_EMAIL_MAPPING = {raw: email for email, raw in _EMAIL_TO_RAW_MAPPING.items()} + + +def parse_email(data: Union[bytes, str]) -> Tuple[RawMetadata, Dict[str, List[str]]]: + """Parse a distribution's metadata stored as email headers (e.g. from ``METADATA``). + + This function returns a two-item tuple of dicts. The first dict is of + recognized fields from the core metadata specification. Fields that can be + parsed and translated into Python's built-in types are converted + appropriately. All other fields are left as-is. Fields that are allowed to + appear multiple times are stored as lists. + + The second dict contains all other fields from the metadata. This includes + any unrecognized fields. It also includes any fields which are expected to + be parsed into a built-in type but were not formatted appropriately. Finally, + any fields that are expected to appear only once but are repeated are + included in this dict. + + """ + raw: Dict[str, Union[str, List[str], Dict[str, str]]] = {} + unparsed: Dict[str, List[str]] = {} + + if isinstance(data, str): + parsed = email.parser.Parser(policy=email.policy.compat32).parsestr(data) + else: + parsed = email.parser.BytesParser(policy=email.policy.compat32).parsebytes(data) + + # We have to wrap parsed.keys() in a set, because in the case of multiple + # values for a key (a list), the key will appear multiple times in the + # list of keys, but we're avoiding that by using get_all(). + for name in frozenset(parsed.keys()): + # Header names in RFC are case insensitive, so we'll normalize to all + # lower case to make comparisons easier. + name = name.lower() + + # We use get_all() here, even for fields that aren't multiple use, + # because otherwise someone could have e.g. two Name fields, and we + # would just silently ignore it rather than doing something about it. + headers = parsed.get_all(name) or [] + + # The way the email module works when parsing bytes is that it + # unconditionally decodes the bytes as ascii using the surrogateescape + # handler. When you pull that data back out (such as with get_all() ), + # it looks to see if the str has any surrogate escapes, and if it does + # it wraps it in a Header object instead of returning the string. + # + # As such, we'll look for those Header objects, and fix up the encoding. + value = [] + # Flag if we have run into any issues processing the headers, thus + # signalling that the data belongs in 'unparsed'. + valid_encoding = True + for h in headers: + # It's unclear if this can return more types than just a Header or + # a str, so we'll just assert here to make sure. + assert isinstance(h, (email.header.Header, str)) + + # If it's a header object, we need to do our little dance to get + # the real data out of it. In cases where there is invalid data + # we're going to end up with mojibake, but there's no obvious, good + # way around that without reimplementing parts of the Header object + # ourselves. + # + # That should be fine since, if mojibacked happens, this key is + # going into the unparsed dict anyways. + if isinstance(h, email.header.Header): + # The Header object stores it's data as chunks, and each chunk + # can be independently encoded, so we'll need to check each + # of them. + chunks: List[Tuple[bytes, Optional[str]]] = [] + for bin, encoding in email.header.decode_header(h): + try: + bin.decode("utf8", "strict") + except UnicodeDecodeError: + # Enable mojibake. + encoding = "latin1" + valid_encoding = False + else: + encoding = "utf8" + chunks.append((bin, encoding)) + + # Turn our chunks back into a Header object, then let that + # Header object do the right thing to turn them into a + # string for us. + value.append(str(email.header.make_header(chunks))) + # This is already a string, so just add it. + else: + value.append(h) + + # We've processed all of our values to get them into a list of str, + # but we may have mojibake data, in which case this is an unparsed + # field. + if not valid_encoding: + unparsed[name] = value + continue + + raw_name = _EMAIL_TO_RAW_MAPPING.get(name) + if raw_name is None: + # This is a bit of a weird situation, we've encountered a key that + # we don't know what it means, so we don't know whether it's meant + # to be a list or not. + # + # Since we can't really tell one way or another, we'll just leave it + # as a list, even though it may be a single item list, because that's + # what makes the most sense for email headers. + unparsed[name] = value + continue + + # If this is one of our string fields, then we'll check to see if our + # value is a list of a single item. If it is then we'll assume that + # it was emitted as a single string, and unwrap the str from inside + # the list. + # + # If it's any other kind of data, then we haven't the faintest clue + # what we should parse it as, and we have to just add it to our list + # of unparsed stuff. + if raw_name in _STRING_FIELDS and len(value) == 1: + raw[raw_name] = value[0] + # If this is one of our list of string fields, then we can just assign + # the value, since email *only* has strings, and our get_all() call + # above ensures that this is a list. + elif raw_name in _LIST_FIELDS: + raw[raw_name] = value + # Special Case: Keywords + # The keywords field is implemented in the metadata spec as a str, + # but it conceptually is a list of strings, and is serialized using + # ", ".join(keywords), so we'll do some light data massaging to turn + # this into what it logically is. + elif raw_name == "keywords" and len(value) == 1: + raw[raw_name] = _parse_keywords(value[0]) + # Special Case: Project-URL + # The project urls is implemented in the metadata spec as a list of + # specially-formatted strings that represent a key and a value, which + # is fundamentally a mapping, however the email format doesn't support + # mappings in a sane way, so it was crammed into a list of strings + # instead. + # + # We will do a little light data massaging to turn this into a map as + # it logically should be. + elif raw_name == "project_urls": + try: + raw[raw_name] = _parse_project_urls(value) + except KeyError: + unparsed[name] = value + # Nothing that we've done has managed to parse this, so it'll just + # throw it in our unparseable data and move on. + else: + unparsed[name] = value + + # We need to support getting the Description from the message payload in + # addition to getting it from the the headers. This does mean, though, there + # is the possibility of it being set both ways, in which case we put both + # in 'unparsed' since we don't know which is right. + try: + payload = _get_payload(parsed, data) + except ValueError: + unparsed.setdefault("description", []).append( + parsed.get_payload(decode=isinstance(data, bytes)) + ) + else: + if payload: + # Check to see if we've already got a description, if so then both + # it, and this body move to unparseable. + if "description" in raw: + description_header = cast(str, raw.pop("description")) + unparsed.setdefault("description", []).extend( + [description_header, payload] + ) + elif "description" in unparsed: + unparsed["description"].append(payload) + else: + raw["description"] = payload + + # We need to cast our `raw` to a metadata, because a TypedDict only support + # literal key names, but we're computing our key names on purpose, but the + # way this function is implemented, our `TypedDict` can only have valid key + # names. + return cast(RawMetadata, raw), unparsed + + +_NOT_FOUND = object() + + +# Keep the two values in sync. +_VALID_METADATA_VERSIONS = ["1.0", "1.1", "1.2", "2.1", "2.2", "2.3"] +_MetadataVersion = Literal["1.0", "1.1", "1.2", "2.1", "2.2", "2.3"] + +_REQUIRED_ATTRS = frozenset(["metadata_version", "name", "version"]) + + +class _Validator(Generic[T]): + """Validate a metadata field. + + All _process_*() methods correspond to a core metadata field. The method is + called with the field's raw value. If the raw value is valid it is returned + in its "enriched" form (e.g. ``version.Version`` for the ``Version`` field). + If the raw value is invalid, :exc:`InvalidMetadata` is raised (with a cause + as appropriate). + """ + + name: str + raw_name: str + added: _MetadataVersion + + def __init__( + self, + *, + added: _MetadataVersion = "1.0", + ) -> None: + self.added = added + + def __set_name__(self, _owner: "Metadata", name: str) -> None: + self.name = name + self.raw_name = _RAW_TO_EMAIL_MAPPING[name] + + def __get__(self, instance: "Metadata", _owner: Type["Metadata"]) -> T: + # With Python 3.8, the caching can be replaced with functools.cached_property(). + # No need to check the cache as attribute lookup will resolve into the + # instance's __dict__ before __get__ is called. + cache = instance.__dict__ + value = instance._raw.get(self.name) + + # To make the _process_* methods easier, we'll check if the value is None + # and if this field is NOT a required attribute, and if both of those + # things are true, we'll skip the the converter. This will mean that the + # converters never have to deal with the None union. + if self.name in _REQUIRED_ATTRS or value is not None: + try: + converter: Callable[[Any], T] = getattr(self, f"_process_{self.name}") + except AttributeError: + pass + else: + value = converter(value) + + cache[self.name] = value + try: + del instance._raw[self.name] # type: ignore[misc] + except KeyError: + pass + + return cast(T, value) + + def _invalid_metadata( + self, msg: str, cause: Optional[Exception] = None + ) -> InvalidMetadata: + exc = InvalidMetadata( + self.raw_name, msg.format_map({"field": repr(self.raw_name)}) + ) + exc.__cause__ = cause + return exc + + def _process_metadata_version(self, value: str) -> _MetadataVersion: + # Implicitly makes Metadata-Version required. + if value not in _VALID_METADATA_VERSIONS: + raise self._invalid_metadata(f"{value!r} is not a valid metadata version") + return cast(_MetadataVersion, value) + + def _process_name(self, value: str) -> str: + if not value: + raise self._invalid_metadata("{field} is a required field") + # Validate the name as a side-effect. + try: + utils.canonicalize_name(value, validate=True) + except utils.InvalidName as exc: + raise self._invalid_metadata( + f"{value!r} is invalid for {{field}}", cause=exc + ) + else: + return value + + def _process_version(self, value: str) -> version_module.Version: + if not value: + raise self._invalid_metadata("{field} is a required field") + try: + return version_module.parse(value) + except version_module.InvalidVersion as exc: + raise self._invalid_metadata( + f"{value!r} is invalid for {{field}}", cause=exc + ) + + def _process_summary(self, value: str) -> str: + """Check the field contains no newlines.""" + if "\n" in value: + raise self._invalid_metadata("{field} must be a single line") + return value + + def _process_description_content_type(self, value: str) -> str: + content_types = {"text/plain", "text/x-rst", "text/markdown"} + message = email.message.EmailMessage() + message["content-type"] = value + + content_type, parameters = ( + # Defaults to `text/plain` if parsing failed. + message.get_content_type().lower(), + message["content-type"].params, + ) + # Check if content-type is valid or defaulted to `text/plain` and thus was + # not parseable. + if content_type not in content_types or content_type not in value.lower(): + raise self._invalid_metadata( + f"{{field}} must be one of {list(content_types)}, not {value!r}" + ) + + charset = parameters.get("charset", "UTF-8") + if charset != "UTF-8": + raise self._invalid_metadata( + f"{{field}} can only specify the UTF-8 charset, not {list(charset)}" + ) + + markdown_variants = {"GFM", "CommonMark"} + variant = parameters.get("variant", "GFM") # Use an acceptable default. + if content_type == "text/markdown" and variant not in markdown_variants: + raise self._invalid_metadata( + f"valid Markdown variants for {{field}} are {list(markdown_variants)}, " + f"not {variant!r}", + ) + return value + + def _process_dynamic(self, value: List[str]) -> List[str]: + for dynamic_field in map(str.lower, value): + if dynamic_field in {"name", "version", "metadata-version"}: + raise self._invalid_metadata( + f"{value!r} is not allowed as a dynamic field" + ) + elif dynamic_field not in _EMAIL_TO_RAW_MAPPING: + raise self._invalid_metadata(f"{value!r} is not a valid dynamic field") + return list(map(str.lower, value)) + + def _process_provides_extra( + self, + value: List[str], + ) -> List[utils.NormalizedName]: + normalized_names = [] + try: + for name in value: + normalized_names.append(utils.canonicalize_name(name, validate=True)) + except utils.InvalidName as exc: + raise self._invalid_metadata( + f"{name!r} is invalid for {{field}}", cause=exc + ) + else: + return normalized_names + + def _process_requires_python(self, value: str) -> specifiers.SpecifierSet: + try: + return specifiers.SpecifierSet(value) + except specifiers.InvalidSpecifier as exc: + raise self._invalid_metadata( + f"{value!r} is invalid for {{field}}", cause=exc + ) + + def _process_requires_dist( + self, + value: List[str], + ) -> List[requirements.Requirement]: + reqs = [] + try: + for req in value: + reqs.append(requirements.Requirement(req)) + except requirements.InvalidRequirement as exc: + raise self._invalid_metadata(f"{req!r} is invalid for {{field}}", cause=exc) + else: + return reqs + + +class Metadata: + """Representation of distribution metadata. + + Compared to :class:`RawMetadata`, this class provides objects representing + metadata fields instead of only using built-in types. Any invalid metadata + will cause :exc:`InvalidMetadata` to be raised (with a + :py:attr:`~BaseException.__cause__` attribute as appropriate). + """ + + _raw: RawMetadata + + @classmethod + def from_raw(cls, data: RawMetadata, *, validate: bool = True) -> "Metadata": + """Create an instance from :class:`RawMetadata`. + + If *validate* is true, all metadata will be validated. All exceptions + related to validation will be gathered and raised as an :class:`ExceptionGroup`. + """ + ins = cls() + ins._raw = data.copy() # Mutations occur due to caching enriched values. + + if validate: + exceptions: List[Exception] = [] + try: + metadata_version = ins.metadata_version + metadata_age = _VALID_METADATA_VERSIONS.index(metadata_version) + except InvalidMetadata as metadata_version_exc: + exceptions.append(metadata_version_exc) + metadata_version = None + + # Make sure to check for the fields that are present, the required + # fields (so their absence can be reported). + fields_to_check = frozenset(ins._raw) | _REQUIRED_ATTRS + # Remove fields that have already been checked. + fields_to_check -= {"metadata_version"} + + for key in fields_to_check: + try: + if metadata_version: + # Can't use getattr() as that triggers descriptor protocol which + # will fail due to no value for the instance argument. + try: + field_metadata_version = cls.__dict__[key].added + except KeyError: + exc = InvalidMetadata(key, f"unrecognized field: {key!r}") + exceptions.append(exc) + continue + field_age = _VALID_METADATA_VERSIONS.index( + field_metadata_version + ) + if field_age > metadata_age: + field = _RAW_TO_EMAIL_MAPPING[key] + exc = InvalidMetadata( + field, + "{field} introduced in metadata version " + "{field_metadata_version}, not {metadata_version}", + ) + exceptions.append(exc) + continue + getattr(ins, key) + except InvalidMetadata as exc: + exceptions.append(exc) + + if exceptions: + raise ExceptionGroup("invalid metadata", exceptions) + + return ins + + @classmethod + def from_email( + cls, data: Union[bytes, str], *, validate: bool = True + ) -> "Metadata": + """Parse metadata from email headers. + + If *validate* is true, the metadata will be validated. All exceptions + related to validation will be gathered and raised as an :class:`ExceptionGroup`. + """ + raw, unparsed = parse_email(data) + + if validate: + exceptions: list[Exception] = [] + for unparsed_key in unparsed: + if unparsed_key in _EMAIL_TO_RAW_MAPPING: + message = f"{unparsed_key!r} has invalid data" + else: + message = f"unrecognized field: {unparsed_key!r}" + exceptions.append(InvalidMetadata(unparsed_key, message)) + + if exceptions: + raise ExceptionGroup("unparsed", exceptions) + + try: + return cls.from_raw(raw, validate=validate) + except ExceptionGroup as exc_group: + raise ExceptionGroup( + "invalid or unparsed metadata", exc_group.exceptions + ) from None + + metadata_version: _Validator[_MetadataVersion] = _Validator() + """:external:ref:`core-metadata-metadata-version` + (required; validated to be a valid metadata version)""" + name: _Validator[str] = _Validator() + """:external:ref:`core-metadata-name` + (required; validated using :func:`~packaging.utils.canonicalize_name` and its + *validate* parameter)""" + version: _Validator[version_module.Version] = _Validator() + """:external:ref:`core-metadata-version` (required)""" + dynamic: _Validator[Optional[List[str]]] = _Validator( + added="2.2", + ) + """:external:ref:`core-metadata-dynamic` + (validated against core metadata field names and lowercased)""" + platforms: _Validator[Optional[List[str]]] = _Validator() + """:external:ref:`core-metadata-platform`""" + supported_platforms: _Validator[Optional[List[str]]] = _Validator(added="1.1") + """:external:ref:`core-metadata-supported-platform`""" + summary: _Validator[Optional[str]] = _Validator() + """:external:ref:`core-metadata-summary` (validated to contain no newlines)""" + description: _Validator[Optional[str]] = _Validator() # TODO 2.1: can be in body + """:external:ref:`core-metadata-description`""" + description_content_type: _Validator[Optional[str]] = _Validator(added="2.1") + """:external:ref:`core-metadata-description-content-type` (validated)""" + keywords: _Validator[Optional[List[str]]] = _Validator() + """:external:ref:`core-metadata-keywords`""" + home_page: _Validator[Optional[str]] = _Validator() + """:external:ref:`core-metadata-home-page`""" + download_url: _Validator[Optional[str]] = _Validator(added="1.1") + """:external:ref:`core-metadata-download-url`""" + author: _Validator[Optional[str]] = _Validator() + """:external:ref:`core-metadata-author`""" + author_email: _Validator[Optional[str]] = _Validator() + """:external:ref:`core-metadata-author-email`""" + maintainer: _Validator[Optional[str]] = _Validator(added="1.2") + """:external:ref:`core-metadata-maintainer`""" + maintainer_email: _Validator[Optional[str]] = _Validator(added="1.2") + """:external:ref:`core-metadata-maintainer-email`""" + license: _Validator[Optional[str]] = _Validator() + """:external:ref:`core-metadata-license`""" + classifiers: _Validator[Optional[List[str]]] = _Validator(added="1.1") + """:external:ref:`core-metadata-classifier`""" + requires_dist: _Validator[Optional[List[requirements.Requirement]]] = _Validator( + added="1.2" + ) + """:external:ref:`core-metadata-requires-dist`""" + requires_python: _Validator[Optional[specifiers.SpecifierSet]] = _Validator( + added="1.2" + ) + """:external:ref:`core-metadata-requires-python`""" + # Because `Requires-External` allows for non-PEP 440 version specifiers, we + # don't do any processing on the values. + requires_external: _Validator[Optional[List[str]]] = _Validator(added="1.2") + """:external:ref:`core-metadata-requires-external`""" + project_urls: _Validator[Optional[Dict[str, str]]] = _Validator(added="1.2") + """:external:ref:`core-metadata-project-url`""" + # PEP 685 lets us raise an error if an extra doesn't pass `Name` validation + # regardless of metadata version. + provides_extra: _Validator[Optional[List[utils.NormalizedName]]] = _Validator( + added="2.1", + ) + """:external:ref:`core-metadata-provides-extra`""" + provides_dist: _Validator[Optional[List[str]]] = _Validator(added="1.2") + """:external:ref:`core-metadata-provides-dist`""" + obsoletes_dist: _Validator[Optional[List[str]]] = _Validator(added="1.2") + """:external:ref:`core-metadata-obsoletes-dist`""" + requires: _Validator[Optional[List[str]]] = _Validator(added="1.1") + """``Requires`` (deprecated)""" + provides: _Validator[Optional[List[str]]] = _Validator(added="1.1") + """``Provides`` (deprecated)""" + obsoletes: _Validator[Optional[List[str]]] = _Validator(added="1.1") + """``Obsoletes`` (deprecated)""" diff --git a/test/fixtures/test-runner/subdir/subdir_test.js b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/py.typed similarity index 100% rename from test/fixtures/test-runner/subdir/subdir_test.js rename to deps/npm/node_modules/node-gyp/gyp/pylib/packaging/py.typed diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/requirements.py b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/requirements.py new file mode 100644 index 00000000000000..0c00eba331b736 --- /dev/null +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/requirements.py @@ -0,0 +1,90 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from typing import Any, Iterator, Optional, Set + +from ._parser import parse_requirement as _parse_requirement +from ._tokenizer import ParserSyntaxError +from .markers import Marker, _normalize_extra_values +from .specifiers import SpecifierSet +from .utils import canonicalize_name + + +class InvalidRequirement(ValueError): + """ + An invalid requirement was found, users should refer to PEP 508. + """ + + +class Requirement: + """Parse a requirement. + + Parse a given requirement string into its parts, such as name, specifier, + URL, and extras. Raises InvalidRequirement on a badly-formed requirement + string. + """ + + # TODO: Can we test whether something is contained within a requirement? + # If so how do we do that? Do we need to test against the _name_ of + # the thing as well as the version? What about the markers? + # TODO: Can we normalize the name and extra name? + + def __init__(self, requirement_string: str) -> None: + try: + parsed = _parse_requirement(requirement_string) + except ParserSyntaxError as e: + raise InvalidRequirement(str(e)) from e + + self.name: str = parsed.name + self.url: Optional[str] = parsed.url or None + self.extras: Set[str] = set(parsed.extras if parsed.extras else []) + self.specifier: SpecifierSet = SpecifierSet(parsed.specifier) + self.marker: Optional[Marker] = None + if parsed.marker is not None: + self.marker = Marker.__new__(Marker) + self.marker._markers = _normalize_extra_values(parsed.marker) + + def _iter_parts(self, name: str) -> Iterator[str]: + yield name + + if self.extras: + formatted_extras = ",".join(sorted(self.extras)) + yield f"[{formatted_extras}]" + + if self.specifier: + yield str(self.specifier) + + if self.url: + yield f"@ {self.url}" + if self.marker: + yield " " + + if self.marker: + yield f"; {self.marker}" + + def __str__(self) -> str: + return "".join(self._iter_parts(self.name)) + + def __repr__(self) -> str: + return f"" + + def __hash__(self) -> int: + return hash( + ( + self.__class__.__name__, + *self._iter_parts(canonicalize_name(self.name)), + ) + ) + + def __eq__(self, other: Any) -> bool: + if not isinstance(other, Requirement): + return NotImplemented + + return ( + canonicalize_name(self.name) == canonicalize_name(other.name) + and self.extras == other.extras + and self.specifier == other.specifier + and self.url == other.url + and self.marker == other.marker + ) diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/specifiers.py b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/specifiers.py new file mode 100644 index 00000000000000..94448327ae2d44 --- /dev/null +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/specifiers.py @@ -0,0 +1,1030 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +""" +.. testsetup:: + + from packaging.specifiers import Specifier, SpecifierSet, InvalidSpecifier + from packaging.version import Version +""" + +import abc +import itertools +import re +from typing import ( + Callable, + Iterable, + Iterator, + List, + Optional, + Set, + Tuple, + TypeVar, + Union, +) + +from .utils import canonicalize_version +from .version import Version + +UnparsedVersion = Union[Version, str] +UnparsedVersionVar = TypeVar("UnparsedVersionVar", bound=UnparsedVersion) +CallableOperator = Callable[[Version, str], bool] + + +def _coerce_version(version: UnparsedVersion) -> Version: + if not isinstance(version, Version): + version = Version(version) + return version + + +class InvalidSpecifier(ValueError): + """ + Raised when attempting to create a :class:`Specifier` with a specifier + string that is invalid. + + >>> Specifier("lolwat") + Traceback (most recent call last): + ... + packaging.specifiers.InvalidSpecifier: Invalid specifier: 'lolwat' + """ + + +class BaseSpecifier(metaclass=abc.ABCMeta): + @abc.abstractmethod + def __str__(self) -> str: + """ + Returns the str representation of this Specifier-like object. This + should be representative of the Specifier itself. + """ + + @abc.abstractmethod + def __hash__(self) -> int: + """ + Returns a hash value for this Specifier-like object. + """ + + @abc.abstractmethod + def __eq__(self, other: object) -> bool: + """ + Returns a boolean representing whether or not the two Specifier-like + objects are equal. + + :param other: The other object to check against. + """ + + @property + @abc.abstractmethod + def prereleases(self) -> Optional[bool]: + """Whether or not pre-releases as a whole are allowed. + + This can be set to either ``True`` or ``False`` to explicitly enable or disable + prereleases or it can be set to ``None`` (the default) to use default semantics. + """ + + @prereleases.setter + def prereleases(self, value: bool) -> None: + """Setter for :attr:`prereleases`. + + :param value: The value to set. + """ + + @abc.abstractmethod + def contains(self, item: str, prereleases: Optional[bool] = None) -> bool: + """ + Determines if the given item is contained within this specifier. + """ + + @abc.abstractmethod + def filter( + self, iterable: Iterable[UnparsedVersionVar], prereleases: Optional[bool] = None + ) -> Iterator[UnparsedVersionVar]: + """ + Takes an iterable of items and filters them so that only items which + are contained within this specifier are allowed in it. + """ + + +class Specifier(BaseSpecifier): + """This class abstracts handling of version specifiers. + + .. tip:: + + It is generally not required to instantiate this manually. You should instead + prefer to work with :class:`SpecifierSet` instead, which can parse + comma-separated version specifiers (which is what package metadata contains). + """ + + _operator_regex_str = r""" + (?P(~=|==|!=|<=|>=|<|>|===)) + """ + _version_regex_str = r""" + (?P + (?: + # The identity operators allow for an escape hatch that will + # do an exact string match of the version you wish to install. + # This will not be parsed by PEP 440 and we cannot determine + # any semantic meaning from it. This operator is discouraged + # but included entirely as an escape hatch. + (?<====) # Only match for the identity operator + \s* + [^\s;)]* # The arbitrary version can be just about anything, + # we match everything except for whitespace, a + # semi-colon for marker support, and a closing paren + # since versions can be enclosed in them. + ) + | + (?: + # The (non)equality operators allow for wild card and local + # versions to be specified so we have to define these two + # operators separately to enable that. + (?<===|!=) # Only match for equals and not equals + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)* # release + + # You cannot use a wild card and a pre-release, post-release, a dev or + # local version together so group them with a | and make them optional. + (?: + \.\* # Wild card syntax of .* + | + (?: # pre release + [-_\.]? + (alpha|beta|preview|pre|a|b|c|rc) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local + )? + ) + | + (?: + # The compatible operator requires at least two digits in the + # release segment. + (?<=~=) # Only match for the compatible operator + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) + (?: # pre release + [-_\.]? + (alpha|beta|preview|pre|a|b|c|rc) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + ) + | + (?: + # All other operators only allow a sub set of what the + # (non)equality operators do. Specifically they do not allow + # local versions to be specified nor do they allow the prefix + # matching wild cards. + (?=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + "===": "arbitrary", + } + + def __init__(self, spec: str = "", prereleases: Optional[bool] = None) -> None: + """Initialize a Specifier instance. + + :param spec: + The string representation of a specifier which will be parsed and + normalized before use. + :param prereleases: + This tells the specifier if it should accept prerelease versions if + applicable or not. The default of ``None`` will autodetect it from the + given specifiers. + :raises InvalidSpecifier: + If the given specifier is invalid (i.e. bad syntax). + """ + match = self._regex.search(spec) + if not match: + raise InvalidSpecifier(f"Invalid specifier: '{spec}'") + + self._spec: Tuple[str, str] = ( + match.group("operator").strip(), + match.group("version").strip(), + ) + + # Store whether or not this Specifier should accept prereleases + self._prereleases = prereleases + + # https://github.com/python/mypy/pull/13475#pullrequestreview-1079784515 + @property # type: ignore[override] + def prereleases(self) -> bool: + # If there is an explicit prereleases set for this, then we'll just + # blindly use that. + if self._prereleases is not None: + return self._prereleases + + # Look at all of our specifiers and determine if they are inclusive + # operators, and if they are if they are including an explicit + # prerelease. + operator, version = self._spec + if operator in ["==", ">=", "<=", "~=", "==="]: + # The == specifier can include a trailing .*, if it does we + # want to remove before parsing. + if operator == "==" and version.endswith(".*"): + version = version[:-2] + + # Parse the version, and if it is a pre-release than this + # specifier allows pre-releases. + if Version(version).is_prerelease: + return True + + return False + + @prereleases.setter + def prereleases(self, value: bool) -> None: + self._prereleases = value + + @property + def operator(self) -> str: + """The operator of this specifier. + + >>> Specifier("==1.2.3").operator + '==' + """ + return self._spec[0] + + @property + def version(self) -> str: + """The version of this specifier. + + >>> Specifier("==1.2.3").version + '1.2.3' + """ + return self._spec[1] + + def __repr__(self) -> str: + """A representation of the Specifier that shows all internal state. + + >>> Specifier('>=1.0.0') + =1.0.0')> + >>> Specifier('>=1.0.0', prereleases=False) + =1.0.0', prereleases=False)> + >>> Specifier('>=1.0.0', prereleases=True) + =1.0.0', prereleases=True)> + """ + pre = ( + f", prereleases={self.prereleases!r}" + if self._prereleases is not None + else "" + ) + + return f"<{self.__class__.__name__}({str(self)!r}{pre})>" + + def __str__(self) -> str: + """A string representation of the Specifier that can be round-tripped. + + >>> str(Specifier('>=1.0.0')) + '>=1.0.0' + >>> str(Specifier('>=1.0.0', prereleases=False)) + '>=1.0.0' + """ + return "{}{}".format(*self._spec) + + @property + def _canonical_spec(self) -> Tuple[str, str]: + canonical_version = canonicalize_version( + self._spec[1], + strip_trailing_zero=(self._spec[0] != "~="), + ) + return self._spec[0], canonical_version + + def __hash__(self) -> int: + return hash(self._canonical_spec) + + def __eq__(self, other: object) -> bool: + """Whether or not the two Specifier-like objects are equal. + + :param other: The other object to check against. + + The value of :attr:`prereleases` is ignored. + + >>> Specifier("==1.2.3") == Specifier("== 1.2.3.0") + True + >>> (Specifier("==1.2.3", prereleases=False) == + ... Specifier("==1.2.3", prereleases=True)) + True + >>> Specifier("==1.2.3") == "==1.2.3" + True + >>> Specifier("==1.2.3") == Specifier("==1.2.4") + False + >>> Specifier("==1.2.3") == Specifier("~=1.2.3") + False + """ + if isinstance(other, str): + try: + other = self.__class__(str(other)) + except InvalidSpecifier: + return NotImplemented + elif not isinstance(other, self.__class__): + return NotImplemented + + return self._canonical_spec == other._canonical_spec + + def _get_operator(self, op: str) -> CallableOperator: + operator_callable: CallableOperator = getattr( + self, f"_compare_{self._operators[op]}" + ) + return operator_callable + + def _compare_compatible(self, prospective: Version, spec: str) -> bool: + + # Compatible releases have an equivalent combination of >= and ==. That + # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to + # implement this in terms of the other specifiers instead of + # implementing it ourselves. The only thing we need to do is construct + # the other specifiers. + + # We want everything but the last item in the version, but we want to + # ignore suffix segments. + prefix = _version_join( + list(itertools.takewhile(_is_not_suffix, _version_split(spec)))[:-1] + ) + + # Add the prefix notation to the end of our string + prefix += ".*" + + return self._get_operator(">=")(prospective, spec) and self._get_operator("==")( + prospective, prefix + ) + + def _compare_equal(self, prospective: Version, spec: str) -> bool: + + # We need special logic to handle prefix matching + if spec.endswith(".*"): + # In the case of prefix matching we want to ignore local segment. + normalized_prospective = canonicalize_version( + prospective.public, strip_trailing_zero=False + ) + # Get the normalized version string ignoring the trailing .* + normalized_spec = canonicalize_version(spec[:-2], strip_trailing_zero=False) + # Split the spec out by bangs and dots, and pretend that there is + # an implicit dot in between a release segment and a pre-release segment. + split_spec = _version_split(normalized_spec) + + # Split the prospective version out by bangs and dots, and pretend + # that there is an implicit dot in between a release segment and + # a pre-release segment. + split_prospective = _version_split(normalized_prospective) + + # 0-pad the prospective version before shortening it to get the correct + # shortened version. + padded_prospective, _ = _pad_version(split_prospective, split_spec) + + # Shorten the prospective version to be the same length as the spec + # so that we can determine if the specifier is a prefix of the + # prospective version or not. + shortened_prospective = padded_prospective[: len(split_spec)] + + return shortened_prospective == split_spec + else: + # Convert our spec string into a Version + spec_version = Version(spec) + + # If the specifier does not have a local segment, then we want to + # act as if the prospective version also does not have a local + # segment. + if not spec_version.local: + prospective = Version(prospective.public) + + return prospective == spec_version + + def _compare_not_equal(self, prospective: Version, spec: str) -> bool: + return not self._compare_equal(prospective, spec) + + def _compare_less_than_equal(self, prospective: Version, spec: str) -> bool: + + # NB: Local version identifiers are NOT permitted in the version + # specifier, so local version labels can be universally removed from + # the prospective version. + return Version(prospective.public) <= Version(spec) + + def _compare_greater_than_equal(self, prospective: Version, spec: str) -> bool: + + # NB: Local version identifiers are NOT permitted in the version + # specifier, so local version labels can be universally removed from + # the prospective version. + return Version(prospective.public) >= Version(spec) + + def _compare_less_than(self, prospective: Version, spec_str: str) -> bool: + + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec_str) + + # Check to see if the prospective version is less than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective < spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a pre-release version, that we do not accept pre-release + # versions for the version mentioned in the specifier (e.g. <3.1 should + # not match 3.1.dev0, but should match 3.0.dev0). + if not spec.is_prerelease and prospective.is_prerelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # less than the spec version *and* it's not a pre-release of the same + # version in the spec. + return True + + def _compare_greater_than(self, prospective: Version, spec_str: str) -> bool: + + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec_str) + + # Check to see if the prospective version is greater than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective > spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a post-release version, that we do not accept + # post-release versions for the version mentioned in the specifier + # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0). + if not spec.is_postrelease and prospective.is_postrelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # Ensure that we do not allow a local version of the version mentioned + # in the specifier, which is technically greater than, to match. + if prospective.local is not None: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # greater than the spec version *and* it's not a pre-release of the + # same version in the spec. + return True + + def _compare_arbitrary(self, prospective: Version, spec: str) -> bool: + return str(prospective).lower() == str(spec).lower() + + def __contains__(self, item: Union[str, Version]) -> bool: + """Return whether or not the item is contained in this specifier. + + :param item: The item to check for. + + This is used for the ``in`` operator and behaves the same as + :meth:`contains` with no ``prereleases`` argument passed. + + >>> "1.2.3" in Specifier(">=1.2.3") + True + >>> Version("1.2.3") in Specifier(">=1.2.3") + True + >>> "1.0.0" in Specifier(">=1.2.3") + False + >>> "1.3.0a1" in Specifier(">=1.2.3") + False + >>> "1.3.0a1" in Specifier(">=1.2.3", prereleases=True) + True + """ + return self.contains(item) + + def contains( + self, item: UnparsedVersion, prereleases: Optional[bool] = None + ) -> bool: + """Return whether or not the item is contained in this specifier. + + :param item: + The item to check for, which can be a version string or a + :class:`Version` instance. + :param prereleases: + Whether or not to match prereleases with this Specifier. If set to + ``None`` (the default), it uses :attr:`prereleases` to determine + whether or not prereleases are allowed. + + >>> Specifier(">=1.2.3").contains("1.2.3") + True + >>> Specifier(">=1.2.3").contains(Version("1.2.3")) + True + >>> Specifier(">=1.2.3").contains("1.0.0") + False + >>> Specifier(">=1.2.3").contains("1.3.0a1") + False + >>> Specifier(">=1.2.3", prereleases=True).contains("1.3.0a1") + True + >>> Specifier(">=1.2.3").contains("1.3.0a1", prereleases=True) + True + """ + + # Determine if prereleases are to be allowed or not. + if prereleases is None: + prereleases = self.prereleases + + # Normalize item to a Version, this allows us to have a shortcut for + # "2.0" in Specifier(">=2") + normalized_item = _coerce_version(item) + + # Determine if we should be supporting prereleases in this specifier + # or not, if we do not support prereleases than we can short circuit + # logic if this version is a prereleases. + if normalized_item.is_prerelease and not prereleases: + return False + + # Actually do the comparison to determine if this item is contained + # within this Specifier or not. + operator_callable: CallableOperator = self._get_operator(self.operator) + return operator_callable(normalized_item, self.version) + + def filter( + self, iterable: Iterable[UnparsedVersionVar], prereleases: Optional[bool] = None + ) -> Iterator[UnparsedVersionVar]: + """Filter items in the given iterable, that match the specifier. + + :param iterable: + An iterable that can contain version strings and :class:`Version` instances. + The items in the iterable will be filtered according to the specifier. + :param prereleases: + Whether or not to allow prereleases in the returned iterator. If set to + ``None`` (the default), it will be intelligently decide whether to allow + prereleases or not (based on the :attr:`prereleases` attribute, and + whether the only versions matching are prereleases). + + This method is smarter than just ``filter(Specifier().contains, [...])`` + because it implements the rule from :pep:`440` that a prerelease item + SHOULD be accepted if no other versions match the given specifier. + + >>> list(Specifier(">=1.2.3").filter(["1.2", "1.3", "1.5a1"])) + ['1.3'] + >>> list(Specifier(">=1.2.3").filter(["1.2", "1.2.3", "1.3", Version("1.4")])) + ['1.2.3', '1.3', ] + >>> list(Specifier(">=1.2.3").filter(["1.2", "1.5a1"])) + ['1.5a1'] + >>> list(Specifier(">=1.2.3").filter(["1.3", "1.5a1"], prereleases=True)) + ['1.3', '1.5a1'] + >>> list(Specifier(">=1.2.3", prereleases=True).filter(["1.3", "1.5a1"])) + ['1.3', '1.5a1'] + """ + + yielded = False + found_prereleases = [] + + kw = {"prereleases": prereleases if prereleases is not None else True} + + # Attempt to iterate over all the values in the iterable and if any of + # them match, yield them. + for version in iterable: + parsed_version = _coerce_version(version) + + if self.contains(parsed_version, **kw): + # If our version is a prerelease, and we were not set to allow + # prereleases, then we'll store it for later in case nothing + # else matches this specifier. + if parsed_version.is_prerelease and not ( + prereleases or self.prereleases + ): + found_prereleases.append(version) + # Either this is not a prerelease, or we should have been + # accepting prereleases from the beginning. + else: + yielded = True + yield version + + # Now that we've iterated over everything, determine if we've yielded + # any values, and if we have not and we have any prereleases stored up + # then we will go ahead and yield the prereleases. + if not yielded and found_prereleases: + for version in found_prereleases: + yield version + + +_prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$") + + +def _version_split(version: str) -> List[str]: + """Split version into components. + + The split components are intended for version comparison. The logic does + not attempt to retain the original version string, so joining the + components back with :func:`_version_join` may not produce the original + version string. + """ + result: List[str] = [] + + epoch, _, rest = version.rpartition("!") + result.append(epoch or "0") + + for item in rest.split("."): + match = _prefix_regex.search(item) + if match: + result.extend(match.groups()) + else: + result.append(item) + return result + + +def _version_join(components: List[str]) -> str: + """Join split version components into a version string. + + This function assumes the input came from :func:`_version_split`, where the + first component must be the epoch (either empty or numeric), and all other + components numeric. + """ + epoch, *rest = components + return f"{epoch}!{'.'.join(rest)}" + + +def _is_not_suffix(segment: str) -> bool: + return not any( + segment.startswith(prefix) for prefix in ("dev", "a", "b", "rc", "post") + ) + + +def _pad_version(left: List[str], right: List[str]) -> Tuple[List[str], List[str]]: + left_split, right_split = [], [] + + # Get the release segment of our versions + left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left))) + right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right))) + + # Get the rest of our versions + left_split.append(left[len(left_split[0]) :]) + right_split.append(right[len(right_split[0]) :]) + + # Insert our padding + left_split.insert(1, ["0"] * max(0, len(right_split[0]) - len(left_split[0]))) + right_split.insert(1, ["0"] * max(0, len(left_split[0]) - len(right_split[0]))) + + return (list(itertools.chain(*left_split)), list(itertools.chain(*right_split))) + + +class SpecifierSet(BaseSpecifier): + """This class abstracts handling of a set of version specifiers. + + It can be passed a single specifier (``>=3.0``), a comma-separated list of + specifiers (``>=3.0,!=3.1``), or no specifier at all. + """ + + def __init__( + self, specifiers: str = "", prereleases: Optional[bool] = None + ) -> None: + """Initialize a SpecifierSet instance. + + :param specifiers: + The string representation of a specifier or a comma-separated list of + specifiers which will be parsed and normalized before use. + :param prereleases: + This tells the SpecifierSet if it should accept prerelease versions if + applicable or not. The default of ``None`` will autodetect it from the + given specifiers. + + :raises InvalidSpecifier: + If the given ``specifiers`` are not parseable than this exception will be + raised. + """ + + # Split on `,` to break each individual specifier into it's own item, and + # strip each item to remove leading/trailing whitespace. + split_specifiers = [s.strip() for s in specifiers.split(",") if s.strip()] + + # Parsed each individual specifier, attempting first to make it a + # Specifier. + parsed: Set[Specifier] = set() + for specifier in split_specifiers: + parsed.add(Specifier(specifier)) + + # Turn our parsed specifiers into a frozen set and save them for later. + self._specs = frozenset(parsed) + + # Store our prereleases value so we can use it later to determine if + # we accept prereleases or not. + self._prereleases = prereleases + + @property + def prereleases(self) -> Optional[bool]: + # If we have been given an explicit prerelease modifier, then we'll + # pass that through here. + if self._prereleases is not None: + return self._prereleases + + # If we don't have any specifiers, and we don't have a forced value, + # then we'll just return None since we don't know if this should have + # pre-releases or not. + if not self._specs: + return None + + # Otherwise we'll see if any of the given specifiers accept + # prereleases, if any of them do we'll return True, otherwise False. + return any(s.prereleases for s in self._specs) + + @prereleases.setter + def prereleases(self, value: bool) -> None: + self._prereleases = value + + def __repr__(self) -> str: + """A representation of the specifier set that shows all internal state. + + Note that the ordering of the individual specifiers within the set may not + match the input string. + + >>> SpecifierSet('>=1.0.0,!=2.0.0') + =1.0.0')> + >>> SpecifierSet('>=1.0.0,!=2.0.0', prereleases=False) + =1.0.0', prereleases=False)> + >>> SpecifierSet('>=1.0.0,!=2.0.0', prereleases=True) + =1.0.0', prereleases=True)> + """ + pre = ( + f", prereleases={self.prereleases!r}" + if self._prereleases is not None + else "" + ) + + return f"" + + def __str__(self) -> str: + """A string representation of the specifier set that can be round-tripped. + + Note that the ordering of the individual specifiers within the set may not + match the input string. + + >>> str(SpecifierSet(">=1.0.0,!=1.0.1")) + '!=1.0.1,>=1.0.0' + >>> str(SpecifierSet(">=1.0.0,!=1.0.1", prereleases=False)) + '!=1.0.1,>=1.0.0' + """ + return ",".join(sorted(str(s) for s in self._specs)) + + def __hash__(self) -> int: + return hash(self._specs) + + def __and__(self, other: Union["SpecifierSet", str]) -> "SpecifierSet": + """Return a SpecifierSet which is a combination of the two sets. + + :param other: The other object to combine with. + + >>> SpecifierSet(">=1.0.0,!=1.0.1") & '<=2.0.0,!=2.0.1' + =1.0.0')> + >>> SpecifierSet(">=1.0.0,!=1.0.1") & SpecifierSet('<=2.0.0,!=2.0.1') + =1.0.0')> + """ + if isinstance(other, str): + other = SpecifierSet(other) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + specifier = SpecifierSet() + specifier._specs = frozenset(self._specs | other._specs) + + if self._prereleases is None and other._prereleases is not None: + specifier._prereleases = other._prereleases + elif self._prereleases is not None and other._prereleases is None: + specifier._prereleases = self._prereleases + elif self._prereleases == other._prereleases: + specifier._prereleases = self._prereleases + else: + raise ValueError( + "Cannot combine SpecifierSets with True and False prerelease " + "overrides." + ) + + return specifier + + def __eq__(self, other: object) -> bool: + """Whether or not the two SpecifierSet-like objects are equal. + + :param other: The other object to check against. + + The value of :attr:`prereleases` is ignored. + + >>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0,!=1.0.1") + True + >>> (SpecifierSet(">=1.0.0,!=1.0.1", prereleases=False) == + ... SpecifierSet(">=1.0.0,!=1.0.1", prereleases=True)) + True + >>> SpecifierSet(">=1.0.0,!=1.0.1") == ">=1.0.0,!=1.0.1" + True + >>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0") + False + >>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0,!=1.0.2") + False + """ + if isinstance(other, (str, Specifier)): + other = SpecifierSet(str(other)) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + return self._specs == other._specs + + def __len__(self) -> int: + """Returns the number of specifiers in this specifier set.""" + return len(self._specs) + + def __iter__(self) -> Iterator[Specifier]: + """ + Returns an iterator over all the underlying :class:`Specifier` instances + in this specifier set. + + >>> sorted(SpecifierSet(">=1.0.0,!=1.0.1"), key=str) + [, =1.0.0')>] + """ + return iter(self._specs) + + def __contains__(self, item: UnparsedVersion) -> bool: + """Return whether or not the item is contained in this specifier. + + :param item: The item to check for. + + This is used for the ``in`` operator and behaves the same as + :meth:`contains` with no ``prereleases`` argument passed. + + >>> "1.2.3" in SpecifierSet(">=1.0.0,!=1.0.1") + True + >>> Version("1.2.3") in SpecifierSet(">=1.0.0,!=1.0.1") + True + >>> "1.0.1" in SpecifierSet(">=1.0.0,!=1.0.1") + False + >>> "1.3.0a1" in SpecifierSet(">=1.0.0,!=1.0.1") + False + >>> "1.3.0a1" in SpecifierSet(">=1.0.0,!=1.0.1", prereleases=True) + True + """ + return self.contains(item) + + def contains( + self, + item: UnparsedVersion, + prereleases: Optional[bool] = None, + installed: Optional[bool] = None, + ) -> bool: + """Return whether or not the item is contained in this SpecifierSet. + + :param item: + The item to check for, which can be a version string or a + :class:`Version` instance. + :param prereleases: + Whether or not to match prereleases with this SpecifierSet. If set to + ``None`` (the default), it uses :attr:`prereleases` to determine + whether or not prereleases are allowed. + + >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.2.3") + True + >>> SpecifierSet(">=1.0.0,!=1.0.1").contains(Version("1.2.3")) + True + >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.0.1") + False + >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.3.0a1") + False + >>> SpecifierSet(">=1.0.0,!=1.0.1", prereleases=True).contains("1.3.0a1") + True + >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.3.0a1", prereleases=True) + True + """ + # Ensure that our item is a Version instance. + if not isinstance(item, Version): + item = Version(item) + + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # We can determine if we're going to allow pre-releases by looking to + # see if any of the underlying items supports them. If none of them do + # and this item is a pre-release then we do not allow it and we can + # short circuit that here. + # Note: This means that 1.0.dev1 would not be contained in something + # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0 + if not prereleases and item.is_prerelease: + return False + + if installed and item.is_prerelease: + item = Version(item.base_version) + + # We simply dispatch to the underlying specs here to make sure that the + # given version is contained within all of them. + # Note: This use of all() here means that an empty set of specifiers + # will always return True, this is an explicit design decision. + return all(s.contains(item, prereleases=prereleases) for s in self._specs) + + def filter( + self, iterable: Iterable[UnparsedVersionVar], prereleases: Optional[bool] = None + ) -> Iterator[UnparsedVersionVar]: + """Filter items in the given iterable, that match the specifiers in this set. + + :param iterable: + An iterable that can contain version strings and :class:`Version` instances. + The items in the iterable will be filtered according to the specifier. + :param prereleases: + Whether or not to allow prereleases in the returned iterator. If set to + ``None`` (the default), it will be intelligently decide whether to allow + prereleases or not (based on the :attr:`prereleases` attribute, and + whether the only versions matching are prereleases). + + This method is smarter than just ``filter(SpecifierSet(...).contains, [...])`` + because it implements the rule from :pep:`440` that a prerelease item + SHOULD be accepted if no other versions match the given specifier. + + >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.3", "1.5a1"])) + ['1.3'] + >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.3", Version("1.4")])) + ['1.3', ] + >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.5a1"])) + [] + >>> list(SpecifierSet(">=1.2.3").filter(["1.3", "1.5a1"], prereleases=True)) + ['1.3', '1.5a1'] + >>> list(SpecifierSet(">=1.2.3", prereleases=True).filter(["1.3", "1.5a1"])) + ['1.3', '1.5a1'] + + An "empty" SpecifierSet will filter items based on the presence of prerelease + versions in the set. + + >>> list(SpecifierSet("").filter(["1.3", "1.5a1"])) + ['1.3'] + >>> list(SpecifierSet("").filter(["1.5a1"])) + ['1.5a1'] + >>> list(SpecifierSet("", prereleases=True).filter(["1.3", "1.5a1"])) + ['1.3', '1.5a1'] + >>> list(SpecifierSet("").filter(["1.3", "1.5a1"], prereleases=True)) + ['1.3', '1.5a1'] + """ + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # If we have any specifiers, then we want to wrap our iterable in the + # filter method for each one, this will act as a logical AND amongst + # each specifier. + if self._specs: + for spec in self._specs: + iterable = spec.filter(iterable, prereleases=bool(prereleases)) + return iter(iterable) + # If we do not have any specifiers, then we need to have a rough filter + # which will filter out any pre-releases, unless there are no final + # releases. + else: + filtered: List[UnparsedVersionVar] = [] + found_prereleases: List[UnparsedVersionVar] = [] + + for item in iterable: + parsed_version = _coerce_version(item) + + # Store any item which is a pre-release for later unless we've + # already found a final version or we are accepting prereleases + if parsed_version.is_prerelease and not prereleases: + if not filtered: + found_prereleases.append(item) + else: + filtered.append(item) + + # If we've found no items except for pre-releases, then we'll go + # ahead and use the pre-releases + if not filtered and found_prereleases and prereleases is None: + return iter(found_prereleases) + + return iter(filtered) diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/tags.py b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/tags.py new file mode 100644 index 00000000000000..37f33b1ef849ed --- /dev/null +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/tags.py @@ -0,0 +1,553 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import logging +import platform +import struct +import subprocess +import sys +import sysconfig +from importlib.machinery import EXTENSION_SUFFIXES +from typing import ( + Dict, + FrozenSet, + Iterable, + Iterator, + List, + Optional, + Sequence, + Tuple, + Union, + cast, +) + +from . import _manylinux, _musllinux + +logger = logging.getLogger(__name__) + +PythonVersion = Sequence[int] +MacVersion = Tuple[int, int] + +INTERPRETER_SHORT_NAMES: Dict[str, str] = { + "python": "py", # Generic. + "cpython": "cp", + "pypy": "pp", + "ironpython": "ip", + "jython": "jy", +} + + +_32_BIT_INTERPRETER = struct.calcsize("P") == 4 + + +class Tag: + """ + A representation of the tag triple for a wheel. + + Instances are considered immutable and thus are hashable. Equality checking + is also supported. + """ + + __slots__ = ["_interpreter", "_abi", "_platform", "_hash"] + + def __init__(self, interpreter: str, abi: str, platform: str) -> None: + self._interpreter = interpreter.lower() + self._abi = abi.lower() + self._platform = platform.lower() + # The __hash__ of every single element in a Set[Tag] will be evaluated each time + # that a set calls its `.disjoint()` method, which may be called hundreds of + # times when scanning a page of links for packages with tags matching that + # Set[Tag]. Pre-computing the value here produces significant speedups for + # downstream consumers. + self._hash = hash((self._interpreter, self._abi, self._platform)) + + @property + def interpreter(self) -> str: + return self._interpreter + + @property + def abi(self) -> str: + return self._abi + + @property + def platform(self) -> str: + return self._platform + + def __eq__(self, other: object) -> bool: + if not isinstance(other, Tag): + return NotImplemented + + return ( + (self._hash == other._hash) # Short-circuit ASAP for perf reasons. + and (self._platform == other._platform) + and (self._abi == other._abi) + and (self._interpreter == other._interpreter) + ) + + def __hash__(self) -> int: + return self._hash + + def __str__(self) -> str: + return f"{self._interpreter}-{self._abi}-{self._platform}" + + def __repr__(self) -> str: + return f"<{self} @ {id(self)}>" + + +def parse_tag(tag: str) -> FrozenSet[Tag]: + """ + Parses the provided tag (e.g. `py3-none-any`) into a frozenset of Tag instances. + + Returning a set is required due to the possibility that the tag is a + compressed tag set. + """ + tags = set() + interpreters, abis, platforms = tag.split("-") + for interpreter in interpreters.split("."): + for abi in abis.split("."): + for platform_ in platforms.split("."): + tags.add(Tag(interpreter, abi, platform_)) + return frozenset(tags) + + +def _get_config_var(name: str, warn: bool = False) -> Union[int, str, None]: + value: Union[int, str, None] = sysconfig.get_config_var(name) + if value is None and warn: + logger.debug( + "Config variable '%s' is unset, Python ABI tag may be incorrect", name + ) + return value + + +def _normalize_string(string: str) -> str: + return string.replace(".", "_").replace("-", "_").replace(" ", "_") + + +def _abi3_applies(python_version: PythonVersion) -> bool: + """ + Determine if the Python version supports abi3. + + PEP 384 was first implemented in Python 3.2. + """ + return len(python_version) > 1 and tuple(python_version) >= (3, 2) + + +def _cpython_abis(py_version: PythonVersion, warn: bool = False) -> List[str]: + py_version = tuple(py_version) # To allow for version comparison. + abis = [] + version = _version_nodot(py_version[:2]) + debug = pymalloc = ucs4 = "" + with_debug = _get_config_var("Py_DEBUG", warn) + has_refcount = hasattr(sys, "gettotalrefcount") + # Windows doesn't set Py_DEBUG, so checking for support of debug-compiled + # extension modules is the best option. + # https://github.com/pypa/pip/issues/3383#issuecomment-173267692 + has_ext = "_d.pyd" in EXTENSION_SUFFIXES + if with_debug or (with_debug is None and (has_refcount or has_ext)): + debug = "d" + if py_version < (3, 8): + with_pymalloc = _get_config_var("WITH_PYMALLOC", warn) + if with_pymalloc or with_pymalloc is None: + pymalloc = "m" + if py_version < (3, 3): + unicode_size = _get_config_var("Py_UNICODE_SIZE", warn) + if unicode_size == 4 or ( + unicode_size is None and sys.maxunicode == 0x10FFFF + ): + ucs4 = "u" + elif debug: + # Debug builds can also load "normal" extension modules. + # We can also assume no UCS-4 or pymalloc requirement. + abis.append(f"cp{version}") + abis.insert( + 0, + "cp{version}{debug}{pymalloc}{ucs4}".format( + version=version, debug=debug, pymalloc=pymalloc, ucs4=ucs4 + ), + ) + return abis + + +def cpython_tags( + python_version: Optional[PythonVersion] = None, + abis: Optional[Iterable[str]] = None, + platforms: Optional[Iterable[str]] = None, + *, + warn: bool = False, +) -> Iterator[Tag]: + """ + Yields the tags for a CPython interpreter. + + The tags consist of: + - cp-- + - cp-abi3- + - cp-none- + - cp-abi3- # Older Python versions down to 3.2. + + If python_version only specifies a major version then user-provided ABIs and + the 'none' ABItag will be used. + + If 'abi3' or 'none' are specified in 'abis' then they will be yielded at + their normal position and not at the beginning. + """ + if not python_version: + python_version = sys.version_info[:2] + + interpreter = f"cp{_version_nodot(python_version[:2])}" + + if abis is None: + if len(python_version) > 1: + abis = _cpython_abis(python_version, warn) + else: + abis = [] + abis = list(abis) + # 'abi3' and 'none' are explicitly handled later. + for explicit_abi in ("abi3", "none"): + try: + abis.remove(explicit_abi) + except ValueError: + pass + + platforms = list(platforms or platform_tags()) + for abi in abis: + for platform_ in platforms: + yield Tag(interpreter, abi, platform_) + if _abi3_applies(python_version): + yield from (Tag(interpreter, "abi3", platform_) for platform_ in platforms) + yield from (Tag(interpreter, "none", platform_) for platform_ in platforms) + + if _abi3_applies(python_version): + for minor_version in range(python_version[1] - 1, 1, -1): + for platform_ in platforms: + interpreter = "cp{version}".format( + version=_version_nodot((python_version[0], minor_version)) + ) + yield Tag(interpreter, "abi3", platform_) + + +def _generic_abi() -> List[str]: + """ + Return the ABI tag based on EXT_SUFFIX. + """ + # The following are examples of `EXT_SUFFIX`. + # We want to keep the parts which are related to the ABI and remove the + # parts which are related to the platform: + # - linux: '.cpython-310-x86_64-linux-gnu.so' => cp310 + # - mac: '.cpython-310-darwin.so' => cp310 + # - win: '.cp310-win_amd64.pyd' => cp310 + # - win: '.pyd' => cp37 (uses _cpython_abis()) + # - pypy: '.pypy38-pp73-x86_64-linux-gnu.so' => pypy38_pp73 + # - graalpy: '.graalpy-38-native-x86_64-darwin.dylib' + # => graalpy_38_native + + ext_suffix = _get_config_var("EXT_SUFFIX", warn=True) + if not isinstance(ext_suffix, str) or ext_suffix[0] != ".": + raise SystemError("invalid sysconfig.get_config_var('EXT_SUFFIX')") + parts = ext_suffix.split(".") + if len(parts) < 3: + # CPython3.7 and earlier uses ".pyd" on Windows. + return _cpython_abis(sys.version_info[:2]) + soabi = parts[1] + if soabi.startswith("cpython"): + # non-windows + abi = "cp" + soabi.split("-")[1] + elif soabi.startswith("cp"): + # windows + abi = soabi.split("-")[0] + elif soabi.startswith("pypy"): + abi = "-".join(soabi.split("-")[:2]) + elif soabi.startswith("graalpy"): + abi = "-".join(soabi.split("-")[:3]) + elif soabi: + # pyston, ironpython, others? + abi = soabi + else: + return [] + return [_normalize_string(abi)] + + +def generic_tags( + interpreter: Optional[str] = None, + abis: Optional[Iterable[str]] = None, + platforms: Optional[Iterable[str]] = None, + *, + warn: bool = False, +) -> Iterator[Tag]: + """ + Yields the tags for a generic interpreter. + + The tags consist of: + - -- + + The "none" ABI will be added if it was not explicitly provided. + """ + if not interpreter: + interp_name = interpreter_name() + interp_version = interpreter_version(warn=warn) + interpreter = "".join([interp_name, interp_version]) + if abis is None: + abis = _generic_abi() + else: + abis = list(abis) + platforms = list(platforms or platform_tags()) + if "none" not in abis: + abis.append("none") + for abi in abis: + for platform_ in platforms: + yield Tag(interpreter, abi, platform_) + + +def _py_interpreter_range(py_version: PythonVersion) -> Iterator[str]: + """ + Yields Python versions in descending order. + + After the latest version, the major-only version will be yielded, and then + all previous versions of that major version. + """ + if len(py_version) > 1: + yield f"py{_version_nodot(py_version[:2])}" + yield f"py{py_version[0]}" + if len(py_version) > 1: + for minor in range(py_version[1] - 1, -1, -1): + yield f"py{_version_nodot((py_version[0], minor))}" + + +def compatible_tags( + python_version: Optional[PythonVersion] = None, + interpreter: Optional[str] = None, + platforms: Optional[Iterable[str]] = None, +) -> Iterator[Tag]: + """ + Yields the sequence of tags that are compatible with a specific version of Python. + + The tags consist of: + - py*-none- + - -none-any # ... if `interpreter` is provided. + - py*-none-any + """ + if not python_version: + python_version = sys.version_info[:2] + platforms = list(platforms or platform_tags()) + for version in _py_interpreter_range(python_version): + for platform_ in platforms: + yield Tag(version, "none", platform_) + if interpreter: + yield Tag(interpreter, "none", "any") + for version in _py_interpreter_range(python_version): + yield Tag(version, "none", "any") + + +def _mac_arch(arch: str, is_32bit: bool = _32_BIT_INTERPRETER) -> str: + if not is_32bit: + return arch + + if arch.startswith("ppc"): + return "ppc" + + return "i386" + + +def _mac_binary_formats(version: MacVersion, cpu_arch: str) -> List[str]: + formats = [cpu_arch] + if cpu_arch == "x86_64": + if version < (10, 4): + return [] + formats.extend(["intel", "fat64", "fat32"]) + + elif cpu_arch == "i386": + if version < (10, 4): + return [] + formats.extend(["intel", "fat32", "fat"]) + + elif cpu_arch == "ppc64": + # TODO: Need to care about 32-bit PPC for ppc64 through 10.2? + if version > (10, 5) or version < (10, 4): + return [] + formats.append("fat64") + + elif cpu_arch == "ppc": + if version > (10, 6): + return [] + formats.extend(["fat32", "fat"]) + + if cpu_arch in {"arm64", "x86_64"}: + formats.append("universal2") + + if cpu_arch in {"x86_64", "i386", "ppc64", "ppc", "intel"}: + formats.append("universal") + + return formats + + +def mac_platforms( + version: Optional[MacVersion] = None, arch: Optional[str] = None +) -> Iterator[str]: + """ + Yields the platform tags for a macOS system. + + The `version` parameter is a two-item tuple specifying the macOS version to + generate platform tags for. The `arch` parameter is the CPU architecture to + generate platform tags for. Both parameters default to the appropriate value + for the current system. + """ + version_str, _, cpu_arch = platform.mac_ver() + if version is None: + version = cast("MacVersion", tuple(map(int, version_str.split(".")[:2]))) + if version == (10, 16): + # When built against an older macOS SDK, Python will report macOS 10.16 + # instead of the real version. + version_str = subprocess.run( + [ + sys.executable, + "-sS", + "-c", + "import platform; print(platform.mac_ver()[0])", + ], + check=True, + env={"SYSTEM_VERSION_COMPAT": "0"}, + stdout=subprocess.PIPE, + text=True, + ).stdout + version = cast("MacVersion", tuple(map(int, version_str.split(".")[:2]))) + else: + version = version + if arch is None: + arch = _mac_arch(cpu_arch) + else: + arch = arch + + if (10, 0) <= version and version < (11, 0): + # Prior to Mac OS 11, each yearly release of Mac OS bumped the + # "minor" version number. The major version was always 10. + for minor_version in range(version[1], -1, -1): + compat_version = 10, minor_version + binary_formats = _mac_binary_formats(compat_version, arch) + for binary_format in binary_formats: + yield "macosx_{major}_{minor}_{binary_format}".format( + major=10, minor=minor_version, binary_format=binary_format + ) + + if version >= (11, 0): + # Starting with Mac OS 11, each yearly release bumps the major version + # number. The minor versions are now the midyear updates. + for major_version in range(version[0], 10, -1): + compat_version = major_version, 0 + binary_formats = _mac_binary_formats(compat_version, arch) + for binary_format in binary_formats: + yield "macosx_{major}_{minor}_{binary_format}".format( + major=major_version, minor=0, binary_format=binary_format + ) + + if version >= (11, 0): + # Mac OS 11 on x86_64 is compatible with binaries from previous releases. + # Arm64 support was introduced in 11.0, so no Arm binaries from previous + # releases exist. + # + # However, the "universal2" binary format can have a + # macOS version earlier than 11.0 when the x86_64 part of the binary supports + # that version of macOS. + if arch == "x86_64": + for minor_version in range(16, 3, -1): + compat_version = 10, minor_version + binary_formats = _mac_binary_formats(compat_version, arch) + for binary_format in binary_formats: + yield "macosx_{major}_{minor}_{binary_format}".format( + major=compat_version[0], + minor=compat_version[1], + binary_format=binary_format, + ) + else: + for minor_version in range(16, 3, -1): + compat_version = 10, minor_version + binary_format = "universal2" + yield "macosx_{major}_{minor}_{binary_format}".format( + major=compat_version[0], + minor=compat_version[1], + binary_format=binary_format, + ) + + +def _linux_platforms(is_32bit: bool = _32_BIT_INTERPRETER) -> Iterator[str]: + linux = _normalize_string(sysconfig.get_platform()) + if not linux.startswith("linux_"): + # we should never be here, just yield the sysconfig one and return + yield linux + return + if is_32bit: + if linux == "linux_x86_64": + linux = "linux_i686" + elif linux == "linux_aarch64": + linux = "linux_armv8l" + _, arch = linux.split("_", 1) + archs = {"armv8l": ["armv8l", "armv7l"]}.get(arch, [arch]) + yield from _manylinux.platform_tags(archs) + yield from _musllinux.platform_tags(archs) + for arch in archs: + yield f"linux_{arch}" + + +def _generic_platforms() -> Iterator[str]: + yield _normalize_string(sysconfig.get_platform()) + + +def platform_tags() -> Iterator[str]: + """ + Provides the platform tags for this installation. + """ + if platform.system() == "Darwin": + return mac_platforms() + elif platform.system() == "Linux": + return _linux_platforms() + else: + return _generic_platforms() + + +def interpreter_name() -> str: + """ + Returns the name of the running interpreter. + + Some implementations have a reserved, two-letter abbreviation which will + be returned when appropriate. + """ + name = sys.implementation.name + return INTERPRETER_SHORT_NAMES.get(name) or name + + +def interpreter_version(*, warn: bool = False) -> str: + """ + Returns the version of the running interpreter. + """ + version = _get_config_var("py_version_nodot", warn=warn) + if version: + version = str(version) + else: + version = _version_nodot(sys.version_info[:2]) + return version + + +def _version_nodot(version: PythonVersion) -> str: + return "".join(map(str, version)) + + +def sys_tags(*, warn: bool = False) -> Iterator[Tag]: + """ + Returns the sequence of tag triples for the running interpreter. + + The order of the sequence corresponds to priority order for the + interpreter, from most to least important. + """ + + interp_name = interpreter_name() + if interp_name == "cp": + yield from cpython_tags(warn=warn) + else: + yield from generic_tags() + + if interp_name == "pp": + interp = "pp3" + elif interp_name == "cp": + interp = "cp" + interpreter_version(warn=warn) + else: + interp = None + yield from compatible_tags(interpreter=interp) diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/utils.py b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/utils.py new file mode 100644 index 00000000000000..c2c2f75aa80628 --- /dev/null +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/utils.py @@ -0,0 +1,172 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import re +from typing import FrozenSet, NewType, Tuple, Union, cast + +from .tags import Tag, parse_tag +from .version import InvalidVersion, Version + +BuildTag = Union[Tuple[()], Tuple[int, str]] +NormalizedName = NewType("NormalizedName", str) + + +class InvalidName(ValueError): + """ + An invalid distribution name; users should refer to the packaging user guide. + """ + + +class InvalidWheelFilename(ValueError): + """ + An invalid wheel filename was found, users should refer to PEP 427. + """ + + +class InvalidSdistFilename(ValueError): + """ + An invalid sdist filename was found, users should refer to the packaging user guide. + """ + + +# Core metadata spec for `Name` +_validate_regex = re.compile( + r"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$", re.IGNORECASE +) +_canonicalize_regex = re.compile(r"[-_.]+") +_normalized_regex = re.compile(r"^([a-z0-9]|[a-z0-9]([a-z0-9-](?!--))*[a-z0-9])$") +# PEP 427: The build number must start with a digit. +_build_tag_regex = re.compile(r"(\d+)(.*)") + + +def canonicalize_name(name: str, *, validate: bool = False) -> NormalizedName: + if validate and not _validate_regex.match(name): + raise InvalidName(f"name is invalid: {name!r}") + # This is taken from PEP 503. + value = _canonicalize_regex.sub("-", name).lower() + return cast(NormalizedName, value) + + +def is_normalized_name(name: str) -> bool: + return _normalized_regex.match(name) is not None + + +def canonicalize_version( + version: Union[Version, str], *, strip_trailing_zero: bool = True +) -> str: + """ + This is very similar to Version.__str__, but has one subtle difference + with the way it handles the release segment. + """ + if isinstance(version, str): + try: + parsed = Version(version) + except InvalidVersion: + # Legacy versions cannot be normalized + return version + else: + parsed = version + + parts = [] + + # Epoch + if parsed.epoch != 0: + parts.append(f"{parsed.epoch}!") + + # Release segment + release_segment = ".".join(str(x) for x in parsed.release) + if strip_trailing_zero: + # NB: This strips trailing '.0's to normalize + release_segment = re.sub(r"(\.0)+$", "", release_segment) + parts.append(release_segment) + + # Pre-release + if parsed.pre is not None: + parts.append("".join(str(x) for x in parsed.pre)) + + # Post-release + if parsed.post is not None: + parts.append(f".post{parsed.post}") + + # Development release + if parsed.dev is not None: + parts.append(f".dev{parsed.dev}") + + # Local version segment + if parsed.local is not None: + parts.append(f"+{parsed.local}") + + return "".join(parts) + + +def parse_wheel_filename( + filename: str, +) -> Tuple[NormalizedName, Version, BuildTag, FrozenSet[Tag]]: + if not filename.endswith(".whl"): + raise InvalidWheelFilename( + f"Invalid wheel filename (extension must be '.whl'): {filename}" + ) + + filename = filename[:-4] + dashes = filename.count("-") + if dashes not in (4, 5): + raise InvalidWheelFilename( + f"Invalid wheel filename (wrong number of parts): {filename}" + ) + + parts = filename.split("-", dashes - 2) + name_part = parts[0] + # See PEP 427 for the rules on escaping the project name. + if "__" in name_part or re.match(r"^[\w\d._]*$", name_part, re.UNICODE) is None: + raise InvalidWheelFilename(f"Invalid project name: {filename}") + name = canonicalize_name(name_part) + + try: + version = Version(parts[1]) + except InvalidVersion as e: + raise InvalidWheelFilename( + f"Invalid wheel filename (invalid version): {filename}" + ) from e + + if dashes == 5: + build_part = parts[2] + build_match = _build_tag_regex.match(build_part) + if build_match is None: + raise InvalidWheelFilename( + f"Invalid build number: {build_part} in '{filename}'" + ) + build = cast(BuildTag, (int(build_match.group(1)), build_match.group(2))) + else: + build = () + tags = parse_tag(parts[-1]) + return (name, version, build, tags) + + +def parse_sdist_filename(filename: str) -> Tuple[NormalizedName, Version]: + if filename.endswith(".tar.gz"): + file_stem = filename[: -len(".tar.gz")] + elif filename.endswith(".zip"): + file_stem = filename[: -len(".zip")] + else: + raise InvalidSdistFilename( + f"Invalid sdist filename (extension must be '.tar.gz' or '.zip'):" + f" {filename}" + ) + + # We are requiring a PEP 440 version, which cannot contain dashes, + # so we split on the last dash. + name_part, sep, version_part = file_stem.rpartition("-") + if not sep: + raise InvalidSdistFilename(f"Invalid sdist filename: {filename}") + + name = canonicalize_name(name_part) + + try: + version = Version(version_part) + except InvalidVersion as e: + raise InvalidSdistFilename( + f"Invalid sdist filename (invalid version): {filename}" + ) from e + + return (name, version) diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/version.py b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/version.py new file mode 100644 index 00000000000000..5faab9bd0dcf28 --- /dev/null +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/packaging/version.py @@ -0,0 +1,563 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +""" +.. testsetup:: + + from packaging.version import parse, Version +""" + +import itertools +import re +from typing import Any, Callable, NamedTuple, Optional, SupportsInt, Tuple, Union + +from ._structures import Infinity, InfinityType, NegativeInfinity, NegativeInfinityType + +__all__ = ["VERSION_PATTERN", "parse", "Version", "InvalidVersion"] + +LocalType = Tuple[Union[int, str], ...] + +CmpPrePostDevType = Union[InfinityType, NegativeInfinityType, Tuple[str, int]] +CmpLocalType = Union[ + NegativeInfinityType, + Tuple[Union[Tuple[int, str], Tuple[NegativeInfinityType, Union[int, str]]], ...], +] +CmpKey = Tuple[ + int, + Tuple[int, ...], + CmpPrePostDevType, + CmpPrePostDevType, + CmpPrePostDevType, + CmpLocalType, +] +VersionComparisonMethod = Callable[[CmpKey, CmpKey], bool] + + +class _Version(NamedTuple): + epoch: int + release: Tuple[int, ...] + dev: Optional[Tuple[str, int]] + pre: Optional[Tuple[str, int]] + post: Optional[Tuple[str, int]] + local: Optional[LocalType] + + +def parse(version: str) -> "Version": + """Parse the given version string. + + >>> parse('1.0.dev1') + + + :param version: The version string to parse. + :raises InvalidVersion: When the version string is not a valid version. + """ + return Version(version) + + +class InvalidVersion(ValueError): + """Raised when a version string is not a valid version. + + >>> Version("invalid") + Traceback (most recent call last): + ... + packaging.version.InvalidVersion: Invalid version: 'invalid' + """ + + +class _BaseVersion: + _key: Tuple[Any, ...] + + def __hash__(self) -> int: + return hash(self._key) + + # Please keep the duplicated `isinstance` check + # in the six comparisons hereunder + # unless you find a way to avoid adding overhead function calls. + def __lt__(self, other: "_BaseVersion") -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key < other._key + + def __le__(self, other: "_BaseVersion") -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key <= other._key + + def __eq__(self, other: object) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key == other._key + + def __ge__(self, other: "_BaseVersion") -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key >= other._key + + def __gt__(self, other: "_BaseVersion") -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key > other._key + + def __ne__(self, other: object) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key != other._key + + +# Deliberately not anchored to the start and end of the string, to make it +# easier for 3rd party code to reuse +_VERSION_PATTERN = r""" + v? + (?: + (?:(?P[0-9]+)!)? # epoch + (?P[0-9]+(?:\.[0-9]+)*) # release segment + (?P
                                          # pre-release
+            [-_\.]?
+            (?Palpha|a|beta|b|preview|pre|c|rc)
+            [-_\.]?
+            (?P[0-9]+)?
+        )?
+        (?P                                         # post release
+            (?:-(?P[0-9]+))
+            |
+            (?:
+                [-_\.]?
+                (?Ppost|rev|r)
+                [-_\.]?
+                (?P[0-9]+)?
+            )
+        )?
+        (?P                                          # dev release
+            [-_\.]?
+            (?Pdev)
+            [-_\.]?
+            (?P[0-9]+)?
+        )?
+    )
+    (?:\+(?P[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?       # local version
+"""
+
+VERSION_PATTERN = _VERSION_PATTERN
+"""
+A string containing the regular expression used to match a valid version.
+
+The pattern is not anchored at either end, and is intended for embedding in larger
+expressions (for example, matching a version number as part of a file name). The
+regular expression should be compiled with the ``re.VERBOSE`` and ``re.IGNORECASE``
+flags set.
+
+:meta hide-value:
+"""
+
+
+class Version(_BaseVersion):
+    """This class abstracts handling of a project's versions.
+
+    A :class:`Version` instance is comparison aware and can be compared and
+    sorted using the standard Python interfaces.
+
+    >>> v1 = Version("1.0a5")
+    >>> v2 = Version("1.0")
+    >>> v1
+    
+    >>> v2
+    
+    >>> v1 < v2
+    True
+    >>> v1 == v2
+    False
+    >>> v1 > v2
+    False
+    >>> v1 >= v2
+    False
+    >>> v1 <= v2
+    True
+    """
+
+    _regex = re.compile(r"^\s*" + VERSION_PATTERN + r"\s*$", re.VERBOSE | re.IGNORECASE)
+    _key: CmpKey
+
+    def __init__(self, version: str) -> None:
+        """Initialize a Version object.
+
+        :param version:
+            The string representation of a version which will be parsed and normalized
+            before use.
+        :raises InvalidVersion:
+            If the ``version`` does not conform to PEP 440 in any way then this
+            exception will be raised.
+        """
+
+        # Validate the version and parse it into pieces
+        match = self._regex.search(version)
+        if not match:
+            raise InvalidVersion(f"Invalid version: '{version}'")
+
+        # Store the parsed out pieces of the version
+        self._version = _Version(
+            epoch=int(match.group("epoch")) if match.group("epoch") else 0,
+            release=tuple(int(i) for i in match.group("release").split(".")),
+            pre=_parse_letter_version(match.group("pre_l"), match.group("pre_n")),
+            post=_parse_letter_version(
+                match.group("post_l"), match.group("post_n1") or match.group("post_n2")
+            ),
+            dev=_parse_letter_version(match.group("dev_l"), match.group("dev_n")),
+            local=_parse_local_version(match.group("local")),
+        )
+
+        # Generate a key which will be used for sorting
+        self._key = _cmpkey(
+            self._version.epoch,
+            self._version.release,
+            self._version.pre,
+            self._version.post,
+            self._version.dev,
+            self._version.local,
+        )
+
+    def __repr__(self) -> str:
+        """A representation of the Version that shows all internal state.
+
+        >>> Version('1.0.0')
+        
+        """
+        return f""
+
+    def __str__(self) -> str:
+        """A string representation of the version that can be rounded-tripped.
+
+        >>> str(Version("1.0a5"))
+        '1.0a5'
+        """
+        parts = []
+
+        # Epoch
+        if self.epoch != 0:
+            parts.append(f"{self.epoch}!")
+
+        # Release segment
+        parts.append(".".join(str(x) for x in self.release))
+
+        # Pre-release
+        if self.pre is not None:
+            parts.append("".join(str(x) for x in self.pre))
+
+        # Post-release
+        if self.post is not None:
+            parts.append(f".post{self.post}")
+
+        # Development release
+        if self.dev is not None:
+            parts.append(f".dev{self.dev}")
+
+        # Local version segment
+        if self.local is not None:
+            parts.append(f"+{self.local}")
+
+        return "".join(parts)
+
+    @property
+    def epoch(self) -> int:
+        """The epoch of the version.
+
+        >>> Version("2.0.0").epoch
+        0
+        >>> Version("1!2.0.0").epoch
+        1
+        """
+        return self._version.epoch
+
+    @property
+    def release(self) -> Tuple[int, ...]:
+        """The components of the "release" segment of the version.
+
+        >>> Version("1.2.3").release
+        (1, 2, 3)
+        >>> Version("2.0.0").release
+        (2, 0, 0)
+        >>> Version("1!2.0.0.post0").release
+        (2, 0, 0)
+
+        Includes trailing zeroes but not the epoch or any pre-release / development /
+        post-release suffixes.
+        """
+        return self._version.release
+
+    @property
+    def pre(self) -> Optional[Tuple[str, int]]:
+        """The pre-release segment of the version.
+
+        >>> print(Version("1.2.3").pre)
+        None
+        >>> Version("1.2.3a1").pre
+        ('a', 1)
+        >>> Version("1.2.3b1").pre
+        ('b', 1)
+        >>> Version("1.2.3rc1").pre
+        ('rc', 1)
+        """
+        return self._version.pre
+
+    @property
+    def post(self) -> Optional[int]:
+        """The post-release number of the version.
+
+        >>> print(Version("1.2.3").post)
+        None
+        >>> Version("1.2.3.post1").post
+        1
+        """
+        return self._version.post[1] if self._version.post else None
+
+    @property
+    def dev(self) -> Optional[int]:
+        """The development number of the version.
+
+        >>> print(Version("1.2.3").dev)
+        None
+        >>> Version("1.2.3.dev1").dev
+        1
+        """
+        return self._version.dev[1] if self._version.dev else None
+
+    @property
+    def local(self) -> Optional[str]:
+        """The local version segment of the version.
+
+        >>> print(Version("1.2.3").local)
+        None
+        >>> Version("1.2.3+abc").local
+        'abc'
+        """
+        if self._version.local:
+            return ".".join(str(x) for x in self._version.local)
+        else:
+            return None
+
+    @property
+    def public(self) -> str:
+        """The public portion of the version.
+
+        >>> Version("1.2.3").public
+        '1.2.3'
+        >>> Version("1.2.3+abc").public
+        '1.2.3'
+        >>> Version("1.2.3+abc.dev1").public
+        '1.2.3'
+        """
+        return str(self).split("+", 1)[0]
+
+    @property
+    def base_version(self) -> str:
+        """The "base version" of the version.
+
+        >>> Version("1.2.3").base_version
+        '1.2.3'
+        >>> Version("1.2.3+abc").base_version
+        '1.2.3'
+        >>> Version("1!1.2.3+abc.dev1").base_version
+        '1!1.2.3'
+
+        The "base version" is the public version of the project without any pre or post
+        release markers.
+        """
+        parts = []
+
+        # Epoch
+        if self.epoch != 0:
+            parts.append(f"{self.epoch}!")
+
+        # Release segment
+        parts.append(".".join(str(x) for x in self.release))
+
+        return "".join(parts)
+
+    @property
+    def is_prerelease(self) -> bool:
+        """Whether this version is a pre-release.
+
+        >>> Version("1.2.3").is_prerelease
+        False
+        >>> Version("1.2.3a1").is_prerelease
+        True
+        >>> Version("1.2.3b1").is_prerelease
+        True
+        >>> Version("1.2.3rc1").is_prerelease
+        True
+        >>> Version("1.2.3dev1").is_prerelease
+        True
+        """
+        return self.dev is not None or self.pre is not None
+
+    @property
+    def is_postrelease(self) -> bool:
+        """Whether this version is a post-release.
+
+        >>> Version("1.2.3").is_postrelease
+        False
+        >>> Version("1.2.3.post1").is_postrelease
+        True
+        """
+        return self.post is not None
+
+    @property
+    def is_devrelease(self) -> bool:
+        """Whether this version is a development release.
+
+        >>> Version("1.2.3").is_devrelease
+        False
+        >>> Version("1.2.3.dev1").is_devrelease
+        True
+        """
+        return self.dev is not None
+
+    @property
+    def major(self) -> int:
+        """The first item of :attr:`release` or ``0`` if unavailable.
+
+        >>> Version("1.2.3").major
+        1
+        """
+        return self.release[0] if len(self.release) >= 1 else 0
+
+    @property
+    def minor(self) -> int:
+        """The second item of :attr:`release` or ``0`` if unavailable.
+
+        >>> Version("1.2.3").minor
+        2
+        >>> Version("1").minor
+        0
+        """
+        return self.release[1] if len(self.release) >= 2 else 0
+
+    @property
+    def micro(self) -> int:
+        """The third item of :attr:`release` or ``0`` if unavailable.
+
+        >>> Version("1.2.3").micro
+        3
+        >>> Version("1").micro
+        0
+        """
+        return self.release[2] if len(self.release) >= 3 else 0
+
+
+def _parse_letter_version(
+    letter: Optional[str], number: Union[str, bytes, SupportsInt, None]
+) -> Optional[Tuple[str, int]]:
+
+    if letter:
+        # We consider there to be an implicit 0 in a pre-release if there is
+        # not a numeral associated with it.
+        if number is None:
+            number = 0
+
+        # We normalize any letters to their lower case form
+        letter = letter.lower()
+
+        # We consider some words to be alternate spellings of other words and
+        # in those cases we want to normalize the spellings to our preferred
+        # spelling.
+        if letter == "alpha":
+            letter = "a"
+        elif letter == "beta":
+            letter = "b"
+        elif letter in ["c", "pre", "preview"]:
+            letter = "rc"
+        elif letter in ["rev", "r"]:
+            letter = "post"
+
+        return letter, int(number)
+    if not letter and number:
+        # We assume if we are given a number, but we are not given a letter
+        # then this is using the implicit post release syntax (e.g. 1.0-1)
+        letter = "post"
+
+        return letter, int(number)
+
+    return None
+
+
+_local_version_separators = re.compile(r"[\._-]")
+
+
+def _parse_local_version(local: Optional[str]) -> Optional[LocalType]:
+    """
+    Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
+    """
+    if local is not None:
+        return tuple(
+            part.lower() if not part.isdigit() else int(part)
+            for part in _local_version_separators.split(local)
+        )
+    return None
+
+
+def _cmpkey(
+    epoch: int,
+    release: Tuple[int, ...],
+    pre: Optional[Tuple[str, int]],
+    post: Optional[Tuple[str, int]],
+    dev: Optional[Tuple[str, int]],
+    local: Optional[LocalType],
+) -> CmpKey:
+
+    # When we compare a release version, we want to compare it with all of the
+    # trailing zeros removed. So we'll use a reverse the list, drop all the now
+    # leading zeros until we come to something non zero, then take the rest
+    # re-reverse it back into the correct order and make it a tuple and use
+    # that for our sorting key.
+    _release = tuple(
+        reversed(list(itertools.dropwhile(lambda x: x == 0, reversed(release))))
+    )
+
+    # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
+    # We'll do this by abusing the pre segment, but we _only_ want to do this
+    # if there is not a pre or a post segment. If we have one of those then
+    # the normal sorting rules will handle this case correctly.
+    if pre is None and post is None and dev is not None:
+        _pre: CmpPrePostDevType = NegativeInfinity
+    # Versions without a pre-release (except as noted above) should sort after
+    # those with one.
+    elif pre is None:
+        _pre = Infinity
+    else:
+        _pre = pre
+
+    # Versions without a post segment should sort before those with one.
+    if post is None:
+        _post: CmpPrePostDevType = NegativeInfinity
+
+    else:
+        _post = post
+
+    # Versions without a development segment should sort after those with one.
+    if dev is None:
+        _dev: CmpPrePostDevType = Infinity
+
+    else:
+        _dev = dev
+
+    if local is None:
+        # Versions without a local segment should sort before those with one.
+        _local: CmpLocalType = NegativeInfinity
+    else:
+        # Versions with a local segment need that segment parsed to implement
+        # the sorting rules in PEP440.
+        # - Alpha numeric segments sort before numeric segments
+        # - Alpha numeric segments sort lexicographically
+        # - Numeric segments sort numerically
+        # - Shorter versions sort before longer versions when the prefixes
+        #   match exactly
+        _local = tuple(
+            (i, "") if isinstance(i, int) else (NegativeInfinity, i) for i in local
+        )
+
+    return epoch, _release, _pre, _post, _dev, _local
diff --git a/deps/npm/node_modules/node-gyp/gyp/pyproject.toml b/deps/npm/node_modules/node-gyp/gyp/pyproject.toml
index d8a5451520cc3c..0c25d0b3c1a065 100644
--- a/deps/npm/node_modules/node-gyp/gyp/pyproject.toml
+++ b/deps/npm/node_modules/node-gyp/gyp/pyproject.toml
@@ -4,14 +4,16 @@ build-backend = "setuptools.build_meta"
 
 [project]
 name = "gyp-next"
-version = "0.14.0"
+version = "0.16.1"
 authors = [
   { name="Node.js contributors", email="ryzokuken@disroot.org" },
 ]
 description = "A fork of the GYP build system for use in the Node.js projects"
 readme = "README.md"
 license = { file="LICENSE" }
-requires-python = ">=3.6"
+requires-python = ">=3.8"
+# The Python module "packaging" is vendored in the "pylib/packaging" directory to support Python >= 3.12.
+# dependencies = ["packaging>=23.1"]  # Uncomment this line if the vendored version is removed.
 classifiers = [
     "Development Status :: 3 - Alpha",
     "Environment :: Console",
@@ -20,15 +22,14 @@ classifiers = [
     "Natural Language :: English",
     "Programming Language :: Python",
     "Programming Language :: Python :: 3",
-    "Programming Language :: Python :: 3.6",
-    "Programming Language :: Python :: 3.7",
     "Programming Language :: Python :: 3.8",
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.10",
+    "Programming Language :: Python :: 3.11",
 ]
 
 [project.optional-dependencies]
-dev = ["flake8", "pytest"]
+dev = ["flake8", "ruff", "pytest"]
 
 [project.scripts]
 gyp = "gyp:script_main"
@@ -36,6 +37,83 @@ gyp = "gyp:script_main"
 [project.urls]
 "Homepage" = "https://github.com/nodejs/gyp-next"
 
+[tool.ruff]
+select = [
+  "C4",   # flake8-comprehensions
+  "C90",  # McCabe cyclomatic complexity
+  "DTZ",  # flake8-datetimez
+  "E",    # pycodestyle
+  "F",    # Pyflakes
+  "G",    # flake8-logging-format
+  "ICN",  # flake8-import-conventions
+  "INT",  # flake8-gettext
+  "PL",   # Pylint
+  "PYI",  # flake8-pyi
+  "RSE",  # flake8-raise
+  "RUF",  # Ruff-specific rules
+  "T10",  # flake8-debugger
+  "TCH",  # flake8-type-checking
+  "TID",  # flake8-tidy-imports
+  "UP",   # pyupgrade
+  "W",    # pycodestyle
+  "YTT",  # flake8-2020
+  # "A",    # flake8-builtins
+  # "ANN",  # flake8-annotations
+  # "ARG",  # flake8-unused-arguments
+  # "B",    # flake8-bugbear
+  # "BLE",  # flake8-blind-except
+  # "COM",  # flake8-commas
+  # "D",    # pydocstyle
+  # "DJ",   # flake8-django
+  # "EM",   # flake8-errmsg
+  # "ERA",  # eradicate
+  # "EXE",  # flake8-executable
+  # "FBT",  # flake8-boolean-trap
+  # "I",    # isort
+  # "INP",  # flake8-no-pep420
+  # "ISC",  # flake8-implicit-str-concat
+  # "N",    # pep8-naming
+  # "NPY",  # NumPy-specific rules
+  # "PD",   # pandas-vet
+  # "PGH",  # pygrep-hooks
+  # "PIE",  # flake8-pie
+  # "PT",   # flake8-pytest-style
+  # "PTH",  # flake8-use-pathlib
+  # "Q",    # flake8-quotes
+  # "RET",  # flake8-return
+  # "S",    # flake8-bandit
+  # "SIM",  # flake8-simplify
+  # "SLF",  # flake8-self
+  # "T20",  # flake8-print
+  # "TRY",  # tryceratops
+]
+ignore = [
+  "E721",
+  "PLC1901",
+  "PLR0402",
+  "PLR1714",
+  "PLR2004",
+  "PLR5501",
+  "PLW0603",
+  "PLW2901",
+  "PYI024",
+  "RUF005",
+  "RUF012",
+  "UP031",
+]
+extend-exclude = ["pylib/packaging"]
+line-length = 88
+target-version = "py37"
+
+[tool.ruff.mccabe]
+max-complexity = 101
+
+[tool.ruff.pylint]
+max-args = 11
+max-branches = 108
+max-returns = 10
+max-statements = 286
+
 [tool.setuptools]
 package-dir = {"" = "pylib"}
 packages = ["gyp", "gyp.generator"]
diff --git a/deps/npm/node_modules/node-gyp/gyp/tools/README b/deps/npm/node_modules/node-gyp/gyp/tools/README
deleted file mode 100644
index 84a73d15214b68..00000000000000
--- a/deps/npm/node_modules/node-gyp/gyp/tools/README
+++ /dev/null
@@ -1,15 +0,0 @@
-pretty_vcproj:
-  Usage: pretty_vcproj.py "c:\path\to\vcproj.vcproj" [key1=value1] [key2=value2]
-
-  They key/value pair are used to resolve vsprops name.
-
-  For example, if I want to diff the base.vcproj project:
-
-  pretty_vcproj.py z:\dev\src-chrome\src\base\build\base.vcproj "$(SolutionDir)=z:\dev\src-chrome\src\chrome\\" "$(CHROMIUM_BUILD)=" "$(CHROME_BUILD_TYPE)=" > original.txt
-  pretty_vcproj.py z:\dev\src-chrome\src\base\base_gyp.vcproj "$(SolutionDir)=z:\dev\src-chrome\src\chrome\\" "$(CHROMIUM_BUILD)=" "$(CHROME_BUILD_TYPE)=" > gyp.txt
-
-  And you can use your favorite diff tool to see the changes.
-
-  Note: In the case of base.vcproj, the original vcproj is one level up the generated one.
-        I suggest you do a search and replace for '"..\' and replace it with '"' in original.txt
-        before you perform the diff.
\ No newline at end of file
diff --git a/deps/npm/node_modules/node-gyp/gyp/tools/Xcode/README b/deps/npm/node_modules/node-gyp/gyp/tools/Xcode/README
deleted file mode 100644
index 2492a2c2f8f170..00000000000000
--- a/deps/npm/node_modules/node-gyp/gyp/tools/Xcode/README
+++ /dev/null
@@ -1,5 +0,0 @@
-Specifications contains syntax formatters for Xcode 3. These do not appear to be supported yet on Xcode 4. To use these with Xcode 3 please install both the gyp.pbfilespec and gyp.xclangspec files in
-
-~/Library/Application Support/Developer/Shared/Xcode/Specifications/
-
-and restart Xcode.
\ No newline at end of file
diff --git a/deps/npm/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.pbfilespec b/deps/npm/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.pbfilespec
deleted file mode 100644
index 85e2e268a51b76..00000000000000
--- a/deps/npm/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.pbfilespec
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-	gyp.pbfilespec
-	GYP source file spec for Xcode 3
-
-	There is not much documentation available regarding the format
-	of .pbfilespec files. As a starting point, see for instance the
-	outdated documentation at:
-	http://maxao.free.fr/xcode-plugin-interface/specifications.html
-	and the files in:
-	/Developer/Library/PrivateFrameworks/XcodeEdit.framework/Versions/A/Resources/
-
-	Place this file in directory:
-	~/Library/Application Support/Developer/Shared/Xcode/Specifications/
-*/
-
-(
-	{
-		Identifier = sourcecode.gyp;
-		BasedOn = sourcecode;
-		Name = "GYP Files";
-		Extensions = ("gyp", "gypi");
-		MIMETypes = ("text/gyp");
-		Language = "xcode.lang.gyp";
-		IsTextFile = YES;
-		IsSourceFile = YES;
-	}
-)
diff --git a/deps/npm/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.xclangspec b/deps/npm/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.xclangspec
deleted file mode 100644
index 3b3506d319e0f2..00000000000000
--- a/deps/npm/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.xclangspec
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
-	Copyright (c) 2011 Google Inc. All rights reserved.
-	Use of this source code is governed by a BSD-style license that can be
-	found in the LICENSE file.
-	
-	gyp.xclangspec
-	GYP language specification for Xcode 3
-
-	There is not much documentation available regarding the format
-	of .xclangspec files. As a starting point, see for instance the
-	outdated documentation at:
-	http://maxao.free.fr/xcode-plugin-interface/specifications.html
-	and the files in:
-	/Developer/Library/PrivateFrameworks/XcodeEdit.framework/Versions/A/Resources/
-
-	Place this file in directory:
-	~/Library/Application Support/Developer/Shared/Xcode/Specifications/
-*/
-
-(
-
-    {
-        Identifier = "xcode.lang.gyp.keyword";
-        Syntax = {
-            Words = (
-                "and",
-                "or",
-                " (caar gyp-parse-history) target-point)
-    (setq gyp-parse-history (cdr gyp-parse-history))))
-
-(defun gyp-parse-point ()
-  "The point of the last parse state added by gyp-parse-to."
-  (caar gyp-parse-history))
-
-(defun gyp-parse-sections ()
-  "A list of section symbols holding at the last parse state point."
-  (cdar gyp-parse-history))
-
-(defun gyp-inside-dictionary-p ()
-  "Predicate returning true if the parser is inside a dictionary."
-  (not (eq (cadar gyp-parse-history) 'list)))
-
-(defun gyp-add-parse-history (point sections)
-  "Add parse state SECTIONS to the parse history at POINT so that parsing can be
-   resumed instantly."
-  (while (>= (caar gyp-parse-history) point)
-    (setq gyp-parse-history (cdr gyp-parse-history)))
-  (setq gyp-parse-history (cons (cons point sections) gyp-parse-history)))
-
-(defun gyp-parse-to (target-point)
-  "Parses from (point) to TARGET-POINT adding the parse state information to
-   gyp-parse-state-history. Parsing stops if TARGET-POINT is reached or if a
-   string literal has been parsed. Returns nil if no further parsing can be
-   done, otherwise returns the position of the start of a parsed string, leaving
-   the point at the end of the string."
-  (let ((parsing t)
-        string-start)
-    (while parsing
-      (setq string-start nil)
-      ;; Parse up to a character that starts a sexp, or if the nesting
-      ;; level decreases.
-      (let ((state (parse-partial-sexp (gyp-parse-point)
-                                       target-point
-                                       -1
-                                       t))
-            (sections (gyp-parse-sections)))
-        (if (= (nth 0 state) -1)
-            (setq sections (cdr sections)) ; pop out a level
-          (cond ((looking-at-p "['\"]") ; a string
-                 (setq string-start (point))
-                 (goto-char (scan-sexps (point) 1))
-                 (if (gyp-inside-dictionary-p)
-                     ;; Look for sections inside a dictionary
-                     (let ((section (gyp-section-name
-                                     (buffer-substring-no-properties
-                                      (+ 1 string-start)
-                                      (- (point) 1)))))
-                       (setq sections (cons section (cdr sections)))))
-                 ;; Stop after the string so it can be fontified.
-                 (setq target-point (point)))
-                ((looking-at-p "{")
-                 ;; Inside a dictionary. Increase nesting.
-                 (forward-char 1)
-                 (setq sections (cons 'unknown sections)))
-                ((looking-at-p "\\[")
-                 ;; Inside a list. Increase nesting
-                 (forward-char 1)
-                 (setq sections (cons 'list sections)))
-                ((not (eobp))
-                 ;; other
-                 (forward-char 1))))
-        (gyp-add-parse-history (point) sections)
-        (setq parsing (< (point) target-point))))
-    string-start))
-
-(defun gyp-section-at-point ()
-  "Transform the last parse state, which is a list of nested sections and return
-   the section symbol that should be used to determine font-lock information for
-   the string. Can return nil indicating the string should not have any attached
-   section."
-  (let ((sections (gyp-parse-sections)))
-    (cond
-     ((eq (car sections) 'conditions)
-      ;; conditions can occur in a variables section, but we still want to
-      ;; highlight it as a keyword.
-      nil)
-     ((and (eq (car sections) 'list)
-           (eq (cadr sections) 'list))
-      ;; conditions and sources can have items in [[ ]]
-      (caddr sections))
-     (t (cadr sections)))))
-
-(defun gyp-section-match (limit)
-  "Parse from (point) to LIMIT returning by means of match data what was
-   matched. The group of the match indicates what style font-lock should apply.
-   See also `gyp-add-font-lock-keywords'."
-  (gyp-invalidate-parse-states-after (point))
-  (let ((group nil)
-        (string-start t))
-    (while (and (< (point) limit)
-                (not group)
-                string-start)
-      (setq string-start (gyp-parse-to limit))
-      (if string-start
-          (setq group (cl-case (gyp-section-at-point)
-                        ('dependencies 1)
-                        ('variables 2)
-                        ('conditions 2)
-                        ('sources 3)
-                        ('defines 4)
-                        (nil nil)))))
-    (if group
-        (progn
-          ;; Set the match data to indicate to the font-lock mechanism the
-          ;; highlighting to be performed.
-          (set-match-data (append (list string-start (point))
-                                  (make-list (* (1- group) 2) nil)
-                                  (list (1+ string-start) (1- (point)))))
-          t))))
-
-;;; Please see http://code.google.com/p/gyp/wiki/GypLanguageSpecification for
-;;; canonical list of keywords.
-(defun gyp-add-font-lock-keywords ()
-  "Add gyp-mode keywords to font-lock mechanism."
-  ;; TODO(jknotten): Move all the keyword highlighting into gyp-section-match
-  ;; so that we can do the font-locking in a single font-lock pass.
-  (font-lock-add-keywords
-   nil
-   (list
-    ;; Top-level keywords
-    (list (concat "['\"]\\("
-              (regexp-opt (list "action" "action_name" "actions" "cflags"
-                                "cflags_cc" "conditions" "configurations"
-                                "copies" "defines" "dependencies" "destination"
-                                "direct_dependent_settings"
-                                "export_dependent_settings" "extension" "files"
-                                "include_dirs" "includes" "inputs" "ldflags" "libraries"
-                                "link_settings" "mac_bundle" "message"
-                                "msvs_external_rule" "outputs" "product_name"
-                                "process_outputs_as_sources" "rules" "rule_name"
-                                "sources" "suppress_wildcard"
-                                "target_conditions" "target_defaults"
-                                "target_defines" "target_name" "toolsets"
-                                "targets" "type" "variables" "xcode_settings"))
-              "[!/+=]?\\)") 1 'font-lock-keyword-face t)
-    ;; Type of target
-    (list (concat "['\"]\\("
-              (regexp-opt (list "loadable_module" "static_library"
-                                "shared_library" "executable" "none"))
-              "\\)") 1 'font-lock-type-face t)
-    (list "\\(?:target\\|action\\)_name['\"]\\s-*:\\s-*['\"]\\([^ '\"]*\\)" 1
-          'font-lock-function-name-face t)
-    (list 'gyp-section-match
-          (list 1 'font-lock-function-name-face t t) ; dependencies
-          (list 2 'font-lock-variable-name-face t t) ; variables, conditions
-          (list 3 'font-lock-constant-face t t) ; sources
-          (list 4 'font-lock-preprocessor-face t t)) ; preprocessor
-    ;; Variable expansion
-    (list "<@?(\\([^\n )]+\\))" 1 'font-lock-variable-name-face t)
-    ;; Command expansion
-    (list " "{dst}"')
-
-    print("}")
-
-
-def main():
-    if len(sys.argv) < 2:
-        print(__doc__, file=sys.stderr)
-        print(file=sys.stderr)
-        print("usage: %s target1 target2..." % (sys.argv[0]), file=sys.stderr)
-        return 1
-
-    edges = LoadEdges("dump.json", sys.argv[1:])
-
-    WriteGraph(edges)
-    return 0
-
-
-if __name__ == "__main__":
-    sys.exit(main())
diff --git a/deps/npm/node_modules/node-gyp/gyp/tools/pretty_gyp.py b/deps/npm/node_modules/node-gyp/gyp/tools/pretty_gyp.py
deleted file mode 100755
index 6eef3a1bbf02a5..00000000000000
--- a/deps/npm/node_modules/node-gyp/gyp/tools/pretty_gyp.py
+++ /dev/null
@@ -1,156 +0,0 @@
-#!/usr/bin/env python3
-
-# Copyright (c) 2012 Google Inc. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Pretty-prints the contents of a GYP file."""
-
-
-import sys
-import re
-
-
-# Regex to remove comments when we're counting braces.
-COMMENT_RE = re.compile(r"\s*#.*")
-
-# Regex to remove quoted strings when we're counting braces.
-# It takes into account quoted quotes, and makes sure that the quotes match.
-# NOTE: It does not handle quotes that span more than one line, or
-# cases where an escaped quote is preceded by an escaped backslash.
-QUOTE_RE_STR = r'(?P[\'"])(.*?)(? 0:
-        after = True
-
-    # This catches the special case of a closing brace having something
-    # other than just whitespace ahead of it -- we don't want to
-    # unindent that until after this line is printed so it stays with
-    # the previous indentation level.
-    if cnt < 0 and closing_prefix_re.match(stripline):
-        after = True
-    return (cnt, after)
-
-
-def prettyprint_input(lines):
-    """Does the main work of indenting the input based on the brace counts."""
-    indent = 0
-    basic_offset = 2
-    for line in lines:
-        if COMMENT_RE.match(line):
-            print(line)
-        else:
-            line = line.strip("\r\n\t ")  # Otherwise doesn't strip \r on Unix.
-            if len(line) > 0:
-                (brace_diff, after) = count_braces(line)
-                if brace_diff != 0:
-                    if after:
-                        print(" " * (basic_offset * indent) + line)
-                        indent += brace_diff
-                    else:
-                        indent += brace_diff
-                        print(" " * (basic_offset * indent) + line)
-                else:
-                    print(" " * (basic_offset * indent) + line)
-            else:
-                print("")
-
-
-def main():
-    if len(sys.argv) > 1:
-        data = open(sys.argv[1]).read().splitlines()
-    else:
-        data = sys.stdin.read().splitlines()
-    # Split up the double braces.
-    lines = split_double_braces(data)
-
-    # Indent and print the output.
-    prettyprint_input(lines)
-    return 0
-
-
-if __name__ == "__main__":
-    sys.exit(main())
diff --git a/deps/npm/node_modules/node-gyp/gyp/tools/pretty_sln.py b/deps/npm/node_modules/node-gyp/gyp/tools/pretty_sln.py
deleted file mode 100755
index 6ca0cd12a7ba06..00000000000000
--- a/deps/npm/node_modules/node-gyp/gyp/tools/pretty_sln.py
+++ /dev/null
@@ -1,181 +0,0 @@
-#!/usr/bin/env python3
-
-# Copyright (c) 2012 Google Inc. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Prints the information in a sln file in a diffable way.
-
-   It first outputs each projects in alphabetical order with their
-   dependencies.
-
-   Then it outputs a possible build order.
-"""
-
-
-import os
-import re
-import sys
-import pretty_vcproj
-
-__author__ = "nsylvain (Nicolas Sylvain)"
-
-
-def BuildProject(project, built, projects, deps):
-    # if all dependencies are done, we can build it, otherwise we try to build the
-    # dependency.
-    # This is not infinite-recursion proof.
-    for dep in deps[project]:
-        if dep not in built:
-            BuildProject(dep, built, projects, deps)
-    print(project)
-    built.append(project)
-
-
-def ParseSolution(solution_file):
-    # All projects, their clsid and paths.
-    projects = dict()
-
-    # A list of dependencies associated with a project.
-    dependencies = dict()
-
-    # Regular expressions that matches the SLN format.
-    # The first line of a project definition.
-    begin_project = re.compile(
-        r'^Project\("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942'
-        r'}"\) = "(.*)", "(.*)", "(.*)"$'
-    )
-    # The last line of a project definition.
-    end_project = re.compile("^EndProject$")
-    # The first line of a dependency list.
-    begin_dep = re.compile(r"ProjectSection\(ProjectDependencies\) = postProject$")
-    # The last line of a dependency list.
-    end_dep = re.compile("EndProjectSection$")
-    # A line describing a dependency.
-    dep_line = re.compile(" *({.*}) = ({.*})$")
-
-    in_deps = False
-    solution = open(solution_file)
-    for line in solution:
-        results = begin_project.search(line)
-        if results:
-            # Hack to remove icu because the diff is too different.
-            if results.group(1).find("icu") != -1:
-                continue
-            # We remove "_gyp" from the names because it helps to diff them.
-            current_project = results.group(1).replace("_gyp", "")
-            projects[current_project] = [
-                results.group(2).replace("_gyp", ""),
-                results.group(3),
-                results.group(2),
-            ]
-            dependencies[current_project] = []
-            continue
-
-        results = end_project.search(line)
-        if results:
-            current_project = None
-            continue
-
-        results = begin_dep.search(line)
-        if results:
-            in_deps = True
-            continue
-
-        results = end_dep.search(line)
-        if results:
-            in_deps = False
-            continue
-
-        results = dep_line.search(line)
-        if results and in_deps and current_project:
-            dependencies[current_project].append(results.group(1))
-            continue
-
-    # Change all dependencies clsid to name instead.
-    for project in dependencies:
-        # For each dependencies in this project
-        new_dep_array = []
-        for dep in dependencies[project]:
-            # Look for the project name matching this cldis
-            for project_info in projects:
-                if projects[project_info][1] == dep:
-                    new_dep_array.append(project_info)
-        dependencies[project] = sorted(new_dep_array)
-
-    return (projects, dependencies)
-
-
-def PrintDependencies(projects, deps):
-    print("---------------------------------------")
-    print("Dependencies for all projects")
-    print("---------------------------------------")
-    print("--                                   --")
-
-    for (project, dep_list) in sorted(deps.items()):
-        print("Project : %s" % project)
-        print("Path : %s" % projects[project][0])
-        if dep_list:
-            for dep in dep_list:
-                print("  - %s" % dep)
-        print("")
-
-    print("--                                   --")
-
-
-def PrintBuildOrder(projects, deps):
-    print("---------------------------------------")
-    print("Build order                            ")
-    print("---------------------------------------")
-    print("--                                   --")
-
-    built = []
-    for (project, _) in sorted(deps.items()):
-        if project not in built:
-            BuildProject(project, built, projects, deps)
-
-    print("--                                   --")
-
-
-def PrintVCProj(projects):
-
-    for project in projects:
-        print("-------------------------------------")
-        print("-------------------------------------")
-        print(project)
-        print(project)
-        print(project)
-        print("-------------------------------------")
-        print("-------------------------------------")
-
-        project_path = os.path.abspath(
-            os.path.join(os.path.dirname(sys.argv[1]), projects[project][2])
-        )
-
-        pretty = pretty_vcproj
-        argv = [
-            "",
-            project_path,
-            "$(SolutionDir)=%s\\" % os.path.dirname(sys.argv[1]),
-        ]
-        argv.extend(sys.argv[3:])
-        pretty.main(argv)
-
-
-def main():
-    # check if we have exactly 1 parameter.
-    if len(sys.argv) < 2:
-        print('Usage: %s "c:\\path\\to\\project.sln"' % sys.argv[0])
-        return 1
-
-    (projects, deps) = ParseSolution(sys.argv[1])
-    PrintDependencies(projects, deps)
-    PrintBuildOrder(projects, deps)
-
-    if "--recursive" in sys.argv:
-        PrintVCProj(projects)
-    return 0
-
-
-if __name__ == "__main__":
-    sys.exit(main())
diff --git a/deps/npm/node_modules/node-gyp/gyp/tools/pretty_vcproj.py b/deps/npm/node_modules/node-gyp/gyp/tools/pretty_vcproj.py
deleted file mode 100755
index 00d32debda51f0..00000000000000
--- a/deps/npm/node_modules/node-gyp/gyp/tools/pretty_vcproj.py
+++ /dev/null
@@ -1,339 +0,0 @@
-#!/usr/bin/env python3
-
-# Copyright (c) 2012 Google Inc. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Make the format of a vcproj really pretty.
-
-   This script normalize and sort an xml. It also fetches all the properties
-   inside linked vsprops and include them explicitly in the vcproj.
-
-   It outputs the resulting xml to stdout.
-"""
-
-
-import os
-import sys
-
-from xml.dom.minidom import parse
-from xml.dom.minidom import Node
-
-__author__ = "nsylvain (Nicolas Sylvain)"
-ARGUMENTS = None
-REPLACEMENTS = dict()
-
-
-def cmp(x, y):
-    return (x > y) - (x < y)
-
-
-class CmpTuple:
-    """Compare function between 2 tuple."""
-
-    def __call__(self, x, y):
-        return cmp(x[0], y[0])
-
-
-class CmpNode:
-    """Compare function between 2 xml nodes."""
-
-    def __call__(self, x, y):
-        def get_string(node):
-            node_string = "node"
-            node_string += node.nodeName
-            if node.nodeValue:
-                node_string += node.nodeValue
-
-            if node.attributes:
-                # We first sort by name, if present.
-                node_string += node.getAttribute("Name")
-
-                all_nodes = []
-                for (name, value) in node.attributes.items():
-                    all_nodes.append((name, value))
-
-                all_nodes.sort(CmpTuple())
-                for (name, value) in all_nodes:
-                    node_string += name
-                    node_string += value
-
-            return node_string
-
-        return cmp(get_string(x), get_string(y))
-
-
-def PrettyPrintNode(node, indent=0):
-    if node.nodeType == Node.TEXT_NODE:
-        if node.data.strip():
-            print("{}{}".format(" " * indent, node.data.strip()))
-        return
-
-    if node.childNodes:
-        node.normalize()
-    # Get the number of attributes
-    attr_count = 0
-    if node.attributes:
-        attr_count = node.attributes.length
-
-    # Print the main tag
-    if attr_count == 0:
-        print("{}<{}>".format(" " * indent, node.nodeName))
-    else:
-        print("{}<{}".format(" " * indent, node.nodeName))
-
-        all_attributes = []
-        for (name, value) in node.attributes.items():
-            all_attributes.append((name, value))
-            all_attributes.sort(CmpTuple())
-        for (name, value) in all_attributes:
-            print('{}  {}="{}"'.format(" " * indent, name, value))
-        print("%s>" % (" " * indent))
-    if node.nodeValue:
-        print("{}  {}".format(" " * indent, node.nodeValue))
-
-    for sub_node in node.childNodes:
-        PrettyPrintNode(sub_node, indent=indent + 2)
-    print("{}".format(" " * indent, node.nodeName))
-
-
-def FlattenFilter(node):
-    """Returns a list of all the node and sub nodes."""
-    node_list = []
-
-    if node.attributes and node.getAttribute("Name") == "_excluded_files":
-        # We don't add the "_excluded_files" filter.
-        return []
-
-    for current in node.childNodes:
-        if current.nodeName == "Filter":
-            node_list.extend(FlattenFilter(current))
-        else:
-            node_list.append(current)
-
-    return node_list
-
-
-def FixFilenames(filenames, current_directory):
-    new_list = []
-    for filename in filenames:
-        if filename:
-            for key in REPLACEMENTS:
-                filename = filename.replace(key, REPLACEMENTS[key])
-            os.chdir(current_directory)
-            filename = filename.strip("\"' ")
-            if filename.startswith("$"):
-                new_list.append(filename)
-            else:
-                new_list.append(os.path.abspath(filename))
-    return new_list
-
-
-def AbsoluteNode(node):
-    """Makes all the properties we know about in this node absolute."""
-    if node.attributes:
-        for (name, value) in node.attributes.items():
-            if name in [
-                "InheritedPropertySheets",
-                "RelativePath",
-                "AdditionalIncludeDirectories",
-                "IntermediateDirectory",
-                "OutputDirectory",
-                "AdditionalLibraryDirectories",
-            ]:
-                # We want to fix up these paths
-                path_list = value.split(";")
-                new_list = FixFilenames(path_list, os.path.dirname(ARGUMENTS[1]))
-                node.setAttribute(name, ";".join(new_list))
-            if not value:
-                node.removeAttribute(name)
-
-
-def CleanupVcproj(node):
-    """For each sub node, we call recursively this function."""
-    for sub_node in node.childNodes:
-        AbsoluteNode(sub_node)
-        CleanupVcproj(sub_node)
-
-    # Normalize the node, and remove all extraneous whitespaces.
-    for sub_node in node.childNodes:
-        if sub_node.nodeType == Node.TEXT_NODE:
-            sub_node.data = sub_node.data.replace("\r", "")
-            sub_node.data = sub_node.data.replace("\n", "")
-            sub_node.data = sub_node.data.rstrip()
-
-    # Fix all the semicolon separated attributes to be sorted, and we also
-    # remove the dups.
-    if node.attributes:
-        for (name, value) in node.attributes.items():
-            sorted_list = sorted(value.split(";"))
-            unique_list = []
-            for i in sorted_list:
-                if not unique_list.count(i):
-                    unique_list.append(i)
-            node.setAttribute(name, ";".join(unique_list))
-            if not value:
-                node.removeAttribute(name)
-
-    if node.childNodes:
-        node.normalize()
-
-    # For each node, take a copy, and remove it from the list.
-    node_array = []
-    while node.childNodes and node.childNodes[0]:
-        # Take a copy of the node and remove it from the list.
-        current = node.childNodes[0]
-        node.removeChild(current)
-
-        # If the child is a filter, we want to append all its children
-        # to this same list.
-        if current.nodeName == "Filter":
-            node_array.extend(FlattenFilter(current))
-        else:
-            node_array.append(current)
-
-    # Sort the list.
-    node_array.sort(CmpNode())
-
-    # Insert the nodes in the correct order.
-    for new_node in node_array:
-        # But don't append empty tool node.
-        if new_node.nodeName == "Tool":
-            if new_node.attributes and new_node.attributes.length == 1:
-                # This one was empty.
-                continue
-        if new_node.nodeName == "UserMacro":
-            continue
-        node.appendChild(new_node)
-
-
-def GetConfiguationNodes(vcproj):
-    # TODO(nsylvain): Find a better way to navigate the xml.
-    nodes = []
-    for node in vcproj.childNodes:
-        if node.nodeName == "Configurations":
-            for sub_node in node.childNodes:
-                if sub_node.nodeName == "Configuration":
-                    nodes.append(sub_node)
-
-    return nodes
-
-
-def GetChildrenVsprops(filename):
-    dom = parse(filename)
-    if dom.documentElement.attributes:
-        vsprops = dom.documentElement.getAttribute("InheritedPropertySheets")
-        return FixFilenames(vsprops.split(";"), os.path.dirname(filename))
-    return []
-
-
-def SeekToNode(node1, child2):
-    # A text node does not have properties.
-    if child2.nodeType == Node.TEXT_NODE:
-        return None
-
-    # Get the name of the current node.
-    current_name = child2.getAttribute("Name")
-    if not current_name:
-        # There is no name. We don't know how to merge.
-        return None
-
-    # Look through all the nodes to find a match.
-    for sub_node in node1.childNodes:
-        if sub_node.nodeName == child2.nodeName:
-            name = sub_node.getAttribute("Name")
-            if name == current_name:
-                return sub_node
-
-    # No match. We give up.
-    return None
-
-
-def MergeAttributes(node1, node2):
-    # No attributes to merge?
-    if not node2.attributes:
-        return
-
-    for (name, value2) in node2.attributes.items():
-        # Don't merge the 'Name' attribute.
-        if name == "Name":
-            continue
-        value1 = node1.getAttribute(name)
-        if value1:
-            # The attribute exist in the main node. If it's equal, we leave it
-            # untouched, otherwise we concatenate it.
-            if value1 != value2:
-                node1.setAttribute(name, ";".join([value1, value2]))
-        else:
-            # The attribute does not exist in the main node. We append this one.
-            node1.setAttribute(name, value2)
-
-        # If the attribute was a property sheet attributes, we remove it, since
-        # they are useless.
-        if name == "InheritedPropertySheets":
-            node1.removeAttribute(name)
-
-
-def MergeProperties(node1, node2):
-    MergeAttributes(node1, node2)
-    for child2 in node2.childNodes:
-        child1 = SeekToNode(node1, child2)
-        if child1:
-            MergeProperties(child1, child2)
-        else:
-            node1.appendChild(child2.cloneNode(True))
-
-
-def main(argv):
-    """Main function of this vcproj prettifier."""
-    global ARGUMENTS
-    ARGUMENTS = argv
-
-    # check if we have exactly 1 parameter.
-    if len(argv) < 2:
-        print(
-            'Usage: %s "c:\\path\\to\\vcproj.vcproj" [key1=value1] '
-            "[key2=value2]" % argv[0]
-        )
-        return 1
-
-    # Parse the keys
-    for i in range(2, len(argv)):
-        (key, value) = argv[i].split("=")
-        REPLACEMENTS[key] = value
-
-    # Open the vcproj and parse the xml.
-    dom = parse(argv[1])
-
-    # First thing we need to do is find the Configuration Node and merge them
-    # with the vsprops they include.
-    for configuration_node in GetConfiguationNodes(dom.documentElement):
-        # Get the property sheets associated with this configuration.
-        vsprops = configuration_node.getAttribute("InheritedPropertySheets")
-
-        # Fix the filenames to be absolute.
-        vsprops_list = FixFilenames(
-            vsprops.strip().split(";"), os.path.dirname(argv[1])
-        )
-
-        # Extend the list of vsprops with all vsprops contained in the current
-        # vsprops.
-        for current_vsprops in vsprops_list:
-            vsprops_list.extend(GetChildrenVsprops(current_vsprops))
-
-        # Now that we have all the vsprops, we need to merge them.
-        for current_vsprops in vsprops_list:
-            MergeProperties(configuration_node, parse(current_vsprops).documentElement)
-
-    # Now that everything is merged, we need to cleanup the xml.
-    CleanupVcproj(dom.documentElement)
-
-    # Finally, we use the prett xml function to print the vcproj back to the
-    # user.
-    # print dom.toprettyxml(newl="\n")
-    PrettyPrintNode(dom.documentElement)
-    return 0
-
-
-if __name__ == "__main__":
-    sys.exit(main(sys.argv))
diff --git a/deps/npm/node_modules/node-gyp/lib/build.js b/deps/npm/node_modules/node-gyp/lib/build.js
index ea1f90652a05d8..6b8d84d3ede344 100644
--- a/deps/npm/node_modules/node-gyp/lib/build.js
+++ b/deps/npm/node_modules/node-gyp/lib/build.js
@@ -1,14 +1,14 @@
 'use strict'
 
-const fs = require('graceful-fs')
+const fs = require('graceful-fs').promises
 const path = require('path')
-const glob = require('glob')
-const log = require('npmlog')
+const { glob } = require('glob')
+const log = require('./log')
 const which = require('which')
 const win = process.platform === 'win32'
 
-function build (gyp, argv, callback) {
-  var platformMake = 'make'
+async function build (gyp, argv) {
+  let platformMake = 'make'
   if (process.platform === 'aix') {
     platformMake = 'gmake'
   } else if (process.platform === 'os400') {
@@ -21,113 +21,107 @@ function build (gyp, argv, callback) {
     })
   }
 
-  var makeCommand = gyp.opts.make || process.env.MAKE || platformMake
-  var command = win ? 'msbuild' : makeCommand
-  var jobs = gyp.opts.jobs || process.env.JOBS
-  var buildType
-  var config
-  var arch
-  var nodeDir
-  var guessedSolution
+  const makeCommand = gyp.opts.make || process.env.MAKE || platformMake
+  let command = win ? 'msbuild' : makeCommand
+  const jobs = gyp.opts.jobs || process.env.JOBS
+  let buildType
+  let config
+  let arch
+  let nodeDir
+  let guessedSolution
+  let python
+  let buildBinsDir
 
-  loadConfigGypi()
+  await loadConfigGypi()
 
   /**
    * Load the "config.gypi" file that was generated during "configure".
    */
 
-  function loadConfigGypi () {
-    var configPath = path.resolve('build', 'config.gypi')
-
-    fs.readFile(configPath, 'utf8', function (err, data) {
-      if (err) {
-        if (err.code === 'ENOENT') {
-          callback(new Error('You must run `node-gyp configure` first!'))
-        } else {
-          callback(err)
-        }
-        return
+  async function loadConfigGypi () {
+    let data
+    try {
+      const configPath = path.resolve('build', 'config.gypi')
+      data = await fs.readFile(configPath, 'utf8')
+    } catch (err) {
+      if (err.code === 'ENOENT') {
+        throw new Error('You must run `node-gyp configure` first!')
+      } else {
+        throw err
       }
-      config = JSON.parse(data.replace(/#.+\n/, ''))
+    }
 
-      // get the 'arch', 'buildType', and 'nodeDir' vars from the config
-      buildType = config.target_defaults.default_configuration
-      arch = config.variables.target_arch
-      nodeDir = config.variables.nodedir
+    config = JSON.parse(data.replace(/#.+\n/, ''))
 
-      if ('debug' in gyp.opts) {
-        buildType = gyp.opts.debug ? 'Debug' : 'Release'
-      }
-      if (!buildType) {
-        buildType = 'Release'
-      }
+    // get the 'arch', 'buildType', and 'nodeDir' vars from the config
+    buildType = config.target_defaults.default_configuration
+    arch = config.variables.target_arch
+    nodeDir = config.variables.nodedir
+    python = config.variables.python
 
-      log.verbose('build type', buildType)
-      log.verbose('architecture', arch)
-      log.verbose('node dev dir', nodeDir)
+    if ('debug' in gyp.opts) {
+      buildType = gyp.opts.debug ? 'Debug' : 'Release'
+    }
+    if (!buildType) {
+      buildType = 'Release'
+    }
 
-      if (win) {
-        findSolutionFile()
-      } else {
-        doWhich()
-      }
-    })
+    log.verbose('build type', buildType)
+    log.verbose('architecture', arch)
+    log.verbose('node dev dir', nodeDir)
+    log.verbose('python', python)
+
+    if (win) {
+      await findSolutionFile()
+    } else {
+      await doWhich()
+    }
   }
 
   /**
    * On Windows, find the first build/*.sln file.
    */
 
-  function findSolutionFile () {
-    glob('build/*.sln', function (err, files) {
-      if (err) {
-        return callback(err)
-      }
-      if (files.length === 0) {
-        return callback(new Error('Could not find *.sln file. Did you run "configure"?'))
-      }
-      guessedSolution = files[0]
-      log.verbose('found first Solution file', guessedSolution)
-      doWhich()
-    })
+  async function findSolutionFile () {
+    const files = await glob('build/*.sln')
+    if (files.length === 0) {
+      throw new Error('Could not find *.sln file. Did you run "configure"?')
+    }
+    guessedSolution = files[0]
+    log.verbose('found first Solution file', guessedSolution)
+    await doWhich()
   }
 
   /**
    * Uses node-which to locate the msbuild / make executable.
    */
 
-  function doWhich () {
+  async function doWhich () {
     // On Windows use msbuild provided by node-gyp configure
     if (win) {
       if (!config.variables.msbuild_path) {
-        return callback(new Error(
-          'MSBuild is not set, please run `node-gyp configure`.'))
+        throw new Error('MSBuild is not set, please run `node-gyp configure`.')
       }
       command = config.variables.msbuild_path
       log.verbose('using MSBuild:', command)
-      doBuild()
+      await doBuild()
       return
     }
+
     // First make sure we have the build command in the PATH
-    which(command, function (err, execPath) {
-      if (err) {
-        // Some other error or 'make' not found on Unix, report that to the user
-        callback(err)
-        return
-      }
-      log.verbose('`which` succeeded for `' + command + '`', execPath)
-      doBuild()
-    })
+    const execPath = await which(command)
+    log.verbose('`which` succeeded for `' + command + '`', execPath)
+    await doBuild()
   }
 
   /**
    * Actually spawn the process and compile the module.
    */
 
-  function doBuild () {
+  async function doBuild () {
     // Enable Verbose build
-    var verbose = log.levels[log.level] <= log.levels.verbose
-    var j
+    const verbose = log.logger.isVisible('verbose')
+    let j
 
     if (!win && verbose) {
       argv.push('V=1')
@@ -147,10 +141,12 @@ function build (gyp, argv, callback) {
       // Convert .gypi config target_arch to MSBuild /Platform
       // Since there are many ways to state '32-bit Intel', default to it.
       // N.B. msbuild's Condition string equality tests are case-insensitive.
-      var archLower = arch.toLowerCase()
-      var p = archLower === 'x64' ? 'x64'
-        : (archLower === 'arm' ? 'ARM'
-          : (archLower === 'arm64' ? 'ARM64' : 'Win32'))
+      const archLower = arch.toLowerCase()
+      const p = archLower === 'x64'
+        ? 'x64'
+        : (archLower === 'arm'
+            ? 'ARM'
+            : (archLower === 'arm64' ? 'ARM64' : 'Win32'))
       argv.push('/p:Configuration=' + buildType + ';Platform=' + p)
       if (jobs) {
         j = parseInt(jobs, 10)
@@ -179,7 +175,7 @@ function build (gyp, argv, callback) {
 
     if (win) {
       // did the user specify their own .sln file?
-      var hasSln = argv.some(function (arg) {
+      const hasSln = argv.some(function (arg) {
         return path.extname(arg) === '.sln'
       })
       if (!hasSln) {
@@ -189,23 +185,34 @@ function build (gyp, argv, callback) {
 
     if (!win) {
       // Add build-time dependency symlinks (such as Python) to PATH
-      const buildBinsDir = path.resolve('build', 'node_gyp_bins')
+      buildBinsDir = path.resolve('build', 'node_gyp_bins')
       process.env.PATH = `${buildBinsDir}:${process.env.PATH}`
-      log.verbose('bin symlinks', `adding symlinks (such as Python), at "${buildBinsDir}", to PATH`)
+      await fs.mkdir(buildBinsDir, { recursive: true })
+      const symlinkDestination = path.join(buildBinsDir, 'python3')
+      try {
+        await fs.unlink(symlinkDestination)
+      } catch (err) {
+        if (err.code !== 'ENOENT') throw err
+      }
+      await fs.symlink(python, symlinkDestination)
+      log.verbose('bin symlinks', `created symlink to "${python}" in "${buildBinsDir}" and added to PATH`)
     }
 
-    var proc = gyp.spawn(command, argv)
-    proc.on('exit', onExit)
-  }
+    const proc = gyp.spawn(command, argv)
+    await new Promise((resolve, reject) => proc.on('exit', async (code, signal) => {
+      if (buildBinsDir) {
+        // Clean up the build-time dependency symlinks:
+        await fs.rm(buildBinsDir, { recursive: true })
+      }
 
-  function onExit (code, signal) {
-    if (code !== 0) {
-      return callback(new Error('`' + command + '` failed with exit code: ' + code))
-    }
-    if (signal) {
-      return callback(new Error('`' + command + '` got signal: ' + signal))
-    }
-    callback()
+      if (code !== 0) {
+        return reject(new Error('`' + command + '` failed with exit code: ' + code))
+      }
+      if (signal) {
+        return reject(new Error('`' + command + '` got signal: ' + signal))
+      }
+      resolve()
+    }))
   }
 }
 
diff --git a/deps/npm/node_modules/node-gyp/lib/clean.js b/deps/npm/node_modules/node-gyp/lib/clean.js
index dbfa4dbb99d3cb..523f8016caecef 100644
--- a/deps/npm/node_modules/node-gyp/lib/clean.js
+++ b/deps/npm/node_modules/node-gyp/lib/clean.js
@@ -1,14 +1,14 @@
 'use strict'
 
-const rm = require('rimraf')
-const log = require('npmlog')
+const fs = require('graceful-fs').promises
+const log = require('./log')
 
-function clean (gyp, argv, callback) {
+async function clean (gyp, argv) {
   // Remove the 'build' dir
-  var buildDir = 'build'
+  const buildDir = 'build'
 
   log.verbose('clean', 'removing "%s" directory', buildDir)
-  rm(buildDir, callback)
+  await fs.rm(buildDir, { recursive: true, force: true })
 }
 
 module.exports = clean
diff --git a/deps/npm/node_modules/node-gyp/lib/configure.js b/deps/npm/node_modules/node-gyp/lib/configure.js
index 1ca3ade70935ee..8da41a849dfcf6 100644
--- a/deps/npm/node_modules/node-gyp/lib/configure.js
+++ b/deps/npm/node_modules/node-gyp/lib/configure.js
@@ -1,47 +1,36 @@
 'use strict'
 
-const fs = require('graceful-fs')
+const { promises: fs } = require('graceful-fs')
 const path = require('path')
-const log = require('npmlog')
+const log = require('./log')
 const os = require('os')
 const processRelease = require('./process-release')
 const win = process.platform === 'win32'
 const findNodeDirectory = require('./find-node-directory')
-const createConfigGypi = require('./create-config-gypi')
-const msgFormat = require('util').format
-var findPython = require('./find-python')
-if (win) {
-  var findVisualStudio = require('./find-visualstudio')
-}
-
-function configure (gyp, argv, callback) {
-  var python
-  var buildDir = path.resolve('build')
-  var buildBinsDir = path.join(buildDir, 'node_gyp_bins')
-  var configNames = ['config.gypi', 'common.gypi']
-  var configs = []
-  var nodeDir
-  var release = processRelease(argv, gyp, process.version, process.release)
-
-  findPython(gyp.opts.python, function (err, found) {
-    if (err) {
-      callback(err)
-    } else {
-      python = found
-      getNodeDir()
-    }
-  })
-
-  function getNodeDir () {
+const { createConfigGypi } = require('./create-config-gypi')
+const { format: msgFormat } = require('util')
+const { findAccessibleSync } = require('./util')
+const { findPython } = require('./find-python')
+const { findVisualStudio } = win ? require('./find-visualstudio') : {}
+
+async function configure (gyp, argv) {
+  const buildDir = path.resolve('build')
+  const configNames = ['config.gypi', 'common.gypi']
+  const configs = []
+  let nodeDir
+  const release = processRelease(argv, gyp, process.version, process.release)
+
+  const python = await findPython(gyp.opts.python)
+  return getNodeDir()
+
+  async function getNodeDir () {
     // 'python' should be set by now
     process.env.PYTHON = python
 
     if (gyp.opts.nodedir) {
       // --nodedir was specified. use that for the dev files
       nodeDir = gyp.opts.nodedir.replace(/^~/, os.homedir())
-
       log.verbose('get node dir', 'compiling against specified --nodedir dev files: %s', nodeDir)
-      createBuildDir()
     } else {
       // if no --nodedir specified, ensure node dependencies are installed
       if ('v' + release.version !== process.version) {
@@ -54,108 +43,66 @@ function configure (gyp, argv, callback) {
 
       if (!release.semver) {
         // could not parse the version string with semver
-        return callback(new Error('Invalid version number: ' + release.version))
+        throw new Error('Invalid version number: ' + release.version)
       }
 
       // If the tarball option is set, always remove and reinstall the headers
       // into devdir. Otherwise only install if they're not already there.
       gyp.opts.ensure = !gyp.opts.tarball
 
-      gyp.commands.install([release.version], function (err) {
-        if (err) {
-          return callback(err)
-        }
-        log.verbose('get node dir', 'target node version installed:', release.versionDir)
-        nodeDir = path.resolve(gyp.devDir, release.versionDir)
-        createBuildDir()
-      })
-    }
-  }
+      await gyp.commands.install([release.version])
 
-  function createBuildDir () {
-    log.verbose('build dir', 'attempting to create "build" dir: %s', buildDir)
+      log.verbose('get node dir', 'target node version installed:', release.versionDir)
+      nodeDir = path.resolve(gyp.devDir, release.versionDir)
+    }
 
-    const deepestBuildDirSubdirectory = win ? buildDir : buildBinsDir
-    fs.mkdir(deepestBuildDirSubdirectory, { recursive: true }, function (err, isNew) {
-      if (err) {
-        return callback(err)
-      }
-      log.verbose(
-        'build dir', '"build" dir needed to be created?', isNew ? 'Yes' : 'No'
-      )
-      if (win) {
-        findVisualStudio(release.semver, gyp.opts.msvs_version,
-          createConfigFile)
-      } else {
-        createPythonSymlink()
-        createConfigFile()
-      }
-    })
+    return createBuildDir()
   }
 
-  function createPythonSymlink () {
-    const symlinkDestination = path.join(buildBinsDir, 'python3')
-
-    log.verbose('python symlink', `creating symlink to "${python}" at "${symlinkDestination}"`)
+  async function createBuildDir () {
+    log.verbose('build dir', 'attempting to create "build" dir: %s', buildDir)
 
-    fs.unlink(symlinkDestination, function (err) {
-      if (err && err.code !== 'ENOENT') {
-        log.verbose('python symlink', 'error when attempting to remove existing symlink')
-        log.verbose('python symlink', err.stack, 'errno: ' + err.errno)
-      }
-      fs.symlink(python, symlinkDestination, function (err) {
-        if (err) {
-          log.verbose('python symlink', 'error when attempting to create Python symlink')
-          log.verbose('python symlink', err.stack, 'errno: ' + err.errno)
-        }
-      })
-    })
+    const isNew = await fs.mkdir(buildDir, { recursive: true })
+    log.verbose(
+      'build dir', '"build" dir needed to be created?', isNew ? 'Yes' : 'No'
+    )
+    const vsInfo = win ? await findVisualStudio(release.semver, gyp.opts['msvs-version']) : null
+    return createConfigFile(vsInfo)
   }
 
-  function createConfigFile (err, vsInfo) {
-    if (err) {
-      return callback(err)
-    }
-    if (process.platform === 'win32') {
+  async function createConfigFile (vsInfo) {
+    if (win) {
       process.env.GYP_MSVS_VERSION = Math.min(vsInfo.versionYear, 2015)
       process.env.GYP_MSVS_OVERRIDE_PATH = vsInfo.path
     }
-    createConfigGypi({ gyp, buildDir, nodeDir, vsInfo }).then(configPath => {
-      configs.push(configPath)
-      findConfigs()
-    }).catch(err => {
-      callback(err)
-    })
+    const configPath = await createConfigGypi({ gyp, buildDir, nodeDir, vsInfo, python })
+    configs.push(configPath)
+    return findConfigs()
   }
 
-  function findConfigs () {
-    var name = configNames.shift()
+  async function findConfigs () {
+    const name = configNames.shift()
     if (!name) {
       return runGyp()
     }
-    var fullPath = path.resolve(name)
 
+    const fullPath = path.resolve(name)
     log.verbose(name, 'checking for gypi file: %s', fullPath)
-    fs.stat(fullPath, function (err) {
-      if (err) {
-        if (err.code === 'ENOENT') {
-          findConfigs() // check next gypi filename
-        } else {
-          callback(err)
-        }
-      } else {
-        log.verbose(name, 'found gypi file')
-        configs.push(fullPath)
-        findConfigs()
+    try {
+      await fs.stat(fullPath)
+      log.verbose(name, 'found gypi file')
+      configs.push(fullPath)
+    } catch (err) {
+      // ENOENT will check next gypi filename
+      if (err.code !== 'ENOENT') {
+        throw err
       }
-    })
-  }
-
-  function runGyp (err) {
-    if (err) {
-      return callback(err)
     }
 
+    return findConfigs()
+  }
+
+  async function runGyp () {
     if (!~argv.indexOf('-f') && !~argv.indexOf('--format')) {
       if (win) {
         log.verbose('gyp', 'gyp format was not specified; forcing "msvs"')
@@ -175,11 +122,13 @@ function configure (gyp, argv, callback) {
 
     // For AIX and z/OS we need to set up the path to the exports file
     // which contains the symbols needed for linking.
-    var nodeExpFile
+    let nodeExpFile
+    let nodeRootDir
+    let candidates
+    let logprefix = 'find exports file'
     if (process.platform === 'aix' || process.platform === 'os390' || process.platform === 'os400') {
-      var ext = process.platform === 'os390' ? 'x' : 'exp'
-      var nodeRootDir = findNodeDirectory()
-      var candidates
+      const ext = process.platform === 'os390' ? 'x' : 'exp'
+      nodeRootDir = findNodeDirectory()
 
       if (process.platform === 'aix' || process.platform === 'os400') {
         candidates = [
@@ -202,24 +151,23 @@ function configure (gyp, argv, callback) {
         })
       }
 
-      var logprefix = 'find exports file'
       nodeExpFile = findAccessibleSync(logprefix, nodeRootDir, candidates)
       if (nodeExpFile !== undefined) {
         log.verbose(logprefix, 'Found exports file: %s', nodeExpFile)
       } else {
-        var msg = msgFormat('Could not find node.%s file in %s', ext, nodeRootDir)
+        const msg = msgFormat('Could not find node.%s file in %s', ext, nodeRootDir)
         log.error(logprefix, 'Could not find exports file')
-        return callback(new Error(msg))
+        throw new Error(msg)
       }
     }
 
     // For z/OS we need to set up the path to zoslib include directory,
     // which contains headers included in v8config.h.
-    var zoslibIncDir
+    let zoslibIncDir
     if (process.platform === 'os390') {
       logprefix = "find zoslib's zos-base.h:"
       let msg
-      var zoslibIncPath = process.env.ZOSLIB_INCLUDES
+      let zoslibIncPath = process.env.ZOSLIB_INCLUDES
       if (zoslibIncPath) {
         zoslibIncPath = findAccessibleSync(logprefix, zoslibIncPath, ['zos-base.h'])
         if (zoslibIncPath === undefined) {
@@ -247,114 +195,88 @@ function configure (gyp, argv, callback) {
       } else if (release.version.split('.')[0] >= 16) {
         // zoslib is only shipped in Node v16 and above.
         log.error(logprefix, msg)
-        return callback(new Error(msg))
+        throw new Error(msg)
       }
     }
 
     // this logic ported from the old `gyp_addon` python file
-    var gypScript = path.resolve(__dirname, '..', 'gyp', 'gyp_main.py')
-    var addonGypi = path.resolve(__dirname, '..', 'addon.gypi')
-    var commonGypi = path.resolve(nodeDir, 'include/node/common.gypi')
-    fs.stat(commonGypi, function (err) {
-      if (err) {
-        commonGypi = path.resolve(nodeDir, 'common.gypi')
-      }
+    const gypScript = path.resolve(__dirname, '..', 'gyp', 'gyp_main.py')
+    const addonGypi = path.resolve(__dirname, '..', 'addon.gypi')
+    let commonGypi = path.resolve(nodeDir, 'include/node/common.gypi')
+    try {
+      await fs.stat(commonGypi)
+    } catch (err) {
+      commonGypi = path.resolve(nodeDir, 'common.gypi')
+    }
 
-      var outputDir = 'build'
-      if (win) {
-        // Windows expects an absolute path
-        outputDir = buildDir
-      }
-      var nodeGypDir = path.resolve(__dirname, '..')
-
-      var nodeLibFile = path.join(nodeDir,
-        !gyp.opts.nodedir ? '<(target_arch)' : '$(Configuration)',
-        release.name + '.lib')
-
-      argv.push('-I', addonGypi)
-      argv.push('-I', commonGypi)
-      argv.push('-Dlibrary=shared_library')
-      argv.push('-Dvisibility=default')
-      argv.push('-Dnode_root_dir=' + nodeDir)
-      if (process.platform === 'aix' || process.platform === 'os390' || process.platform === 'os400') {
-        argv.push('-Dnode_exp_file=' + nodeExpFile)
-        if (process.platform === 'os390' && zoslibIncDir) {
-          argv.push('-Dzoslib_include_dir=' + zoslibIncDir)
-        }
-      }
-      argv.push('-Dnode_gyp_dir=' + nodeGypDir)
+    let outputDir = 'build'
+    if (win) {
+      // Windows expects an absolute path
+      outputDir = buildDir
+    }
+    const nodeGypDir = path.resolve(__dirname, '..')
 
-      // Do this to keep Cygwin environments happy, else the unescaped '\' gets eaten up,
-      // resulting in bad paths, Ex c:parentFolderfolderanotherFolder instead of c:\parentFolder\folder\anotherFolder
-      if (win) {
-        nodeLibFile = nodeLibFile.replace(/\\/g, '\\\\')
-      }
-      argv.push('-Dnode_lib_file=' + nodeLibFile)
-      argv.push('-Dmodule_root_dir=' + process.cwd())
-      argv.push('-Dnode_engine=' +
-        (gyp.opts.node_engine || process.jsEngine || 'v8'))
-      argv.push('--depth=.')
-      argv.push('--no-parallel')
+    let nodeLibFile = path.join(nodeDir,
+      !gyp.opts.nodedir ? '<(target_arch)' : '$(Configuration)',
+      release.name + '.lib')
 
-      // tell gyp to write the Makefile/Solution files into output_dir
-      argv.push('--generator-output', outputDir)
+    argv.push('-I', addonGypi)
+    argv.push('-I', commonGypi)
+    argv.push('-Dlibrary=shared_library')
+    argv.push('-Dvisibility=default')
+    argv.push('-Dnode_root_dir=' + nodeDir)
+    if (process.platform === 'aix' || process.platform === 'os390' || process.platform === 'os400') {
+      argv.push('-Dnode_exp_file=' + nodeExpFile)
+      if (process.platform === 'os390' && zoslibIncDir) {
+        argv.push('-Dzoslib_include_dir=' + zoslibIncDir)
+      }
+    }
+    argv.push('-Dnode_gyp_dir=' + nodeGypDir)
 
-      // tell make to write its output into the same dir
-      argv.push('-Goutput_dir=.')
+    // Do this to keep Cygwin environments happy, else the unescaped '\' gets eaten up,
+    // resulting in bad paths, Ex c:parentFolderfolderanotherFolder instead of c:\parentFolder\folder\anotherFolder
+    if (win) {
+      nodeLibFile = nodeLibFile.replace(/\\/g, '\\\\')
+    }
+    argv.push('-Dnode_lib_file=' + nodeLibFile)
+    argv.push('-Dmodule_root_dir=' + process.cwd())
+    argv.push('-Dnode_engine=' +
+        (gyp.opts.node_engine || process.jsEngine || 'v8'))
+    argv.push('--depth=.')
+    argv.push('--no-parallel')
 
-      // enforce use of the "binding.gyp" file
-      argv.unshift('binding.gyp')
+    // tell gyp to write the Makefile/Solution files into output_dir
+    argv.push('--generator-output', outputDir)
 
-      // execute `gyp` from the current target nodedir
-      argv.unshift(gypScript)
+    // tell make to write its output into the same dir
+    argv.push('-Goutput_dir=.')
 
-      // make sure python uses files that came with this particular node package
-      var pypath = [path.join(__dirname, '..', 'gyp', 'pylib')]
-      if (process.env.PYTHONPATH) {
-        pypath.push(process.env.PYTHONPATH)
-      }
-      process.env.PYTHONPATH = pypath.join(win ? ';' : ':')
+    // enforce use of the "binding.gyp" file
+    argv.unshift('binding.gyp')
 
-      var cp = gyp.spawn(python, argv)
-      cp.on('exit', onCpExit)
-    })
-  }
+    // execute `gyp` from the current target nodedir
+    argv.unshift(gypScript)
 
-  function onCpExit (code) {
-    if (code !== 0) {
-      callback(new Error('`gyp` failed with exit code: ' + code))
-    } else {
-      // we're done
-      callback()
+    // make sure python uses files that came with this particular node package
+    const pypath = [path.join(__dirname, '..', 'gyp', 'pylib')]
+    if (process.env.PYTHONPATH) {
+      pypath.push(process.env.PYTHONPATH)
     }
-  }
-}
+    process.env.PYTHONPATH = pypath.join(win ? ';' : ':')
 
-/**
- * Returns the first file or directory from an array of candidates that is
- * readable by the current user, or undefined if none of the candidates are
- * readable.
- */
-function findAccessibleSync (logprefix, dir, candidates) {
-  for (var next = 0; next < candidates.length; next++) {
-    var candidate = path.resolve(dir, candidates[next])
-    try {
-      var fd = fs.openSync(candidate, 'r')
-    } catch (e) {
-      // this candidate was not found or not readable, do nothing
-      log.silly(logprefix, 'Could not open %s: %s', candidate, e.message)
-      continue
-    }
-    fs.closeSync(fd)
-    log.silly(logprefix, 'Found readable %s', candidate)
-    return candidate
+    await new Promise((resolve, reject) => {
+      const cp = gyp.spawn(python, argv)
+      cp.on('exit', (code) => {
+        if (code !== 0) {
+          reject(new Error('`gyp` failed with exit code: ' + code))
+        } else {
+          // we're done
+          resolve()
+        }
+      })
+    })
   }
-
-  return undefined
 }
 
 module.exports = configure
-module.exports.test = {
-  findAccessibleSync: findAccessibleSync
-}
 module.exports.usage = 'Generates ' + (win ? 'MSVC project files' : 'a Makefile') + ' for the current module'
diff --git a/deps/npm/node_modules/node-gyp/lib/create-config-gypi.js b/deps/npm/node_modules/node-gyp/lib/create-config-gypi.js
index ced49115027336..d598dea6e2e7fa 100644
--- a/deps/npm/node_modules/node-gyp/lib/create-config-gypi.js
+++ b/deps/npm/node_modules/node-gyp/lib/create-config-gypi.js
@@ -1,7 +1,7 @@
 'use strict'
 
-const fs = require('graceful-fs')
-const log = require('npmlog')
+const fs = require('graceful-fs').promises
+const log = require('./log')
 const path = require('path')
 
 function parseConfigGypi (config) {
@@ -24,7 +24,7 @@ async function getBaseConfigGypi ({ gyp, nodeDir }) {
   if (shouldReadConfigGypi && nodeDir) {
     try {
       const baseConfigGypiPath = path.resolve(nodeDir, 'include/node/config.gypi')
-      const baseConfigGypi = await fs.promises.readFile(baseConfigGypiPath)
+      const baseConfigGypi = await fs.readFile(baseConfigGypiPath)
       return parseConfigGypi(baseConfigGypi.toString())
     } catch (err) {
       log.warn('read config.gypi', err.message)
@@ -35,7 +35,7 @@ async function getBaseConfigGypi ({ gyp, nodeDir }) {
   return JSON.parse(JSON.stringify(process.config))
 }
 
-async function getCurrentConfigGypi ({ gyp, nodeDir, vsInfo }) {
+async function getCurrentConfigGypi ({ gyp, nodeDir, vsInfo, python }) {
   const config = await getBaseConfigGypi({ gyp, nodeDir })
   if (!config.target_defaults) {
     config.target_defaults = {}
@@ -75,6 +75,9 @@ async function getCurrentConfigGypi ({ gyp, nodeDir, vsInfo }) {
   // set the node development directory
   variables.nodedir = nodeDir
 
+  // set the configured Python path
+  variables.python = python
+
   // disable -T "thin" static archives by default
   variables.standalone_static_library = gyp.opts.thin ? 0 : 1
 
@@ -112,13 +115,13 @@ async function getCurrentConfigGypi ({ gyp, nodeDir, vsInfo }) {
   return config
 }
 
-async function createConfigGypi ({ gyp, buildDir, nodeDir, vsInfo }) {
+async function createConfigGypi ({ gyp, buildDir, nodeDir, vsInfo, python }) {
   const configFilename = 'config.gypi'
   const configPath = path.resolve(buildDir, configFilename)
 
   log.verbose('build/' + configFilename, 'creating config file')
 
-  const config = await getCurrentConfigGypi({ gyp, nodeDir, vsInfo })
+  const config = await getCurrentConfigGypi({ gyp, nodeDir, vsInfo, python })
 
   // ensures that any boolean values in config.gypi get stringified
   function boolsToString (k, v) {
@@ -135,13 +138,13 @@ async function createConfigGypi ({ gyp, buildDir, nodeDir, vsInfo }) {
 
   const json = JSON.stringify(config, boolsToString, 2)
   log.verbose('build/' + configFilename, 'writing out config file: %s', configPath)
-  await fs.promises.writeFile(configPath, [prefix, json, ''].join('\n'))
+  await fs.writeFile(configPath, [prefix, json, ''].join('\n'))
 
   return configPath
 }
 
-module.exports = createConfigGypi
-module.exports.test = {
-  parseConfigGypi: parseConfigGypi,
-  getCurrentConfigGypi: getCurrentConfigGypi
+module.exports = {
+  createConfigGypi,
+  parseConfigGypi,
+  getCurrentConfigGypi
 }
diff --git a/deps/npm/node_modules/node-gyp/lib/download.js b/deps/npm/node_modules/node-gyp/lib/download.js
new file mode 100644
index 00000000000000..ed0aa37f441165
--- /dev/null
+++ b/deps/npm/node_modules/node-gyp/lib/download.js
@@ -0,0 +1,39 @@
+const fetch = require('make-fetch-happen')
+const { promises: fs } = require('graceful-fs')
+const log = require('./log')
+
+async function download (gyp, url) {
+  log.http('GET', url)
+
+  const requestOpts = {
+    headers: {
+      'User-Agent': `node-gyp v${gyp.version} (node ${process.version})`,
+      Connection: 'keep-alive'
+    },
+    proxy: gyp.opts.proxy,
+    noProxy: gyp.opts.noproxy
+  }
+
+  const cafile = gyp.opts.cafile
+  if (cafile) {
+    requestOpts.ca = await readCAFile(cafile)
+  }
+
+  const res = await fetch(url, requestOpts)
+  log.http(res.status, res.url)
+
+  return res
+}
+
+async function readCAFile (filename) {
+  // The CA file can contain multiple certificates so split on certificate
+  // boundaries.  [\S\s]*? is used to match everything including newlines.
+  const ca = await fs.readFile(filename, 'utf8')
+  const re = /(-----BEGIN CERTIFICATE-----[\S\s]*?-----END CERTIFICATE-----)/g
+  return ca.match(re)
+}
+
+module.exports = {
+  download,
+  readCAFile
+}
diff --git a/deps/npm/node_modules/node-gyp/lib/find-node-directory.js b/deps/npm/node_modules/node-gyp/lib/find-node-directory.js
index 0dd781a6cfae8c..8838b81d338997 100644
--- a/deps/npm/node_modules/node-gyp/lib/find-node-directory.js
+++ b/deps/npm/node_modules/node-gyp/lib/find-node-directory.js
@@ -1,7 +1,7 @@
 'use strict'
 
 const path = require('path')
-const log = require('npmlog')
+const log = require('./log')
 
 function findNodeDirectory (scriptLocation, processObj) {
   // set dirname and process if not passed in
@@ -14,10 +14,10 @@ function findNodeDirectory (scriptLocation, processObj) {
   }
 
   // Have a look to see what is above us, to try and work out where we are
-  var npmParentDirectory = path.join(scriptLocation, '../../../..')
+  const npmParentDirectory = path.join(scriptLocation, '../../../..')
   log.verbose('node-gyp root', 'npm_parent_directory is ' +
               path.basename(npmParentDirectory))
-  var nodeRootDir = ''
+  let nodeRootDir = ''
 
   log.verbose('node-gyp root', 'Finding node root directory')
   if (path.basename(npmParentDirectory) === 'deps') {
@@ -41,8 +41,8 @@ function findNodeDirectory (scriptLocation, processObj) {
   } else {
     // We don't know where we are, try working it out from the location
     // of the node binary
-    var nodeDir = path.dirname(processObj.execPath)
-    var directoryUp = path.basename(nodeDir)
+    const nodeDir = path.dirname(processObj.execPath)
+    const directoryUp = path.basename(nodeDir)
     if (directoryUp === 'bin') {
       nodeRootDir = path.join(nodeDir, '..')
     } else if (directoryUp === 'Release' || directoryUp === 'Debug') {
diff --git a/deps/npm/node_modules/node-gyp/lib/find-python.js b/deps/npm/node_modules/node-gyp/lib/find-python.js
index a445e825b9d7e3..615da57bb85723 100644
--- a/deps/npm/node_modules/node-gyp/lib/find-python.js
+++ b/deps/npm/node_modules/node-gyp/lib/find-python.js
@@ -1,11 +1,15 @@
 'use strict'
 
-const log = require('npmlog')
+const log = require('./log')
 const semver = require('semver')
-const cp = require('child_process')
-const extend = require('util')._extend // eslint-disable-line
+const { execFile } = require('./util')
 const win = process.platform === 'win32'
-const logWithPrefix = require('./util').logWithPrefix
+
+function getOsUserInfo () {
+  try {
+    return require('os').userInfo().username
+  } catch {}
+}
 
 const systemDrive = process.env.SystemDrive || 'C:'
 const username = process.env.USERNAME || process.env.USER || getOsUserInfo()
@@ -15,7 +19,7 @@ const programFiles = process.env.ProgramW6432 || process.env.ProgramFiles || `${
 const programFilesX86 = process.env['ProgramFiles(x86)'] || `${programFiles} (x86)`
 
 const winDefaultLocationsArray = []
-for (const majorMinor of ['39', '38', '37', '36']) {
+for (const majorMinor of ['311', '310', '39', '38']) {
   if (foundLocalAppData) {
     winDefaultLocationsArray.push(
       `${localAppData}\\Programs\\Python\\Python${majorMinor}\\python.exe`,
@@ -33,45 +37,39 @@ for (const majorMinor of ['39', '38', '37', '36']) {
   }
 }
 
-function getOsUserInfo () {
-  try {
-    return require('os').userInfo().username
-  } catch (e) {}
-}
-
-function PythonFinder (configPython, callback) {
-  this.callback = callback
-  this.configPython = configPython
-  this.errorLog = []
-}
+class PythonFinder {
+  static findPython = (...args) => new PythonFinder(...args).findPython()
 
-PythonFinder.prototype = {
-  log: logWithPrefix(log, 'find Python'),
-  argsExecutable: ['-c', 'import sys; print(sys.executable);'],
-  argsVersion: ['-c', 'import sys; print("%s.%s.%s" % sys.version_info[:3]);'],
-  semverRange: '>=3.6.0',
+  log = log.withPrefix('find Python')
+  argsExecutable = ['-c', 'import sys; print(sys.executable);']
+  argsVersion = ['-c', 'import sys; print("%s.%s.%s" % sys.version_info[:3]);']
+  semverRange = '>=3.6.0'
 
   // These can be overridden for testing:
-  execFile: cp.execFile,
-  env: process.env,
-  win: win,
-  pyLauncher: 'py.exe',
-  winDefaultLocations: winDefaultLocationsArray,
+  execFile = execFile
+  env = process.env
+  win = win
+  pyLauncher = 'py.exe'
+  winDefaultLocations = winDefaultLocationsArray
+
+  constructor (configPython) {
+    this.configPython = configPython
+    this.errorLog = []
+  }
 
   // Logs a message at verbose level, but also saves it to be displayed later
   // at error level if an error occurs. This should help diagnose the problem.
-  addLog: function addLog (message) {
+  addLog (message) {
     this.log.verbose(message)
     this.errorLog.push(message)
-  },
+  }
 
   // Find Python by trying a sequence of possibilities.
   // Ignore errors, keep trying until Python is found.
-  findPython: function findPython () {
-    const SKIP = 0; const FAIL = 1
-    var toCheck = getChecks.apply(this)
-
-    function getChecks () {
+  async findPython () {
+    const SKIP = 0
+    const FAIL = 1
+    const toCheck = (() => {
       if (this.env.NODE_GYP_FORCE_PYTHON) {
         return [{
           before: () => {
@@ -80,12 +78,11 @@ PythonFinder.prototype = {
             this.addLog('- process.env.NODE_GYP_FORCE_PYTHON is ' +
               `"${this.env.NODE_GYP_FORCE_PYTHON}"`)
           },
-          check: this.checkCommand,
-          arg: this.env.NODE_GYP_FORCE_PYTHON
+          check: () => this.checkCommand(this.env.NODE_GYP_FORCE_PYTHON)
         }]
       }
 
-      var checks = [
+      const checks = [
         {
           before: () => {
             if (!this.configPython) {
@@ -98,8 +95,7 @@ PythonFinder.prototype = {
             this.addLog('- "--python=" or "npm config get python" is ' +
               `"${this.configPython}"`)
           },
-          check: this.checkCommand,
-          arg: this.configPython
+          check: () => this.checkCommand(this.configPython)
         },
         {
           before: () => {
@@ -112,78 +108,69 @@ PythonFinder.prototype = {
               'variable PYTHON')
             this.addLog(`- process.env.PYTHON is "${this.env.PYTHON}"`)
           },
-          check: this.checkCommand,
-          arg: this.env.PYTHON
-        },
+          check: () => this.checkCommand(this.env.PYTHON)
+        }
+      ]
+
+      if (this.win) {
+        checks.push({
+          before: () => {
+            this.addLog(
+              'checking if the py launcher can be used to find Python 3')
+          },
+          check: () => this.checkPyLauncher()
+        })
+      }
+
+      checks.push(...[
         {
           before: () => { this.addLog('checking if "python3" can be used') },
-          check: this.checkCommand,
-          arg: 'python3'
+          check: () => this.checkCommand('python3')
         },
         {
           before: () => { this.addLog('checking if "python" can be used') },
-          check: this.checkCommand,
-          arg: 'python'
+          check: () => this.checkCommand('python')
         }
-      ]
+      ])
 
       if (this.win) {
-        for (var i = 0; i < this.winDefaultLocations.length; ++i) {
+        for (let i = 0; i < this.winDefaultLocations.length; ++i) {
           const location = this.winDefaultLocations[i]
           checks.push({
-            before: () => {
-              this.addLog('checking if Python is ' +
-                `${location}`)
-            },
-            check: this.checkExecPath,
-            arg: location
+            before: () => this.addLog(`checking if Python is ${location}`),
+            check: () => this.checkExecPath(location)
           })
         }
-        checks.push({
-          before: () => {
-            this.addLog(
-              'checking if the py launcher can be used to find Python 3')
-          },
-          check: this.checkPyLauncher
-        })
       }
 
       return checks
-    }
-
-    function runChecks (err) {
-      this.log.silly('runChecks: err = %j', (err && err.stack) || err)
+    })()
 
-      const check = toCheck.shift()
-      if (!check) {
-        return this.fail()
-      }
-
-      const before = check.before.apply(this)
+    for (const check of toCheck) {
+      const before = check.before()
       if (before === SKIP) {
-        return runChecks.apply(this)
+        continue
       }
       if (before === FAIL) {
         return this.fail()
       }
-
-      const args = [runChecks.bind(this)]
-      if (check.arg) {
-        args.unshift(check.arg)
+      try {
+        return await check.check()
+      } catch (err) {
+        this.log.silly('runChecks: err = %j', (err && err.stack) || err)
       }
-      check.check.apply(this, args)
     }
 
-    runChecks.apply(this)
-  },
+    return this.fail()
+  }
 
   // Check if command is a valid Python to use.
   // Will exit the Python finder on success.
   // If on Windows, run in a CMD shell to support BAT/CMD launchers.
-  checkCommand: function checkCommand (command, errorCallback) {
-    var exec = command
-    var args = this.argsExecutable
-    var shell = false
+  async checkCommand (command) {
+    let exec = command
+    let args = this.argsExecutable
+    let shell = false
     if (this.win) {
       // Arguments have to be manually quoted
       exec = `"${exec}"`
@@ -192,19 +179,19 @@ PythonFinder.prototype = {
     }
 
     this.log.verbose(`- executing "${command}" to get executable path`)
-    this.run(exec, args, shell, function (err, execPath) {
-      // Possible outcomes:
-      // - Error: not in PATH, not executable or execution fails
-      // - Gibberish: the next command to check version will fail
-      // - Absolute path to executable
-      if (err) {
-        this.addLog(`- "${command}" is not in PATH or produced an error`)
-        return errorCallback(err)
-      }
+    // Possible outcomes:
+    // - Error: not in PATH, not executable or execution fails
+    // - Gibberish: the next command to check version will fail
+    // - Absolute path to executable
+    try {
+      const execPath = await this.run(exec, args, shell)
       this.addLog(`- executable path is "${execPath}"`)
-      this.checkExecPath(execPath, errorCallback)
-    }.bind(this))
-  },
+      return this.checkExecPath(execPath)
+    } catch (err) {
+      this.addLog(`- "${command}" is not in PATH or produced an error`)
+      throw err
+    }
+  }
 
   // Check if the py launcher can find a valid Python to use.
   // Will exit the Python finder on success.
@@ -216,97 +203,86 @@ PythonFinder.prototype = {
   // the first command line argument. Since "py.exe -3" would be an invalid
   // executable for "execFile", we have to use the launcher to figure out
   // where the actual "python.exe" executable is located.
-  checkPyLauncher: function checkPyLauncher (errorCallback) {
-    this.log.verbose(
-      `- executing "${this.pyLauncher}" to get Python 3 executable path`)
-    this.run(this.pyLauncher, ['-3', ...this.argsExecutable], false,
-      function (err, execPath) {
-      // Possible outcomes: same as checkCommand
-        if (err) {
-          this.addLog(
-            `- "${this.pyLauncher}" is not in PATH or produced an error`)
-          return errorCallback(err)
-        }
-        this.addLog(`- executable path is "${execPath}"`)
-        this.checkExecPath(execPath, errorCallback)
-      }.bind(this))
-  },
+  async checkPyLauncher () {
+    this.log.verbose(`- executing "${this.pyLauncher}" to get Python 3 executable path`)
+    // Possible outcomes: same as checkCommand
+    try {
+      const execPath = await this.run(this.pyLauncher, ['-3', ...this.argsExecutable], false)
+      this.addLog(`- executable path is "${execPath}"`)
+      return this.checkExecPath(execPath)
+    } catch (err) {
+      this.addLog(`- "${this.pyLauncher}" is not in PATH or produced an error`)
+      throw err
+    }
+  }
 
   // Check if a Python executable is the correct version to use.
   // Will exit the Python finder on success.
-  checkExecPath: function checkExecPath (execPath, errorCallback) {
+  async checkExecPath (execPath) {
     this.log.verbose(`- executing "${execPath}" to get version`)
-    this.run(execPath, this.argsVersion, false, function (err, version) {
-      // Possible outcomes:
-      // - Error: executable can not be run (likely meaning the command wasn't
-      //   a Python executable and the previous command produced gibberish)
-      // - Gibberish: somehow the last command produced an executable path,
-      //   this will fail when verifying the version
-      // - Version of the Python executable
-      if (err) {
-        this.addLog(`- "${execPath}" could not be run`)
-        return errorCallback(err)
-      }
+    // Possible outcomes:
+    // - Error: executable can not be run (likely meaning the command wasn't
+    //   a Python executable and the previous command produced gibberish)
+    // - Gibberish: somehow the last command produced an executable path,
+    //   this will fail when verifying the version
+    // - Version of the Python executable
+    try {
+      const version = await this.run(execPath, this.argsVersion, false)
       this.addLog(`- version is "${version}"`)
 
       const range = new semver.Range(this.semverRange)
-      var valid = false
+      let valid = false
       try {
         valid = range.test(version)
       } catch (err) {
         this.log.silly('range.test() threw:\n%s', err.stack)
         this.addLog(`- "${execPath}" does not have a valid version`)
         this.addLog('- is it a Python executable?')
-        return errorCallback(err)
+        throw err
       }
-
       if (!valid) {
         this.addLog(`- version is ${version} - should be ${this.semverRange}`)
         this.addLog('- THIS VERSION OF PYTHON IS NOT SUPPORTED')
-        return errorCallback(new Error(
-          `Found unsupported Python version ${version}`))
+        throw new Error(`Found unsupported Python version ${version}`)
       }
-      this.succeed(execPath, version)
-    }.bind(this))
-  },
+      return this.succeed(execPath, version)
+    } catch (err) {
+      this.addLog(`- "${execPath}" could not be run`)
+      throw err
+    }
+  }
 
   // Run an executable or shell command, trimming the output.
-  run: function run (exec, args, shell, callback) {
-    var env = extend({}, this.env)
+  async run (exec, args, shell) {
+    const env = Object.assign({}, this.env)
     env.TERM = 'dumb'
-    const opts = { env: env, shell: shell }
+    const opts = { env, shell }
 
     this.log.silly('execFile: exec = %j', exec)
     this.log.silly('execFile: args = %j', args)
     this.log.silly('execFile: opts = %j', opts)
     try {
-      this.execFile(exec, args, opts, execFileCallback.bind(this))
-    } catch (err) {
-      this.log.silly('execFile: threw:\n%s', err.stack)
-      return callback(err)
-    }
-
-    function execFileCallback (err, stdout, stderr) {
+      const [err, stdout, stderr] = await this.execFile(exec, args, opts)
       this.log.silly('execFile result: err = %j', (err && err.stack) || err)
       this.log.silly('execFile result: stdout = %j', stdout)
       this.log.silly('execFile result: stderr = %j', stderr)
-      if (err) {
-        return callback(err)
-      }
-      const execPath = stdout.trim()
-      callback(null, execPath)
+      return stdout.trim()
+    } catch (err) {
+      this.log.silly('execFile: threw:\n%s', err.stack)
+      throw err
     }
-  },
+  }
 
-  succeed: function succeed (execPath, version) {
+  succeed (execPath, version) {
     this.log.info(`using Python version ${version} found at "${execPath}"`)
-    process.nextTick(this.callback.bind(null, null, execPath))
-  },
+    return execPath
+  }
 
-  fail: function fail () {
+  fail () {
     const errorLog = this.errorLog.join('\n')
 
-    const pathExample = this.win ? 'C:\\Path\\To\\python.exe'
+    const pathExample = this.win
+      ? 'C:\\Path\\To\\python.exe'
       : '/path/to/pythonexecutable'
     // For Windows 80 col console, use up to the column before the one marked
     // with X (total 79 chars including logger prefix, 58 chars usable here):
@@ -327,18 +303,8 @@ PythonFinder.prototype = {
     ].join('\n')
 
     this.log.error(`\n${errorLog}\n\n${info}\n`)
-    process.nextTick(this.callback.bind(null, new Error(
-      'Could not find any Python installation to use')))
+    throw new Error('Could not find any Python installation to use')
   }
 }
 
-function findPython (configPython, callback) {
-  var finder = new PythonFinder(configPython, callback)
-  finder.findPython()
-}
-
-module.exports = findPython
-module.exports.test = {
-  PythonFinder: PythonFinder,
-  findPython: findPython
-}
+module.exports = PythonFinder
diff --git a/deps/npm/node_modules/node-gyp/lib/find-visualstudio.js b/deps/npm/node_modules/node-gyp/lib/find-visualstudio.js
index 16f6e79559307c..b57770259abde3 100644
--- a/deps/npm/node_modules/node-gyp/lib/find-visualstudio.js
+++ b/deps/npm/node_modules/node-gyp/lib/find-visualstudio.js
@@ -1,39 +1,32 @@
 'use strict'
 
-const log = require('npmlog')
-const execFile = require('child_process').execFile
-const fs = require('fs')
-const path = require('path').win32
-const logWithPrefix = require('./util').logWithPrefix
-const regSearchKeys = require('./util').regSearchKeys
-
-function findVisualStudio (nodeSemver, configMsvsVersion, callback) {
-  const finder = new VisualStudioFinder(nodeSemver, configMsvsVersion,
-    callback)
-  finder.findVisualStudio()
-}
+const log = require('./log')
+const { existsSync } = require('fs')
+const { win32: path } = require('path')
+const { regSearchKeys, execFile } = require('./util')
 
-function VisualStudioFinder (nodeSemver, configMsvsVersion, callback) {
-  this.nodeSemver = nodeSemver
-  this.configMsvsVersion = configMsvsVersion
-  this.callback = callback
-  this.errorLog = []
-  this.validVersions = []
-}
+class VisualStudioFinder {
+  static findVisualStudio = (...args) => new VisualStudioFinder(...args).findVisualStudio()
+
+  log = log.withPrefix('find VS')
 
-VisualStudioFinder.prototype = {
-  log: logWithPrefix(log, 'find VS'),
+  regSearchKeys = regSearchKeys
 
-  regSearchKeys: regSearchKeys,
+  constructor (nodeSemver, configMsvsVersion) {
+    this.nodeSemver = nodeSemver
+    this.configMsvsVersion = configMsvsVersion
+    this.errorLog = []
+    this.validVersions = []
+  }
 
   // Logs a message at verbose level, but also saves it to be displayed later
   // at error level if an error occurs. This should help diagnose the problem.
-  addLog: function addLog (message) {
+  addLog (message) {
     this.log.verbose(message)
     this.errorLog.push(message)
-  },
+  }
 
-  findVisualStudio: function findVisualStudio () {
+  async findVisualStudio () {
     this.configVersionYear = null
     this.configPath = null
     if (this.configMsvsVersion) {
@@ -60,32 +53,30 @@ VisualStudioFinder.prototype = {
       this.addLog('VCINSTALLDIR not set, not running in VS Command Prompt')
     }
 
-    this.findVisualStudio2017OrNewer((info) => {
+    const checks = [
+      () => this.findVisualStudio2017OrNewer(),
+      () => this.findVisualStudio2015(),
+      () => this.findVisualStudio2013()
+    ]
+
+    for (const check of checks) {
+      const info = await check()
       if (info) {
         return this.succeed(info)
       }
-      this.findVisualStudio2015((info) => {
-        if (info) {
-          return this.succeed(info)
-        }
-        this.findVisualStudio2013((info) => {
-          if (info) {
-            return this.succeed(info)
-          }
-          this.fail()
-        })
-      })
-    })
-  },
+    }
+
+    return this.fail()
+  }
 
-  succeed: function succeed (info) {
+  succeed (info) {
     this.log.info(`using VS${info.versionYear} (${info.version}) found at:` +
                   `\n"${info.path}"` +
                   '\nrun with --verbose for detailed information')
-    process.nextTick(this.callback.bind(null, null, info))
-  },
+    return info
+  }
 
-  fail: function fail () {
+  fail () {
     if (this.configMsvsVersion && this.envVcInstallDir) {
       this.errorLog.push(
         'msvs_version does not match this VS Command Prompt or the',
@@ -119,17 +110,16 @@ VisualStudioFinder.prototype = {
     ].join('\n')
 
     this.log.error(`\n${errorLog}\n\n${infoLog}\n`)
-    process.nextTick(this.callback.bind(null, new Error(
-      'Could not find any Visual Studio installation to use')))
-  },
+    throw new Error('Could not find any Visual Studio installation to use')
+  }
 
   // Invoke the PowerShell script to get information about Visual Studio 2017
   // or newer installations
-  findVisualStudio2017OrNewer: function findVisualStudio2017OrNewer (cb) {
-    var ps = path.join(process.env.SystemRoot, 'System32',
+  async findVisualStudio2017OrNewer () {
+    const ps = path.join(process.env.SystemRoot, 'System32',
       'WindowsPowerShell', 'v1.0', 'powershell.exe')
-    var csFile = path.join(__dirname, 'Find-VisualStudio.cs')
-    var psArgs = [
+    const csFile = path.join(__dirname, 'Find-VisualStudio.cs')
+    const psArgs = [
       '-ExecutionPolicy',
       'Unrestricted',
       '-NoProfile',
@@ -138,22 +128,19 @@ VisualStudioFinder.prototype = {
     ]
 
     this.log.silly('Running', ps, psArgs)
-    var child = execFile(ps, psArgs, { encoding: 'utf8' },
-      (err, stdout, stderr) => {
-        this.parseData(err, stdout, stderr, cb)
-      })
-    child.stdin.end()
-  },
+    const [err, stdout, stderr] = await execFile(ps, psArgs, { encoding: 'utf8' })
+    return this.parseData(err, stdout, stderr)
+  }
 
   // Parse the output of the PowerShell script and look for an installation
   // of Visual Studio 2017 or newer to use
-  parseData: function parseData (err, stdout, stderr, cb) {
+  parseData (err, stdout, stderr) {
     this.log.silly('PS stderr = %j', stderr)
 
     const failPowershell = () => {
       this.addLog(
         'could not use PowerShell to find Visual Studio 2017 or newer, try re-running with \'--loglevel silly\' for more details')
-      cb(null)
+      return null
     }
 
     if (err) {
@@ -161,7 +148,7 @@ VisualStudioFinder.prototype = {
       return failPowershell()
     }
 
-    var vsInfo
+    let vsInfo
     try {
       vsInfo = JSON.parse(stdout)
     } catch (e) {
@@ -178,7 +165,7 @@ VisualStudioFinder.prototype = {
     vsInfo = vsInfo.map((info) => {
       this.log.silly(`processing installation: "${info.path}"`)
       info.path = path.resolve(info.path)
-      var ret = this.getVersionInfo(info)
+      const ret = this.getVersionInfo(info)
       ret.path = info.path
       ret.msBuild = this.getMSBuild(info, ret.versionYear)
       ret.toolset = this.getToolset(info, ret.versionYear)
@@ -199,7 +186,7 @@ VisualStudioFinder.prototype = {
     // Sort to place newer versions first
     vsInfo.sort((a, b) => b.versionYear - a.versionYear)
 
-    for (var i = 0; i < vsInfo.length; ++i) {
+    for (let i = 0; i < vsInfo.length; ++i) {
       const info = vsInfo[i]
       this.addLog(`checking VS${info.versionYear} (${info.version}) found ` +
                   `at:\n"${info.path}"`)
@@ -229,23 +216,23 @@ VisualStudioFinder.prototype = {
         continue
       }
 
-      return cb(info)
+      return info
     }
 
     this.addLog(
       'could not find a version of Visual Studio 2017 or newer to use')
-    cb(null)
-  },
+    return null
+  }
 
   // Helper - process version information
-  getVersionInfo: function getVersionInfo (info) {
+  getVersionInfo (info) {
     const match = /^(\d+)\.(\d+)\..*/.exec(info.version)
     if (!match) {
       this.log.silly('- failed to parse version:', info.version)
       return {}
     }
     this.log.silly('- version match = %j', match)
-    var ret = {
+    const ret = {
       version: info.version,
       versionMajor: parseInt(match[1], 10),
       versionMinor: parseInt(match[2], 10)
@@ -264,14 +251,14 @@ VisualStudioFinder.prototype = {
     }
     this.log.silly('- unsupported version:', ret.versionMajor)
     return {}
-  },
+  }
 
-  msBuildPathExists: function msBuildPathExists (path) {
-    return fs.existsSync(path)
-  },
+  msBuildPathExists (path) {
+    return existsSync(path)
+  }
 
   // Helper - process MSBuild information
-  getMSBuild: function getMSBuild (info, versionYear) {
+  getMSBuild (info, versionYear) {
     const pkg = 'Microsoft.VisualStudio.VC.MSBuild.Base'
     const msbuildPath = path.join(info.path, 'MSBuild', 'Current', 'Bin', 'MSBuild.exe')
     const msbuildPathArm64 = path.join(info.path, 'MSBuild', 'Current', 'Bin', 'arm64', 'MSBuild.exe')
@@ -295,10 +282,10 @@ VisualStudioFinder.prototype = {
       return msbuildPath
     }
     return null
-  },
+  }
 
   // Helper - process toolset information
-  getToolset: function getToolset (info, versionYear) {
+  getToolset (info, versionYear) {
     const pkg = 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64'
     const express = 'Microsoft.VisualStudio.WDExpress'
 
@@ -319,15 +306,15 @@ VisualStudioFinder.prototype = {
     }
     this.log.silly('- invalid versionYear:', versionYear)
     return null
-  },
+  }
 
   // Helper - process Windows SDK information
-  getSDK: function getSDK (info) {
+  getSDK (info) {
     const win8SDK = 'Microsoft.VisualStudio.Component.Windows81SDK'
     const win10SDKPrefix = 'Microsoft.VisualStudio.Component.Windows10SDK.'
     const win11SDKPrefix = 'Microsoft.VisualStudio.Component.Windows11SDK.'
 
-    var Win10or11SDKVer = 0
+    let Win10or11SDKVer = 0
     info.packages.forEach((pkg) => {
       if (!pkg.startsWith(win10SDKPrefix) && !pkg.startsWith(win11SDKPrefix)) {
         return
@@ -354,14 +341,14 @@ VisualStudioFinder.prototype = {
       return '8.1'
     }
     return null
-  },
+  }
 
   // Find an installation of Visual Studio 2015 to use
-  findVisualStudio2015: function findVisualStudio2015 (cb) {
+  async findVisualStudio2015 () {
     if (this.nodeSemver.major >= 19) {
       this.addLog(
         'not looking for VS2015 as it is only supported up to Node.js 18')
-      return cb(null)
+      return null
     }
     return this.findOldVS({
       version: '14.0',
@@ -369,15 +356,15 @@ VisualStudioFinder.prototype = {
       versionMinor: 0,
       versionYear: 2015,
       toolset: 'v140'
-    }, cb)
-  },
+    })
+  }
 
   // Find an installation of Visual Studio 2013 to use
-  findVisualStudio2013: function findVisualStudio2013 (cb) {
+  async findVisualStudio2013 () {
     if (this.nodeSemver.major >= 9) {
       this.addLog(
         'not looking for VS2013 as it is only supported up to Node.js 8')
-      return cb(null)
+      return null
     }
     return this.findOldVS({
       version: '12.0',
@@ -385,55 +372,52 @@ VisualStudioFinder.prototype = {
       versionMinor: 0,
       versionYear: 2013,
       toolset: 'v120'
-    }, cb)
-  },
+    })
+  }
 
   // Helper - common code for VS2013 and VS2015
-  findOldVS: function findOldVS (info, cb) {
+  async findOldVS (info) {
     const regVC7 = ['HKLM\\Software\\Microsoft\\VisualStudio\\SxS\\VC7',
       'HKLM\\Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7']
     const regMSBuild = 'HKLM\\Software\\Microsoft\\MSBuild\\ToolsVersions'
 
     this.addLog(`looking for Visual Studio ${info.versionYear}`)
-    this.regSearchKeys(regVC7, info.version, [], (err, res) => {
-      if (err) {
-        this.addLog('- not found')
-        return cb(null)
-      }
-
+    try {
+      let res = await this.regSearchKeys(regVC7, info.version, [])
       const vsPath = path.resolve(res, '..')
       this.addLog(`- found in "${vsPath}"`)
-
       const msBuildRegOpts = process.arch === 'ia32' ? [] : ['/reg:32']
-      this.regSearchKeys([`${regMSBuild}\\${info.version}`],
-        'MSBuildToolsPath', msBuildRegOpts, (err, res) => {
-          if (err) {
-            this.addLog(
-              '- could not find MSBuild in registry for this version')
-            return cb(null)
-          }
-
-          const msBuild = path.join(res, 'MSBuild.exe')
-          this.addLog(`- MSBuild in "${msBuild}"`)
-
-          if (!this.checkConfigVersion(info.versionYear, vsPath)) {
-            return cb(null)
-          }
-
-          info.path = vsPath
-          info.msBuild = msBuild
-          info.sdk = null
-          cb(info)
-        })
-    })
-  },
+
+      try {
+        res = await this.regSearchKeys([`${regMSBuild}\\${info.version}`], 'MSBuildToolsPath', msBuildRegOpts)
+      } catch (err) {
+        this.addLog('- could not find MSBuild in registry for this version')
+        return null
+      }
+
+      const msBuild = path.join(res, 'MSBuild.exe')
+      this.addLog(`- MSBuild in "${msBuild}"`)
+
+      if (!this.checkConfigVersion(info.versionYear, vsPath)) {
+        return null
+      }
+
+      info.path = vsPath
+      info.msBuild = msBuild
+      info.sdk = null
+      return info
+    } catch (err) {
+      this.addLog('- not found')
+      return null
+    }
+  }
 
   // After finding a usable version of Visual Studio:
   // - add it to validVersions to be displayed at the end if a specific
   //   version was requested and not found;
   // - check if this is the version that was requested.
   // - check if this matches the Visual Studio Command Prompt
-  checkConfigVersion: function checkConfigVersion (versionYear, vsPath) {
+  checkConfigVersion (versionYear, vsPath) {
     this.validVersions.push(versionYear)
     this.validVersions.push(vsPath)
 
@@ -456,8 +440,4 @@ VisualStudioFinder.prototype = {
   }
 }
 
-module.exports = findVisualStudio
-module.exports.test = {
-  VisualStudioFinder: VisualStudioFinder,
-  findVisualStudio: findVisualStudio
-}
+module.exports = VisualStudioFinder
diff --git a/deps/npm/node_modules/node-gyp/lib/install.js b/deps/npm/node_modules/node-gyp/lib/install.js
index 1eb9f14c6742aa..7196a316296fb8 100644
--- a/deps/npm/node_modules/node-gyp/lib/install.js
+++ b/deps/npm/node_modules/node-gyp/lib/install.js
@@ -1,26 +1,21 @@
 'use strict'
 
-const fs = require('graceful-fs')
+const { createWriteStream, promises: fs } = require('graceful-fs')
 const os = require('os')
 const { backOff } = require('exponential-backoff')
-const rm = require('rimraf')
 const tar = require('tar')
 const path = require('path')
-const util = require('util')
-const stream = require('stream')
+const { Transform, promises: { pipeline } } = require('stream')
 const crypto = require('crypto')
-const log = require('npmlog')
+const log = require('./log')
 const semver = require('semver')
-const fetch = require('make-fetch-happen')
+const { download } = require('./download')
 const processRelease = require('./process-release')
-const win = process.platform === 'win32'
-const streamPipeline = util.promisify(stream.pipeline)
 
-/**
- * @param {typeof import('graceful-fs')} fs
- */
+const win = process.platform === 'win32'
 
-async function install (fs, gyp, argv) {
+async function install (gyp, argv) {
+  log.stdout()
   const release = processRelease(argv, gyp, process.version, process.release)
   // Detecting target_arch based on logic from create-cnfig-gyp.js. Used on Windows only.
   const arch = win ? (gyp.opts.target_arch || gyp.opts.arch || process.arch || 'ia32') : ''
@@ -60,7 +55,7 @@ async function install (fs, gyp, argv) {
   if (gyp.opts.ensure) {
     log.verbose('install', '--ensure was passed, so won\'t reinstall if already installed')
     try {
-      await fs.promises.stat(devDir)
+      await fs.stat(devDir)
     } catch (err) {
       if (err.code === 'ENOENT') {
         log.verbose('install', 'version not already installed, continuing with install', release.version)
@@ -78,7 +73,7 @@ async function install (fs, gyp, argv) {
     const installVersionFile = path.resolve(devDir, 'installVersion')
     let installVersion = 0
     try {
-      const ver = await fs.promises.readFile(installVersionFile, 'ascii')
+      const ver = await fs.readFile(installVersionFile, 'ascii')
       installVersion = parseInt(ver, 10) || 0
     } catch (err) {
       if (err.code !== 'ENOENT') {
@@ -100,7 +95,7 @@ async function install (fs, gyp, argv) {
       log.verbose('on Windows; need to check node.lib')
       const nodeLibPath = path.resolve(devDir, arch, 'node.lib')
       try {
-        await fs.promises.stat(nodeLibPath)
+        await fs.stat(nodeLibPath)
       } catch (err) {
         if (err.code === 'ENOENT') {
           log.verbose('install', `version not already installed for ${arch}, continuing with install`, release.version)
@@ -126,12 +121,12 @@ async function install (fs, gyp, argv) {
 
   async function copyDirectory (src, dest) {
     try {
-      await fs.promises.stat(src)
+      await fs.stat(src)
     } catch {
       throw new Error(`Missing source directory for copy: ${src}`)
     }
-    await fs.promises.mkdir(dest, { recursive: true })
-    const entries = await fs.promises.readdir(src, { withFileTypes: true })
+    await fs.mkdir(dest, { recursive: true })
+    const entries = await fs.readdir(src, { withFileTypes: true })
     for (const entry of entries) {
       if (entry.isDirectory()) {
         await copyDirectory(path.join(src, entry.name), path.join(dest, entry.name))
@@ -140,12 +135,12 @@ async function install (fs, gyp, argv) {
         // Windows so use an exponential backoff to resolve collisions
         await backOff(async () => {
           try {
-            await fs.promises.copyFile(path.join(src, entry.name), path.join(dest, entry.name))
+            await fs.copyFile(path.join(src, entry.name), path.join(dest, entry.name))
           } catch (err) {
             // if ensure, check if file already exists and that's good enough
             if (gyp.opts.ensure && err.code === 'EBUSY') {
               try {
-                await fs.promises.stat(path.join(dest, entry.name))
+                await fs.stat(path.join(dest, entry.name))
                 return
               } catch {}
             }
@@ -163,7 +158,7 @@ async function install (fs, gyp, argv) {
 
     // first create the dir for the node dev files
     try {
-      const created = await fs.promises.mkdir(devDir, { recursive: true })
+      const created = await fs.mkdir(devDir, { recursive: true })
 
       if (created) {
         log.verbose('created devDir', created)
@@ -208,7 +203,7 @@ async function install (fs, gyp, argv) {
     // on Windows there can be file errors from tar if parallel installs
     // are happening (not uncommon with multiple native modules) so
     // extract the tarball to a temp directory first and then copy over
-    const tarExtractDir = win ? await fs.promises.mkdtemp(path.join(os.tmpdir(), 'node-gyp-tmp-')) : devDir
+    const tarExtractDir = win ? await fs.mkdtemp(path.join(os.tmpdir(), 'node-gyp-tmp-')) : devDir
 
     try {
       if (shouldDownloadTarball) {
@@ -228,7 +223,7 @@ async function install (fs, gyp, argv) {
               throw new Error(`${res.status} response downloading ${release.tarballUrl}`)
             }
 
-            await streamPipeline(
+            await pipeline(
               res.body,
               // content checksum
               new ShaSum((_, checksum) => {
@@ -267,7 +262,7 @@ async function install (fs, gyp, argv) {
       // need to download node.lib
         ...(win ? [downloadNodeLib()] : []),
         // write the "installVersion" file
-        fs.promises.writeFile(installVersionPath, gyp.package.installVersion + '\n'),
+        fs.writeFile(installVersionPath, gyp.package.installVersion + '\n'),
         // Only download SHASUMS.txt if we downloaded something in need of SHA verification
         ...(!tarPath || win ? [downloadShasums()] : [])
       ])
@@ -289,7 +284,7 @@ async function install (fs, gyp, argv) {
       if (tarExtractDir !== devDir) {
         try {
           // try to cleanup temp dir
-          await util.promisify(rm)(tarExtractDir)
+          await fs.rm(tarExtractDir, { recursive: true })
         } catch {
           log.warn('failed to clean up temp tarball extract directory')
         }
@@ -329,7 +324,7 @@ async function install (fs, gyp, argv) {
       log.verbose(name, 'dir', dir)
       log.verbose(name, 'url', libUrl)
 
-      await fs.promises.mkdir(dir, { recursive: true })
+      await fs.mkdir(dir, { recursive: true })
       log.verbose('streaming', name, 'to:', targetLibPath)
 
       const res = await download(gyp, libUrl)
@@ -339,13 +334,13 @@ async function install (fs, gyp, argv) {
         throw new Error(`${res.status} status code downloading ${name}`)
       }
 
-      return streamPipeline(
+      return pipeline(
         res.body,
         new ShaSum((_, checksum) => {
           contentShasums[libPath] = checksum
           log.verbose('content checksum', libPath, checksum)
         }),
-        fs.createWriteStream(targetLibPath)
+        createWriteStream(targetLibPath)
       )
     } // downloadNodeLib()
   } // go()
@@ -363,7 +358,7 @@ async function install (fs, gyp, argv) {
   async function rollback (err) {
     log.warn('install', 'got an error, rolling back install')
     // roll-back the install if anything went wrong
-    await util.promisify(gyp.commands.remove)([release.versionDir])
+    await gyp.commands.remove([release.versionDir])
     throw err
   }
 
@@ -394,11 +389,11 @@ async function install (fs, gyp, argv) {
       log.verbose('tmpdir == cwd', 'automatically will remove dev files after to save disk space')
       gyp.todo.push({ name: 'remove', args: argv })
     }
-    return util.promisify(gyp.commands.install)([noretry].concat(argv))
+    return gyp.commands.install([noretry].concat(argv))
   }
 }
 
-class ShaSum extends stream.Transform {
+class ShaSum extends Transform {
   constructor (callback) {
     super()
     this._callback = callback
@@ -416,43 +411,5 @@ class ShaSum extends stream.Transform {
   }
 }
 
-async function download (gyp, url) {
-  log.http('GET', url)
-
-  const requestOpts = {
-    headers: {
-      'User-Agent': `node-gyp v${gyp.version} (node ${process.version})`,
-      Connection: 'keep-alive'
-    },
-    proxy: gyp.opts.proxy,
-    noProxy: gyp.opts.noproxy
-  }
-
-  const cafile = gyp.opts.cafile
-  if (cafile) {
-    requestOpts.ca = await readCAFile(cafile)
-  }
-
-  const res = await fetch(url, requestOpts)
-  log.http(res.status, res.url)
-
-  return res
-}
-
-async function readCAFile (filename) {
-  // The CA file can contain multiple certificates so split on certificate
-  // boundaries.  [\S\s]*? is used to match everything including newlines.
-  const ca = await fs.promises.readFile(filename, 'utf8')
-  const re = /(-----BEGIN CERTIFICATE-----[\S\s]*?-----END CERTIFICATE-----)/g
-  return ca.match(re)
-}
-
-module.exports = function (gyp, argv, callback) {
-  install(fs, gyp, argv).then(callback.bind(undefined, null), callback)
-}
-module.exports.test = {
-  download,
-  install,
-  readCAFile
-}
+module.exports = install
 module.exports.usage = 'Install node development files for the specified node version.'
diff --git a/deps/npm/node_modules/node-gyp/lib/list.js b/deps/npm/node_modules/node-gyp/lib/list.js
index 405ebc0d889590..36889ad4f71e27 100644
--- a/deps/npm/node_modules/node-gyp/lib/list.js
+++ b/deps/npm/node_modules/node-gyp/lib/list.js
@@ -1,26 +1,25 @@
 'use strict'
 
-const fs = require('graceful-fs')
-const log = require('npmlog')
+const fs = require('graceful-fs').promises
+const log = require('./log')
 
-function list (gyp, args, callback) {
-  var devDir = gyp.devDir
+async function list (gyp, args) {
+  const devDir = gyp.devDir
   log.verbose('list', 'using node-gyp dir:', devDir)
 
-  fs.readdir(devDir, onreaddir)
-
-  function onreaddir (err, versions) {
-    if (err && err.code !== 'ENOENT') {
-      return callback(err)
+  let versions = []
+  try {
+    const dir = await fs.readdir(devDir)
+    if (Array.isArray(dir)) {
+      versions = dir.filter((v) => v !== 'current')
     }
-
-    if (Array.isArray(versions)) {
-      versions = versions.filter(function (v) { return v !== 'current' })
-    } else {
-      versions = []
+  } catch (err) {
+    if (err && err.code !== 'ENOENT') {
+      throw err
     }
-    callback(null, versions)
   }
+
+  return versions
 }
 
 module.exports = list
diff --git a/deps/npm/node_modules/node-gyp/lib/log.js b/deps/npm/node_modules/node-gyp/lib/log.js
new file mode 100644
index 00000000000000..6841719abab5a9
--- /dev/null
+++ b/deps/npm/node_modules/node-gyp/lib/log.js
@@ -0,0 +1,169 @@
+'use strict'
+
+const procLog = require('proc-log')
+const { format } = require('util')
+
+// helper to emit log messages with a predefined prefix
+const logLevels = Object.keys(procLog).filter((k) => typeof procLog[k] === 'function')
+const withPrefix = (prefix) => logLevels.reduce((acc, level) => {
+  acc[level] = (...args) => procLog[level](prefix, ...args)
+  return acc
+}, {})
+
+// very basic ansi color generator
+const COLORS = {
+  wrap: (str, colors) => {
+    const codes = colors.filter(c => typeof c === 'number')
+    return `\x1b[${codes.join(';')}m${str}\x1b[0m`
+  },
+  inverse: 7,
+  fg: {
+    black: 30,
+    red: 31,
+    green: 32,
+    yellow: 33,
+    blue: 34,
+    magenta: 35,
+    cyan: 36,
+    white: 37
+  },
+  bg: {
+    black: 40,
+    red: 41,
+    green: 42,
+    yellow: 43,
+    blue: 44,
+    magenta: 45,
+    cyan: 46,
+    white: 47
+  }
+}
+
+class Logger {
+  #buffer = []
+  #paused = null
+  #level = null
+  #stream = null
+
+  // ordered from loudest to quietest
+  #levels = [{
+    id: 'silly',
+    display: 'sill',
+    style: { inverse: true }
+  }, {
+    id: 'verbose',
+    display: 'verb',
+    style: { fg: 'cyan', bg: 'black' }
+  }, {
+    id: 'info',
+    style: { fg: 'green' }
+  }, {
+    id: 'http',
+    style: { fg: 'green', bg: 'black' }
+  }, {
+    id: 'notice',
+    style: { fg: 'cyan', bg: 'black' }
+  }, {
+    id: 'warn',
+    display: 'WARN',
+    style: { fg: 'black', bg: 'yellow' }
+  }, {
+    id: 'error',
+    display: 'ERR!',
+    style: { fg: 'red', bg: 'black' }
+  }]
+
+  constructor (stream) {
+    process.on('log', (...args) => this.#onLog(...args))
+    this.#levels = new Map(this.#levels.map((level, index) => [level.id, { ...level, index }]))
+    this.level = 'info'
+    this.stream = stream
+    procLog.pause()
+  }
+
+  get stream () {
+    return this.#stream
+  }
+
+  set stream (stream) {
+    this.#stream = stream
+  }
+
+  get level () {
+    return this.#levels.get(this.#level) ?? null
+  }
+
+  set level (level) {
+    this.#level = this.#levels.get(level)?.id ?? null
+  }
+
+  isVisible (level) {
+    return this.level?.index <= this.#levels.get(level)?.index ?? -1
+  }
+
+  #onLog (...args) {
+    const [level] = args
+
+    if (level === 'pause') {
+      this.#paused = true
+      return
+    }
+
+    if (level === 'resume') {
+      this.#paused = false
+      this.#buffer.forEach((b) => this.#log(...b))
+      this.#buffer.length = 0
+      return
+    }
+
+    if (this.#paused) {
+      this.#buffer.push(args)
+      return
+    }
+
+    this.#log(...args)
+  }
+
+  #color (str, { fg, bg, inverse }) {
+    if (!this.#stream?.isTTY) {
+      return str
+    }
+
+    return COLORS.wrap(str, [
+      COLORS.fg[fg],
+      COLORS.bg[bg],
+      inverse && COLORS.inverse
+    ])
+  }
+
+  #log (levelId, msgPrefix, ...args) {
+    if (!this.isVisible(levelId) || typeof this.#stream?.write !== 'function') {
+      return
+    }
+
+    const level = this.#levels.get(levelId)
+
+    const prefixParts = [
+      this.#color('gyp', { fg: 'white', bg: 'black' }),
+      this.#color(level.display ?? level.id, level.style)
+    ]
+    if (msgPrefix) {
+      prefixParts.push(this.#color(msgPrefix, { fg: 'magenta' }))
+    }
+
+    const prefix = prefixParts.join(' ').trim() + ' '
+    const lines = format(...args).split(/\r?\n/).map(l => prefix + l.trim())
+
+    this.#stream.write(lines.join('\n') + '\n')
+  }
+}
+
+// used to suppress logs in tests
+const NULL_LOGGER = !!process.env.NODE_GYP_NULL_LOGGER
+
+module.exports = {
+  logger: new Logger(NULL_LOGGER ? null : process.stderr),
+  stdout: NULL_LOGGER ? () => {} : (...args) => console.log(...args),
+  withPrefix,
+  ...procLog
+}
diff --git a/deps/npm/node_modules/node-gyp/lib/node-gyp.js b/deps/npm/node_modules/node-gyp/lib/node-gyp.js
index e492ec1026d9d3..5e25bf996f8b22 100644
--- a/deps/npm/node_modules/node-gyp/lib/node-gyp.js
+++ b/deps/npm/node_modules/node-gyp/lib/node-gyp.js
@@ -2,10 +2,10 @@
 
 const path = require('path')
 const nopt = require('nopt')
-const log = require('npmlog')
+const log = require('./log')
 const childProcess = require('child_process')
-const EE = require('events').EventEmitter
-const inherits = require('util').inherits
+const { EventEmitter } = require('events')
+
 const commands = [
   // Module build commands
   'build',
@@ -17,199 +17,172 @@ const commands = [
   'list',
   'remove'
 ]
-const aliases = {
-  ls: 'list',
-  rm: 'remove'
-}
-
-// differentiate node-gyp's logs from npm's
-log.heading = 'gyp'
-
-function gyp () {
-  return new Gyp()
-}
 
-function Gyp () {
-  var self = this
+class Gyp extends EventEmitter {
+  /**
+   * Export the contents of the package.json.
+   */
+  package = require('../package.json')
+
+  /**
+   * nopt configuration definitions
+   */
+  configDefs = {
+    help: Boolean, // everywhere
+    arch: String, // 'configure'
+    cafile: String, // 'install'
+    debug: Boolean, // 'build'
+    directory: String, // bin
+    make: String, // 'build'
+    'msvs-version': String, // 'configure'
+    ensure: Boolean, // 'install'
+    solution: String, // 'build' (windows only)
+    proxy: String, // 'install'
+    noproxy: String, // 'install'
+    devdir: String, // everywhere
+    nodedir: String, // 'configure'
+    loglevel: String, // everywhere
+    python: String, // 'configure'
+    'dist-url': String, // 'install'
+    tarball: String, // 'install'
+    jobs: String, // 'build'
+    thin: String, // 'configure'
+    'force-process-config': Boolean // 'configure'
+  }
 
-  this.devDir = ''
-  this.commands = {}
+  /**
+   * nopt shorthands
+   */
+  shorthands = {
+    release: '--no-debug',
+    C: '--directory',
+    debug: '--debug',
+    j: '--jobs',
+    silly: '--loglevel=silly',
+    verbose: '--loglevel=verbose',
+    silent: '--loglevel=silent'
+  }
 
-  commands.forEach(function (command) {
-    self.commands[command] = function (argv, callback) {
-      log.verbose('command', command, argv)
-      return require('./' + command)(self, argv, callback)
-    }
-  })
-}
-inherits(Gyp, EE)
-exports.Gyp = Gyp
-var proto = Gyp.prototype
-
-/**
- * Export the contents of the package.json.
- */
-
-proto.package = require('../package.json')
-
-/**
- * nopt configuration definitions
- */
-
-proto.configDefs = {
-  help: Boolean, // everywhere
-  arch: String, // 'configure'
-  cafile: String, // 'install'
-  debug: Boolean, // 'build'
-  directory: String, // bin
-  make: String, // 'build'
-  msvs_version: String, // 'configure'
-  ensure: Boolean, // 'install'
-  solution: String, // 'build' (windows only)
-  proxy: String, // 'install'
-  noproxy: String, // 'install'
-  devdir: String, // everywhere
-  nodedir: String, // 'configure'
-  loglevel: String, // everywhere
-  python: String, // 'configure'
-  'dist-url': String, // 'install'
-  tarball: String, // 'install'
-  jobs: String, // 'build'
-  thin: String, // 'configure'
-  'force-process-config': Boolean // 'configure'
-}
+  /**
+   * expose the command aliases for the bin file to use.
+   */
+  aliases = {
+    ls: 'list',
+    rm: 'remove'
+  }
 
-/**
- * nopt shorthands
- */
-
-proto.shorthands = {
-  release: '--no-debug',
-  C: '--directory',
-  debug: '--debug',
-  j: '--jobs',
-  silly: '--loglevel=silly',
-  verbose: '--loglevel=verbose',
-  silent: '--loglevel=silent'
-}
+  constructor (...args) {
+    super(...args)
 
-/**
- * expose the command aliases for the bin file to use.
- */
+    this.devDir = ''
 
-proto.aliases = aliases
+    this.commands = commands.reduce((acc, command) => {
+      acc[command] = (argv) => require('./' + command)(this, argv)
+      return acc
+    }, {})
 
-/**
- * Parses the given argv array and sets the 'opts',
- * 'argv' and 'command' properties.
- */
+    Object.defineProperty(this, 'version', {
+      enumerable: true,
+      get: function () { return this.package.version }
+    })
+  }
 
-proto.parseArgv = function parseOpts (argv) {
-  this.opts = nopt(this.configDefs, this.shorthands, argv)
-  this.argv = this.opts.argv.remain.slice()
+  /**
+   * Parses the given argv array and sets the 'opts',
+   * 'argv' and 'command' properties.
+   */
+  parseArgv (argv) {
+    this.opts = nopt(this.configDefs, this.shorthands, argv)
+    this.argv = this.opts.argv.remain.slice()
 
-  var commands = this.todo = []
+    const commands = this.todo = []
 
-  // create a copy of the argv array with aliases mapped
-  argv = this.argv.map(function (arg) {
+    // create a copy of the argv array with aliases mapped
+    argv = this.argv.map((arg) => {
     // is this an alias?
-    if (arg in this.aliases) {
-      arg = this.aliases[arg]
-    }
-    return arg
-  }, this)
-
-  // process the mapped args into "command" objects ("name" and "args" props)
-  argv.slice().forEach(function (arg) {
-    if (arg in this.commands) {
-      var args = argv.splice(0, argv.indexOf(arg))
-      argv.shift()
-      if (commands.length > 0) {
-        commands[commands.length - 1].args = args
+      if (arg in this.aliases) {
+        arg = this.aliases[arg]
+      }
+      return arg
+    })
+
+    // process the mapped args into "command" objects ("name" and "args" props)
+    argv.slice().forEach((arg) => {
+      if (arg in this.commands) {
+        const args = argv.splice(0, argv.indexOf(arg))
+        argv.shift()
+        if (commands.length > 0) {
+          commands[commands.length - 1].args = args
+        }
+        commands.push({ name: arg, args: [] })
       }
-      commands.push({ name: arg, args: [] })
+    })
+    if (commands.length > 0) {
+      commands[commands.length - 1].args = argv.splice(0)
     }
-  }, this)
-  if (commands.length > 0) {
-    commands[commands.length - 1].args = argv.splice(0)
-  }
 
-  // support for inheriting config env variables from npm
-  var npmConfigPrefix = 'npm_config_'
-  Object.keys(process.env).forEach(function (name) {
-    if (name.indexOf(npmConfigPrefix) !== 0) {
-      return
-    }
-    var val = process.env[name]
-    if (name === npmConfigPrefix + 'loglevel') {
-      log.level = val
-    } else {
+    // support for inheriting config env variables from npm
+    const npmConfigPrefix = 'npm_config_'
+    Object.keys(process.env).forEach((name) => {
+      if (name.indexOf(npmConfigPrefix) !== 0) {
+        return
+      }
+      const val = process.env[name]
+      if (name === npmConfigPrefix + 'loglevel') {
+        log.logger.level = val
+      } else {
       // add the user-defined options to the config
-      name = name.substring(npmConfigPrefix.length)
-      // gyp@741b7f1 enters an infinite loop when it encounters
-      // zero-length options so ensure those don't get through.
-      if (name) {
+        name = name.substring(npmConfigPrefix.length)
+        // gyp@741b7f1 enters an infinite loop when it encounters
+        // zero-length options so ensure those don't get through.
+        if (name) {
         // convert names like force_process_config to force-process-config
-        if (name.includes('_')) {
-          name = name.replace(/_/g, '-')
+          if (name.includes('_')) {
+            name = name.replace(/_/g, '-')
+          }
+          this.opts[name] = val
         }
-        this.opts[name] = val
       }
-    }
-  }, this)
+    })
 
-  if (this.opts.loglevel) {
-    log.level = this.opts.loglevel
+    if (this.opts.loglevel) {
+      log.logger.level = this.opts.loglevel
+    }
+    log.resume()
   }
-  log.resume()
-}
-
-/**
- * Spawns a child process and emits a 'spawn' event.
- */
 
-proto.spawn = function spawn (command, args, opts) {
-  if (!opts) {
-    opts = {}
-  }
-  if (!opts.silent && !opts.stdio) {
-    opts.stdio = [0, 1, 2]
+  /**
+   * Spawns a child process and emits a 'spawn' event.
+   */
+  spawn (command, args, opts) {
+    if (!opts) {
+      opts = {}
+    }
+    if (!opts.silent && !opts.stdio) {
+      opts.stdio = [0, 1, 2]
+    }
+    const cp = childProcess.spawn(command, args, opts)
+    log.info('spawn', command)
+    log.info('spawn args', args)
+    return cp
   }
-  var cp = childProcess.spawn(command, args, opts)
-  log.info('spawn', command)
-  log.info('spawn args', args)
-  return cp
-}
 
-/**
- * Returns the usage instructions for node-gyp.
- */
-
-proto.usage = function usage () {
-  var str = [
-    '',
-    '  Usage: node-gyp  [options]',
-    '',
-    '  where  is one of:',
-    commands.map(function (c) {
-      return '    - ' + c + ' - ' + require('./' + c).usage
-    }).join('\n'),
-    '',
-    'node-gyp@' + this.version + '  ' + path.resolve(__dirname, '..'),
-    'node@' + process.versions.node
-  ].join('\n')
-  return str
+  /**
+   * Returns the usage instructions for node-gyp.
+   */
+  usage () {
+    return [
+      '',
+      '  Usage: node-gyp  [options]',
+      '',
+      '  where  is one of:',
+      commands.map((c) => '    - ' + c + ' - ' + require('./' + c).usage).join('\n'),
+      '',
+      'node-gyp@' + this.version + '  ' + path.resolve(__dirname, '..'),
+      'node@' + process.versions.node
+    ].join('\n')
+  }
 }
 
-/**
- * Version number getter.
- */
-
-Object.defineProperty(proto, 'version', {
-  get: function () {
-    return this.package.version
-  },
-  enumerable: true
-})
-
-module.exports = exports = gyp
+module.exports = () => new Gyp()
+module.exports.Gyp = Gyp
diff --git a/deps/npm/node_modules/node-gyp/lib/process-release.js b/deps/npm/node_modules/node-gyp/lib/process-release.js
index 95b55e4426dee7..c9a319dfadd2bc 100644
--- a/deps/npm/node_modules/node-gyp/lib/process-release.js
+++ b/deps/npm/node_modules/node-gyp/lib/process-release.js
@@ -1,11 +1,11 @@
-/* eslint-disable node/no-deprecated-api */
+/* eslint-disable n/no-deprecated-api */
 
 'use strict'
 
 const semver = require('semver')
 const url = require('url')
 const path = require('path')
-const log = require('npmlog')
+const log = require('./log')
 
 // versions where -headers.tar.gz started shipping
 const headersTarballRange = '>= 3.0.0 || ~0.12.10 || ~0.10.42'
@@ -17,29 +17,28 @@ const bitsreV3 = /\/win-(x86|ia32|x64)\// // io.js v3.x.x shipped with "ia32" bu
 // file names. Inputs come from command-line switches (--target, --dist-url),
 // `process.version` and `process.release` where it exists.
 function processRelease (argv, gyp, defaultVersion, defaultRelease) {
-  var version = (semver.valid(argv[0]) && argv[0]) || gyp.opts.target || defaultVersion
-  var versionSemver = semver.parse(version)
-  var overrideDistUrl = gyp.opts['dist-url'] || gyp.opts.disturl
-  var isDefaultVersion
-  var isNamedForLegacyIojs
-  var name
-  var distBaseUrl
-  var baseUrl
-  var libUrl32
-  var libUrl64
-  var libUrlArm64
-  var tarballUrl
-  var canGetHeaders
+  let version = (semver.valid(argv[0]) && argv[0]) || gyp.opts.target || defaultVersion
+  const versionSemver = semver.parse(version)
+  let overrideDistUrl = gyp.opts['dist-url'] || gyp.opts.disturl
+  let isNamedForLegacyIojs
+  let name
+  let distBaseUrl
+  let baseUrl
+  let libUrl32
+  let libUrl64
+  let libUrlArm64
+  let tarballUrl
+  let canGetHeaders
 
   if (!versionSemver) {
     // not a valid semver string, nothing we can do
-    return { version: version }
+    return { version }
   }
   // flatten version into String
   version = versionSemver.version
 
   // defaultVersion should come from process.version so ought to be valid semver
-  isDefaultVersion = version === semver.parse(defaultVersion).version
+  const isDefaultVersion = version === semver.parse(defaultVersion).version
 
   // can't use process.release if we're using --target=x.y.z
   if (!isDefaultVersion) {
@@ -101,11 +100,11 @@ function processRelease (argv, gyp, defaultVersion, defaultRelease) {
   }
 
   return {
-    version: version,
+    version,
     semver: versionSemver,
-    name: name,
-    baseUrl: baseUrl,
-    tarballUrl: tarballUrl,
+    name,
+    baseUrl,
+    tarballUrl,
     shasumsUrl: url.resolve(baseUrl, 'SHASUMS256.txt'),
     versionDir: (name !== 'node' ? name + '-' : '') + version,
     ia32: {
@@ -128,8 +127,8 @@ function normalizePath (p) {
 }
 
 function resolveLibUrl (name, defaultUrl, arch, versionMajor) {
-  var base = url.resolve(defaultUrl, './')
-  var hasLibUrl = bitsre.test(defaultUrl) || (versionMajor === 3 && bitsreV3.test(defaultUrl))
+  const base = url.resolve(defaultUrl, './')
+  const hasLibUrl = bitsre.test(defaultUrl) || (versionMajor === 3 && bitsreV3.test(defaultUrl))
 
   if (!hasLibUrl) {
     // let's assume it's a baseUrl then
diff --git a/deps/npm/node_modules/node-gyp/lib/rebuild.js b/deps/npm/node_modules/node-gyp/lib/rebuild.js
index a1c5b27cbe56a5..609817665e2dba 100644
--- a/deps/npm/node_modules/node-gyp/lib/rebuild.js
+++ b/deps/npm/node_modules/node-gyp/lib/rebuild.js
@@ -1,12 +1,11 @@
 'use strict'
 
-function rebuild (gyp, argv, callback) {
+async function rebuild (gyp, argv) {
   gyp.todo.push(
     { name: 'clean', args: [] }
     , { name: 'configure', args: argv }
     , { name: 'build', args: [] }
   )
-  process.nextTick(callback)
 }
 
 module.exports = rebuild
diff --git a/deps/npm/node_modules/node-gyp/lib/remove.js b/deps/npm/node_modules/node-gyp/lib/remove.js
index 8c945e5659001c..7efdb01a662e76 100644
--- a/deps/npm/node_modules/node-gyp/lib/remove.js
+++ b/deps/npm/node_modules/node-gyp/lib/remove.js
@@ -1,46 +1,43 @@
 'use strict'
 
-const fs = require('fs')
-const rm = require('rimraf')
+const fs = require('graceful-fs').promises
 const path = require('path')
-const log = require('npmlog')
+const log = require('./log')
 const semver = require('semver')
 
-function remove (gyp, argv, callback) {
-  var devDir = gyp.devDir
+async function remove (gyp, argv) {
+  const devDir = gyp.devDir
   log.verbose('remove', 'using node-gyp dir:', devDir)
 
   // get the user-specified version to remove
-  var version = argv[0] || gyp.opts.target
+  let version = argv[0] || gyp.opts.target
   log.verbose('remove', 'removing target version:', version)
 
   if (!version) {
-    return callback(new Error('You must specify a version number to remove. Ex: "' + process.version + '"'))
+    throw new Error('You must specify a version number to remove. Ex: "' + process.version + '"')
   }
 
-  var versionSemver = semver.parse(version)
+  const versionSemver = semver.parse(version)
   if (versionSemver) {
     // flatten the version Array into a String
     version = versionSemver.version
   }
 
-  var versionPath = path.resolve(gyp.devDir, version)
+  const versionPath = path.resolve(gyp.devDir, version)
   log.verbose('remove', 'removing development files for version:', version)
 
   // first check if its even installed
-  fs.stat(versionPath, function (err) {
-    if (err) {
-      if (err.code === 'ENOENT') {
-        callback(null, 'version was already uninstalled: ' + version)
-      } else {
-        callback(err)
-      }
-      return
+  try {
+    await fs.stat(versionPath)
+  } catch (err) {
+    if (err.code === 'ENOENT') {
+      return 'version was already uninstalled: ' + version
     }
-    // Go ahead and delete the dir
-    rm(versionPath, callback)
-  })
+    throw err
+  }
+
+  await fs.rm(versionPath, { recursive: true, force: true })
 }
 
-module.exports = exports = remove
+module.exports = remove
 module.exports.usage = 'Removes the node development files for the specified version'
diff --git a/deps/npm/node_modules/node-gyp/lib/util.js b/deps/npm/node_modules/node-gyp/lib/util.js
index 3e23c628e6ad71..3f6aeeb7dcb436 100644
--- a/deps/npm/node_modules/node-gyp/lib/util.js
+++ b/deps/npm/node_modules/node-gyp/lib/util.js
@@ -1,64 +1,81 @@
 'use strict'
 
-const log = require('npmlog')
-const execFile = require('child_process').execFile
+const cp = require('child_process')
 const path = require('path')
+const { openSync, closeSync } = require('graceful-fs')
+const log = require('./log')
 
-function logWithPrefix (log, prefix) {
-  function setPrefix (logFunction) {
-    return (...args) => logFunction.apply(null, [ prefix, ...args ]) // eslint-disable-line
-  }
-  return {
-    silly: setPrefix(log.silly),
-    verbose: setPrefix(log.verbose),
-    info: setPrefix(log.info),
-    warn: setPrefix(log.warn),
-    error: setPrefix(log.error)
-  }
-}
+const execFile = async (...args) => new Promise((resolve) => {
+  const child = cp.execFile(...args, (...a) => resolve(a))
+  child.stdin.end()
+})
 
-function regGetValue (key, value, addOpts, cb) {
+async function regGetValue (key, value, addOpts) {
   const outReValue = value.replace(/\W/g, '.')
   const outRe = new RegExp(`^\\s+${outReValue}\\s+REG_\\w+\\s+(\\S.*)$`, 'im')
   const reg = path.join(process.env.SystemRoot, 'System32', 'reg.exe')
   const regArgs = ['query', key, '/v', value].concat(addOpts)
 
   log.silly('reg', 'running', reg, regArgs)
-  const child = execFile(reg, regArgs, { encoding: 'utf8' },
-    function (err, stdout, stderr) {
-      log.silly('reg', 'reg.exe stdout = %j', stdout)
-      if (err || stderr.trim() !== '') {
-        log.silly('reg', 'reg.exe err = %j', err && (err.stack || err))
-        log.silly('reg', 'reg.exe stderr = %j', stderr)
-        return cb(err, stderr)
-      }
+  const [err, stdout, stderr] = await execFile(reg, regArgs, { encoding: 'utf8' })
 
-      const result = outRe.exec(stdout)
-      if (!result) {
-        log.silly('reg', 'error parsing stdout')
-        return cb(new Error('Could not parse output of reg.exe'))
-      }
-      log.silly('reg', 'found: %j', result[1])
-      cb(null, result[1])
-    })
-  child.stdin.end()
+  log.silly('reg', 'reg.exe stdout = %j', stdout)
+  if (err || stderr.trim() !== '') {
+    log.silly('reg', 'reg.exe err = %j', err && (err.stack || err))
+    log.silly('reg', 'reg.exe stderr = %j', stderr)
+    if (err) {
+      throw err
+    }
+    throw new Error(stderr)
+  }
+
+  const result = outRe.exec(stdout)
+  if (!result) {
+    log.silly('reg', 'error parsing stdout')
+    throw new Error('Could not parse output of reg.exe')
+  }
+
+  log.silly('reg', 'found: %j', result[1])
+  return result[1]
+}
+
+async function regSearchKeys (keys, value, addOpts) {
+  for (const key of keys) {
+    try {
+      return await regGetValue(key, value, addOpts)
+    } catch {
+      continue
+    }
+  }
 }
 
-function regSearchKeys (keys, value, addOpts, cb) {
-  var i = 0
-  const search = () => {
-    log.silly('reg-search', 'looking for %j in %j', value, keys[i])
-    regGetValue(keys[i], value, addOpts, (err, res) => {
-      ++i
-      if (err && i < keys.length) { return search() }
-      cb(err, res)
-    })
+/**
+ * Returns the first file or directory from an array of candidates that is
+ * readable by the current user, or undefined if none of the candidates are
+ * readable.
+ */
+function findAccessibleSync (logprefix, dir, candidates) {
+  for (let next = 0; next < candidates.length; next++) {
+    const candidate = path.resolve(dir, candidates[next])
+    let fd
+    try {
+      fd = openSync(candidate, 'r')
+    } catch (e) {
+      // this candidate was not found or not readable, do nothing
+      log.silly(logprefix, 'Could not open %s: %s', candidate, e.message)
+      continue
+    }
+    closeSync(fd)
+    log.silly(logprefix, 'Found readable %s', candidate)
+    return candidate
   }
-  search()
+
+  return undefined
 }
 
 module.exports = {
-  logWithPrefix: logWithPrefix,
-  regGetValue: regGetValue,
-  regSearchKeys: regSearchKeys
+  execFile,
+  regGetValue,
+  regSearchKeys,
+  findAccessibleSync
 }
diff --git a/deps/npm/node_modules/node-gyp/macOS_Catalina.md b/deps/npm/node_modules/node-gyp/macOS_Catalina.md
deleted file mode 100644
index dde5fe3f7d4fbf..00000000000000
--- a/deps/npm/node_modules/node-gyp/macOS_Catalina.md
+++ /dev/null
@@ -1,104 +0,0 @@
-# Installation notes for macOS Catalina (v10.15)
-
-_This document specifically refers to upgrades from previous versions of macOS to Catalina (10.15). It should be removed from the source repository when Catalina ceases to be the latest macOS version or when future Catalina versions no longer raise these issues._
-
-**Both upgrading to macOS Catalina and running a Software Update in Catalina may cause normal `node-gyp` installations to fail. This might manifest as the following error during `npm install`:**
-
-```console
-gyp: No Xcode or CLT version detected!
-```
-
-## node-gyp v7
-
-The newest release of `node-gyp` should solve this problem. If you are using `node-gyp` directly then you should be able to install v7 and use it as-is.
-
-If you need to use `node-gyp` from within `npm` (e.g. through `npm install`), you will have to install `node-gyp` (either globally with `-g` or to a predictable location) and tell `npm` where the new version is. Either use:
-
-* `npm config set node_gyp `; or
-* run `npm` with an environment variable prefix: `npm_config_node_gyp= npm install`
-
-Where "path to node-gyp" is to the `node-gyp` executable which may be a symlink in your global bin directory (e.g. `/usr/local/bin/node-gyp`), or a path to the `node-gyp` installation directory and the `bin/node-gyp.js` file within it (e.g. `/usr/local/lib/node_modules/node-gyp/bin/node-gyp.js`).
-
-**If you use `npm config set` to change your global `node_gyp` you are responsible for keeping it up to date and can't rely on `npm` to give you a newer version when available.** Use `npm config delete node_gyp` to unset this configuration option.
-
-## Fixing Catalina for older versions of `node-gyp`
-
-### Is my Mac running macOS Catalina?
-Let's first make sure that your Mac is running Catalina:
-```
-% sw_vers
-    ProductName:	Mac OS X
-    ProductVersion:	10.15
-    BuildVersion:	19A602
-```
-If `ProductVersion` is less then `10.15` then this document is not for you. Normal install docs for `node-gyp` on macOS can be found at https://github.com/nodejs/node-gyp#on-macos
-
-
-### The acid test
-To see if `Xcode Command Line Tools` is installed in a way that will work with `node-gyp`, run:
-```
-curl -sL https://github.com/nodejs/node-gyp/raw/main/macOS_Catalina_acid_test.sh | bash
-```
-
-If test succeeded, _you are done_! You should be ready to [install](https://github.com/nodejs/node-gyp#installation) `node-gyp`.
-
-If test failed, there is a problem with your Xcode Command Line Tools installation. [Continue to Solutions](#Solutions).
-
-### Solutions
-There are three ways to install the Xcode libraries `node-gyp` needs on macOS. People running Catalina have had success with some but not others in a way that has been unpredictable.
-
-1. With the full Xcode (~7.6 GB download) from the `App Store` app.
-2. With the _much_ smaller Xcode Command Line Tools via `xcode-select --install`
-3. With the _much_ smaller Xcode Command Line Tools via manual download. **For people running the latest version of Catalina (10.15.2 at the time of this writing), this has worked when the other two solutions haven't.**
-
-### Installing `node-gyp` using the full Xcode
-1. `xcodebuild -version` should show `Xcode 11.1` or later.
-    * If not, then install/upgrade Xcode from the App Store app.
-2. Open the Xcode app and...
-    * Under __Preferences > Locations__ select the tools if their location is empty.
-    * Allow Xcode app to do an essential install of the most recent compiler tools.
-3. Once all installations are _complete_, quit out of Xcode.
-4. `sudo xcodebuild -license accept`  # If you agree with the licensing terms.
-5. `softwareupdate -l`  # No listing is a good sign.
-    * If Xcode or Tools upgrades are listed, use "Software Upgrade" to install them.
-6. `xcode-select -version`  # Should return `xcode-select version 2370` or later.
-7. `xcode-select -print-path`  # Should return `/Applications/Xcode.app/Contents/Developer`
-8. Try the [_acid test_ steps above](#The-acid-test) to see if your Mac is ready.
-9. If the _acid test_ does _not_ pass then...
-10. `sudo xcode-select --reset`  # Enter root password.  No output is normal.
-11. Repeat step 7 above.  Is the path different this time?  Repeat the _acid test_.
-
-### Installing `node-gyp` using the Xcode Command Line Tools via `xcode-select --install`
-1. If the _acid test_ has not succeeded, then try `xcode-select --install`
-2. If the installation command returns `xcode-select: error: command line tools are already installed, use "Software Update" to install updates`, continue to [remove and reinstall](#i-did-all-that-and-the-acid-test-still-does-not-pass--)
-3. Wait until the install process is _complete_.
-4. `softwareupdate -l`  # No listing is a good sign.
-    * If Xcode or Tools upgrades are listed, use "Software Update" to install them.
-5. `xcode-select -version`  # Should return `xcode-select version 2370` or later.
-6. `xcode-select -print-path`  # Should return `/Library/Developer/CommandLineTools`
-7. Try the [_acid test_ steps above](#The-acid-test) to see if your Mac is ready.
-8. If the _acid test_ does _not_ pass then...
-9. `sudo xcode-select --reset`  # Enter root password.  No output is normal.
-10. Repeat step 5 above.  Is the path different this time?  Repeat the _acid test_.
-
-### Installing `node-gyp` using the Xcode Command Line Tools via manual download
-1. Download the appropriate version of the "Command Line Tools for Xcode" for your version of Catalina from . As of MacOS 10.15.5, that's [Command_Line_Tools_for_Xcode_11.5.dmg](https://download.developer.apple.com/Developer_Tools/Command_Line_Tools_for_Xcode_11.5/Command_Line_Tools_for_Xcode_11.5.dmg)
-2. Install the package.
-3. Run the [_acid test_ steps above](#The-acid-test).
-
-### I did all that and the acid test still does not pass :-(
-1. `sudo rm -rf $(xcode-select -print-path)`  # Enter root password.  No output is normal.
-2. `sudo rm -rf /Library/Developer/CommandLineTools`  # Enter root password.
-3. `sudo xcode-select --reset`
-4. `xcode-select --install`
-5. If the [_acid test_ steps above](#The-acid-test) still does _not_ pass then...
-6. `npm explore npm -g -- npm install node-gyp@latest`
-7. `npm explore npm -g -- npm explore npm-lifecycle -- npm install node-gyp@latest`
-8. If the _acid test_ still does _not_ pass then...
-9. Add a comment to https://github.com/nodejs/node-gyp/issues/1927 so we can improve.
-
-Lessons learned from:
-* https://github.com/nodejs/node-gyp/issues/1779
-* https://github.com/nodejs/node-gyp/issues/1861
-* https://github.com/nodejs/node-gyp/issues/1927 and elsewhere
-* Thanks to @rrrix for discovering Solution 3
diff --git a/deps/npm/node_modules/node-gyp/node_modules/abbrev/LICENSE b/deps/npm/node_modules/node-gyp/node_modules/abbrev/LICENSE
deleted file mode 100644
index 9bcfa9d7d8d26e..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/abbrev/LICENSE
+++ /dev/null
@@ -1,46 +0,0 @@
-This software is dual-licensed under the ISC and MIT licenses.
-You may use this software under EITHER of the following licenses.
-
-----------
-
-The ISC License
-
-Copyright (c) Isaac Z. Schlueter and Contributors
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-----------
-
-Copyright Isaac Z. Schlueter and 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.
diff --git a/deps/npm/node_modules/node-gyp/node_modules/abbrev/abbrev.js b/deps/npm/node_modules/node-gyp/node_modules/abbrev/abbrev.js
deleted file mode 100644
index 7b1dc5d67694a2..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/abbrev/abbrev.js
+++ /dev/null
@@ -1,61 +0,0 @@
-module.exports = exports = abbrev.abbrev = abbrev
-
-abbrev.monkeyPatch = monkeyPatch
-
-function monkeyPatch () {
-  Object.defineProperty(Array.prototype, 'abbrev', {
-    value: function () { return abbrev(this) },
-    enumerable: false, configurable: true, writable: true
-  })
-
-  Object.defineProperty(Object.prototype, 'abbrev', {
-    value: function () { return abbrev(Object.keys(this)) },
-    enumerable: false, configurable: true, writable: true
-  })
-}
-
-function abbrev (list) {
-  if (arguments.length !== 1 || !Array.isArray(list)) {
-    list = Array.prototype.slice.call(arguments, 0)
-  }
-  for (var i = 0, l = list.length, args = [] ; i < l ; i ++) {
-    args[i] = typeof list[i] === "string" ? list[i] : String(list[i])
-  }
-
-  // sort them lexicographically, so that they're next to their nearest kin
-  args = args.sort(lexSort)
-
-  // walk through each, seeing how much it has in common with the next and previous
-  var abbrevs = {}
-    , prev = ""
-  for (var i = 0, l = args.length ; i < l ; i ++) {
-    var current = args[i]
-      , next = args[i + 1] || ""
-      , nextMatches = true
-      , prevMatches = true
-    if (current === next) continue
-    for (var j = 0, cl = current.length ; j < cl ; j ++) {
-      var curChar = current.charAt(j)
-      nextMatches = nextMatches && curChar === next.charAt(j)
-      prevMatches = prevMatches && curChar === prev.charAt(j)
-      if (!nextMatches && !prevMatches) {
-        j ++
-        break
-      }
-    }
-    prev = current
-    if (j === cl) {
-      abbrevs[current] = current
-      continue
-    }
-    for (var a = current.substr(0, j) ; j <= cl ; j ++) {
-      abbrevs[a] = current
-      a += current.charAt(j)
-    }
-  }
-  return abbrevs
-}
-
-function lexSort (a, b) {
-  return a === b ? 0 : a > b ? 1 : -1
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/abbrev/package.json b/deps/npm/node_modules/node-gyp/node_modules/abbrev/package.json
deleted file mode 100644
index bf4e8015bba9d5..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/abbrev/package.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-  "name": "abbrev",
-  "version": "1.1.1",
-  "description": "Like ruby's abbrev module, but in js",
-  "author": "Isaac Z. Schlueter ",
-  "main": "abbrev.js",
-  "scripts": {
-    "test": "tap test.js --100",
-    "preversion": "npm test",
-    "postversion": "npm publish",
-    "postpublish": "git push origin --all; git push origin --tags"
-  },
-  "repository": "http://github.com/isaacs/abbrev-js",
-  "license": "ISC",
-  "devDependencies": {
-    "tap": "^10.1"
-  },
-  "files": [
-    "abbrev.js"
-  ]
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/are-we-there-yet/LICENSE.md b/deps/npm/node_modules/node-gyp/node_modules/are-we-there-yet/LICENSE.md
deleted file mode 100644
index 845be76f64e789..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/are-we-there-yet/LICENSE.md
+++ /dev/null
@@ -1,18 +0,0 @@
-ISC License
-
-Copyright npm, Inc.
-
-Permission to use, copy, modify, and/or distribute this
-software for any purpose with or without fee is hereby
-granted, provided that the above copyright notice and this
-permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND NPM DISCLAIMS ALL
-WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
-EVENT SHALL NPM BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
-USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/deps/npm/node_modules/node-gyp/node_modules/are-we-there-yet/lib/index.js b/deps/npm/node_modules/node-gyp/node_modules/are-we-there-yet/lib/index.js
deleted file mode 100644
index 57d8743fdad177..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/are-we-there-yet/lib/index.js
+++ /dev/null
@@ -1,4 +0,0 @@
-'use strict'
-exports.TrackerGroup = require('./tracker-group.js')
-exports.Tracker = require('./tracker.js')
-exports.TrackerStream = require('./tracker-stream.js')
diff --git a/deps/npm/node_modules/node-gyp/node_modules/are-we-there-yet/lib/tracker-base.js b/deps/npm/node_modules/node-gyp/node_modules/are-we-there-yet/lib/tracker-base.js
deleted file mode 100644
index 6f436875578a7a..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/are-we-there-yet/lib/tracker-base.js
+++ /dev/null
@@ -1,11 +0,0 @@
-'use strict'
-var EventEmitter = require('events').EventEmitter
-var util = require('util')
-
-var trackerId = 0
-var TrackerBase = module.exports = function (name) {
-  EventEmitter.call(this)
-  this.id = ++trackerId
-  this.name = name
-}
-util.inherits(TrackerBase, EventEmitter)
diff --git a/deps/npm/node_modules/node-gyp/node_modules/are-we-there-yet/lib/tracker-group.js b/deps/npm/node_modules/node-gyp/node_modules/are-we-there-yet/lib/tracker-group.js
deleted file mode 100644
index a3c7af804c4d3b..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/are-we-there-yet/lib/tracker-group.js
+++ /dev/null
@@ -1,116 +0,0 @@
-'use strict'
-var util = require('util')
-var TrackerBase = require('./tracker-base.js')
-var Tracker = require('./tracker.js')
-var TrackerStream = require('./tracker-stream.js')
-
-var TrackerGroup = module.exports = function (name) {
-  TrackerBase.call(this, name)
-  this.parentGroup = null
-  this.trackers = []
-  this.completion = {}
-  this.weight = {}
-  this.totalWeight = 0
-  this.finished = false
-  this.bubbleChange = bubbleChange(this)
-}
-util.inherits(TrackerGroup, TrackerBase)
-
-function bubbleChange (trackerGroup) {
-  return function (name, completed, tracker) {
-    trackerGroup.completion[tracker.id] = completed
-    if (trackerGroup.finished) {
-      return
-    }
-    trackerGroup.emit('change', name || trackerGroup.name, trackerGroup.completed(), trackerGroup)
-  }
-}
-
-TrackerGroup.prototype.nameInTree = function () {
-  var names = []
-  var from = this
-  while (from) {
-    names.unshift(from.name)
-    from = from.parentGroup
-  }
-  return names.join('/')
-}
-
-TrackerGroup.prototype.addUnit = function (unit, weight) {
-  if (unit.addUnit) {
-    var toTest = this
-    while (toTest) {
-      if (unit === toTest) {
-        throw new Error(
-          'Attempted to add tracker group ' +
-          unit.name + ' to tree that already includes it ' +
-          this.nameInTree(this))
-      }
-      toTest = toTest.parentGroup
-    }
-    unit.parentGroup = this
-  }
-  this.weight[unit.id] = weight || 1
-  this.totalWeight += this.weight[unit.id]
-  this.trackers.push(unit)
-  this.completion[unit.id] = unit.completed()
-  unit.on('change', this.bubbleChange)
-  if (!this.finished) {
-    this.emit('change', unit.name, this.completion[unit.id], unit)
-  }
-  return unit
-}
-
-TrackerGroup.prototype.completed = function () {
-  if (this.trackers.length === 0) {
-    return 0
-  }
-  var valPerWeight = 1 / this.totalWeight
-  var completed = 0
-  for (var ii = 0; ii < this.trackers.length; ii++) {
-    var trackerId = this.trackers[ii].id
-    completed +=
-      valPerWeight * this.weight[trackerId] * this.completion[trackerId]
-  }
-  return completed
-}
-
-TrackerGroup.prototype.newGroup = function (name, weight) {
-  return this.addUnit(new TrackerGroup(name), weight)
-}
-
-TrackerGroup.prototype.newItem = function (name, todo, weight) {
-  return this.addUnit(new Tracker(name, todo), weight)
-}
-
-TrackerGroup.prototype.newStream = function (name, todo, weight) {
-  return this.addUnit(new TrackerStream(name, todo), weight)
-}
-
-TrackerGroup.prototype.finish = function () {
-  this.finished = true
-  if (!this.trackers.length) {
-    this.addUnit(new Tracker(), 1, true)
-  }
-  for (var ii = 0; ii < this.trackers.length; ii++) {
-    var tracker = this.trackers[ii]
-    tracker.finish()
-    tracker.removeListener('change', this.bubbleChange)
-  }
-  this.emit('change', this.name, 1, this)
-}
-
-var buffer = '                                  '
-TrackerGroup.prototype.debug = function (depth) {
-  depth = depth || 0
-  var indent = depth ? buffer.slice(0, depth) : ''
-  var output = indent + (this.name || 'top') + ': ' + this.completed() + '\n'
-  this.trackers.forEach(function (tracker) {
-    if (tracker instanceof TrackerGroup) {
-      output += tracker.debug(depth + 1)
-    } else {
-      output += indent + ' ' + tracker.name + ': ' + tracker.completed() + '\n'
-    }
-  })
-  return output
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/are-we-there-yet/lib/tracker-stream.js b/deps/npm/node_modules/node-gyp/node_modules/are-we-there-yet/lib/tracker-stream.js
deleted file mode 100644
index e1cf85055702a7..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/are-we-there-yet/lib/tracker-stream.js
+++ /dev/null
@@ -1,36 +0,0 @@
-'use strict'
-var util = require('util')
-var stream = require('readable-stream')
-var delegate = require('delegates')
-var Tracker = require('./tracker.js')
-
-var TrackerStream = module.exports = function (name, size, options) {
-  stream.Transform.call(this, options)
-  this.tracker = new Tracker(name, size)
-  this.name = name
-  this.id = this.tracker.id
-  this.tracker.on('change', delegateChange(this))
-}
-util.inherits(TrackerStream, stream.Transform)
-
-function delegateChange (trackerStream) {
-  return function (name, completion, tracker) {
-    trackerStream.emit('change', name, completion, trackerStream)
-  }
-}
-
-TrackerStream.prototype._transform = function (data, encoding, cb) {
-  this.tracker.completeWork(data.length ? data.length : 1)
-  this.push(data)
-  cb()
-}
-
-TrackerStream.prototype._flush = function (cb) {
-  this.tracker.finish()
-  cb()
-}
-
-delegate(TrackerStream.prototype, 'tracker')
-  .method('completed')
-  .method('addWork')
-  .method('finish')
diff --git a/deps/npm/node_modules/node-gyp/node_modules/are-we-there-yet/lib/tracker.js b/deps/npm/node_modules/node-gyp/node_modules/are-we-there-yet/lib/tracker.js
deleted file mode 100644
index a8f8b3ba013915..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/are-we-there-yet/lib/tracker.js
+++ /dev/null
@@ -1,32 +0,0 @@
-'use strict'
-var util = require('util')
-var TrackerBase = require('./tracker-base.js')
-
-var Tracker = module.exports = function (name, todo) {
-  TrackerBase.call(this, name)
-  this.workDone = 0
-  this.workTodo = todo || 0
-}
-util.inherits(Tracker, TrackerBase)
-
-Tracker.prototype.completed = function () {
-  return this.workTodo === 0 ? 0 : this.workDone / this.workTodo
-}
-
-Tracker.prototype.addWork = function (work) {
-  this.workTodo += work
-  this.emit('change', this.name, this.completed(), this)
-}
-
-Tracker.prototype.completeWork = function (work) {
-  this.workDone += work
-  if (this.workDone > this.workTodo) {
-    this.workDone = this.workTodo
-  }
-  this.emit('change', this.name, this.completed(), this)
-}
-
-Tracker.prototype.finish = function () {
-  this.workTodo = this.workDone = 1
-  this.emit('change', this.name, 1, this)
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/are-we-there-yet/package.json b/deps/npm/node_modules/node-gyp/node_modules/are-we-there-yet/package.json
deleted file mode 100644
index cc3d7504299fa2..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/are-we-there-yet/package.json
+++ /dev/null
@@ -1,56 +0,0 @@
-{
-  "name": "are-we-there-yet",
-  "version": "3.0.1",
-  "description": "Keep track of the overall completion of many disparate processes",
-  "main": "lib/index.js",
-  "scripts": {
-    "test": "tap",
-    "npmclilint": "npmcli-lint",
-    "lint": "eslint \"**/*.js\"",
-    "lintfix": "npm run lint -- --fix",
-    "posttest": "npm run lint",
-    "postsnap": "npm run lintfix --",
-    "preversion": "npm test",
-    "postversion": "npm publish",
-    "prepublishOnly": "git push origin --follow-tags",
-    "snap": "tap",
-    "postlint": "template-oss-check",
-    "template-oss-apply": "template-oss-apply --force"
-  },
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/npm/are-we-there-yet.git"
-  },
-  "author": "GitHub Inc.",
-  "license": "ISC",
-  "bugs": {
-    "url": "https://github.com/npm/are-we-there-yet/issues"
-  },
-  "homepage": "https://github.com/npm/are-we-there-yet",
-  "devDependencies": {
-    "@npmcli/eslint-config": "^3.0.1",
-    "@npmcli/template-oss": "3.5.0",
-    "tap": "^16.0.1"
-  },
-  "dependencies": {
-    "delegates": "^1.0.0",
-    "readable-stream": "^3.6.0"
-  },
-  "files": [
-    "bin/",
-    "lib/"
-  ],
-  "engines": {
-    "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
-  },
-  "tap": {
-    "branches": 68,
-    "statements": 92,
-    "functions": 86,
-    "lines": 92
-  },
-  "templateOSS": {
-    "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
-    "version": "3.5.0"
-  }
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/brace-expansion/LICENSE b/deps/npm/node_modules/node-gyp/node_modules/brace-expansion/LICENSE
deleted file mode 100644
index de3226673c3874..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/brace-expansion/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2013 Julian Gruber 
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/deps/npm/node_modules/node-gyp/node_modules/brace-expansion/index.js b/deps/npm/node_modules/node-gyp/node_modules/brace-expansion/index.js
deleted file mode 100644
index 2b6f4f85c951fc..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/brace-expansion/index.js
+++ /dev/null
@@ -1,200 +0,0 @@
-var concatMap = require('concat-map');
-var balanced = require('balanced-match');
-
-module.exports = expandTop;
-
-var escSlash = '\0SLASH'+Math.random()+'\0';
-var escOpen = '\0OPEN'+Math.random()+'\0';
-var escClose = '\0CLOSE'+Math.random()+'\0';
-var escComma = '\0COMMA'+Math.random()+'\0';
-var escPeriod = '\0PERIOD'+Math.random()+'\0';
-
-function numeric(str) {
-  return parseInt(str, 10) == str
-    ? parseInt(str, 10)
-    : str.charCodeAt(0);
-}
-
-function escapeBraces(str) {
-  return str.split('\\\\').join(escSlash)
-            .split('\\{').join(escOpen)
-            .split('\\}').join(escClose)
-            .split('\\,').join(escComma)
-            .split('\\.').join(escPeriod);
-}
-
-function unescapeBraces(str) {
-  return str.split(escSlash).join('\\')
-            .split(escOpen).join('{')
-            .split(escClose).join('}')
-            .split(escComma).join(',')
-            .split(escPeriod).join('.');
-}
-
-
-// Basically just str.split(","), but handling cases
-// where we have nested braced sections, which should be
-// treated as individual members, like {a,{b,c},d}
-function parseCommaParts(str) {
-  if (!str)
-    return [''];
-
-  var parts = [];
-  var m = balanced('{', '}', str);
-
-  if (!m)
-    return str.split(',');
-
-  var pre = m.pre;
-  var body = m.body;
-  var post = m.post;
-  var p = pre.split(',');
-
-  p[p.length-1] += '{' + body + '}';
-  var postParts = parseCommaParts(post);
-  if (post.length) {
-    p[p.length-1] += postParts.shift();
-    p.push.apply(p, postParts);
-  }
-
-  parts.push.apply(parts, p);
-
-  return parts;
-}
-
-function expandTop(str) {
-  if (!str)
-    return [];
-
-  // I don't know why Bash 4.3 does this, but it does.
-  // Anything starting with {} will have the first two bytes preserved
-  // but *only* at the top level, so {},a}b will not expand to anything,
-  // but a{},b}c will be expanded to [a}c,abc].
-  // One could argue that this is a bug in Bash, but since the goal of
-  // this module is to match Bash's rules, we escape a leading {}
-  if (str.substr(0, 2) === '{}') {
-    str = '\\{\\}' + str.substr(2);
-  }
-
-  return expand(escapeBraces(str), true).map(unescapeBraces);
-}
-
-function identity(e) {
-  return e;
-}
-
-function embrace(str) {
-  return '{' + str + '}';
-}
-function isPadded(el) {
-  return /^-?0\d/.test(el);
-}
-
-function lte(i, y) {
-  return i <= y;
-}
-function gte(i, y) {
-  return i >= y;
-}
-
-function expand(str, isTop) {
-  var expansions = [];
-
-  var m = balanced('{', '}', str);
-  if (!m || /\$$/.test(m.pre)) return [str];
-
-  var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
-  var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
-  var isSequence = isNumericSequence || isAlphaSequence;
-  var isOptions = m.body.indexOf(',') >= 0;
-  if (!isSequence && !isOptions) {
-    // {a},b}
-    if (m.post.match(/,.*\}/)) {
-      str = m.pre + '{' + m.body + escClose + m.post;
-      return expand(str);
-    }
-    return [str];
-  }
-
-  var n;
-  if (isSequence) {
-    n = m.body.split(/\.\./);
-  } else {
-    n = parseCommaParts(m.body);
-    if (n.length === 1) {
-      // x{{a,b}}y ==> x{a}y x{b}y
-      n = expand(n[0], false).map(embrace);
-      if (n.length === 1) {
-        var post = m.post.length
-          ? expand(m.post, false)
-          : [''];
-        return post.map(function(p) {
-          return m.pre + n[0] + p;
-        });
-      }
-    }
-  }
-
-  // at this point, n is the parts, and we know it's not a comma set
-  // with a single entry.
-
-  // no need to expand pre, since it is guaranteed to be free of brace-sets
-  var pre = m.pre;
-  var post = m.post.length
-    ? expand(m.post, false)
-    : [''];
-
-  var N;
-
-  if (isSequence) {
-    var x = numeric(n[0]);
-    var y = numeric(n[1]);
-    var width = Math.max(n[0].length, n[1].length)
-    var incr = n.length == 3
-      ? Math.abs(numeric(n[2]))
-      : 1;
-    var test = lte;
-    var reverse = y < x;
-    if (reverse) {
-      incr *= -1;
-      test = gte;
-    }
-    var pad = n.some(isPadded);
-
-    N = [];
-
-    for (var i = x; test(i, y); i += incr) {
-      var c;
-      if (isAlphaSequence) {
-        c = String.fromCharCode(i);
-        if (c === '\\')
-          c = '';
-      } else {
-        c = String(i);
-        if (pad) {
-          var need = width - c.length;
-          if (need > 0) {
-            var z = new Array(need + 1).join('0');
-            if (i < 0)
-              c = '-' + z + c.slice(1);
-            else
-              c = z + c;
-          }
-        }
-      }
-      N.push(c);
-    }
-  } else {
-    N = concatMap(n, function(el) { return expand(el, false) });
-  }
-
-  for (var j = 0; j < N.length; j++) {
-    for (var k = 0; k < post.length; k++) {
-      var expansion = pre + N[j] + post[k];
-      if (!isTop || isSequence || expansion)
-        expansions.push(expansion);
-    }
-  }
-
-  return expansions;
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/brace-expansion/package.json b/deps/npm/node_modules/node-gyp/node_modules/brace-expansion/package.json
deleted file mode 100644
index a18faa8fd67b82..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/brace-expansion/package.json
+++ /dev/null
@@ -1,47 +0,0 @@
-{
-  "name": "brace-expansion",
-  "description": "Brace expansion as known from sh/bash",
-  "version": "1.1.11",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/juliangruber/brace-expansion.git"
-  },
-  "homepage": "https://github.com/juliangruber/brace-expansion",
-  "main": "index.js",
-  "scripts": {
-    "test": "tape test/*.js",
-    "gentest": "bash test/generate.sh",
-    "bench": "matcha test/perf/bench.js"
-  },
-  "dependencies": {
-    "balanced-match": "^1.0.0",
-    "concat-map": "0.0.1"
-  },
-  "devDependencies": {
-    "matcha": "^0.7.0",
-    "tape": "^4.6.0"
-  },
-  "keywords": [],
-  "author": {
-    "name": "Julian Gruber",
-    "email": "mail@juliangruber.com",
-    "url": "http://juliangruber.com"
-  },
-  "license": "MIT",
-  "testling": {
-    "files": "test/*.js",
-    "browsers": [
-      "ie/8..latest",
-      "firefox/20..latest",
-      "firefox/nightly",
-      "chrome/25..latest",
-      "chrome/canary",
-      "opera/12..latest",
-      "opera/next",
-      "safari/5.1..latest",
-      "ipad/6.0..latest",
-      "iphone/6.0..latest",
-      "android-browser/4.2..latest"
-    ]
-  }
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/gauge/LICENSE.md b/deps/npm/node_modules/node-gyp/node_modules/gauge/LICENSE.md
deleted file mode 100644
index 5fc208ff122e08..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/gauge/LICENSE.md
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-ISC License
-
-Copyright npm, Inc.
-
-Permission to use, copy, modify, and/or distribute this
-software for any purpose with or without fee is hereby
-granted, provided that the above copyright notice and this
-permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND NPM DISCLAIMS ALL
-WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
-EVENT SHALL NPM BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
-USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/base-theme.js b/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/base-theme.js
deleted file mode 100644
index 00bf5684cddab8..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/base-theme.js
+++ /dev/null
@@ -1,18 +0,0 @@
-'use strict'
-var spin = require('./spin.js')
-var progressBar = require('./progress-bar.js')
-
-module.exports = {
-  activityIndicator: function (values, theme, width) {
-    if (values.spun == null) {
-      return
-    }
-    return spin(theme, values.spun)
-  },
-  progressbar: function (values, theme, width) {
-    if (values.completed == null) {
-      return
-    }
-    return progressBar(theme, width, values.completed)
-  },
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/error.js b/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/error.js
deleted file mode 100644
index d9914ba5335d25..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/error.js
+++ /dev/null
@@ -1,24 +0,0 @@
-'use strict'
-var util = require('util')
-
-var User = exports.User = function User (msg) {
-  var err = new Error(msg)
-  Error.captureStackTrace(err, User)
-  err.code = 'EGAUGE'
-  return err
-}
-
-exports.MissingTemplateValue = function MissingTemplateValue (item, values) {
-  var err = new User(util.format('Missing template value "%s"', item.type))
-  Error.captureStackTrace(err, MissingTemplateValue)
-  err.template = item
-  err.values = values
-  return err
-}
-
-exports.Internal = function Internal (msg) {
-  var err = new Error(msg)
-  Error.captureStackTrace(err, Internal)
-  err.code = 'EGAUGEINTERNAL'
-  return err
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/has-color.js b/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/has-color.js
deleted file mode 100644
index 16cba0eb47d332..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/has-color.js
+++ /dev/null
@@ -1,4 +0,0 @@
-'use strict'
-var colorSupport = require('color-support')
-
-module.exports = colorSupport().hasBasic
diff --git a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/index.js b/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/index.js
deleted file mode 100644
index 37fc5ac60a16fd..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/index.js
+++ /dev/null
@@ -1,289 +0,0 @@
-'use strict'
-var Plumbing = require('./plumbing.js')
-var hasUnicode = require('has-unicode')
-var hasColor = require('./has-color.js')
-var onExit = require('signal-exit')
-var defaultThemes = require('./themes')
-var setInterval = require('./set-interval.js')
-var process = require('./process.js')
-var setImmediate = require('./set-immediate')
-
-module.exports = Gauge
-
-function callWith (obj, method) {
-  return function () {
-    return method.call(obj)
-  }
-}
-
-function Gauge (arg1, arg2) {
-  var options, writeTo
-  if (arg1 && arg1.write) {
-    writeTo = arg1
-    options = arg2 || {}
-  } else if (arg2 && arg2.write) {
-    writeTo = arg2
-    options = arg1 || {}
-  } else {
-    writeTo = process.stderr
-    options = arg1 || arg2 || {}
-  }
-
-  this._status = {
-    spun: 0,
-    section: '',
-    subsection: '',
-  }
-  this._paused = false // are we paused for back pressure?
-  this._disabled = true // are all progress bar updates disabled?
-  this._showing = false // do we WANT the progress bar on screen
-  this._onScreen = false // IS the progress bar on screen
-  this._needsRedraw = false // should we print something at next tick?
-  this._hideCursor = options.hideCursor == null ? true : options.hideCursor
-  this._fixedFramerate = options.fixedFramerate == null
-    ? !(/^v0\.8\./.test(process.version))
-    : options.fixedFramerate
-  this._lastUpdateAt = null
-  this._updateInterval = options.updateInterval == null ? 50 : options.updateInterval
-
-  this._themes = options.themes || defaultThemes
-  this._theme = options.theme
-  var theme = this._computeTheme(options.theme)
-  var template = options.template || [
-    { type: 'progressbar', length: 20 },
-    { type: 'activityIndicator', kerning: 1, length: 1 },
-    { type: 'section', kerning: 1, default: '' },
-    { type: 'subsection', kerning: 1, default: '' },
-  ]
-  this.setWriteTo(writeTo, options.tty)
-  var PlumbingClass = options.Plumbing || Plumbing
-  this._gauge = new PlumbingClass(theme, template, this.getWidth())
-
-  this._$$doRedraw = callWith(this, this._doRedraw)
-  this._$$handleSizeChange = callWith(this, this._handleSizeChange)
-
-  this._cleanupOnExit = options.cleanupOnExit == null || options.cleanupOnExit
-  this._removeOnExit = null
-
-  if (options.enabled || (options.enabled == null && this._tty && this._tty.isTTY)) {
-    this.enable()
-  } else {
-    this.disable()
-  }
-}
-Gauge.prototype = {}
-
-Gauge.prototype.isEnabled = function () {
-  return !this._disabled
-}
-
-Gauge.prototype.setTemplate = function (template) {
-  this._gauge.setTemplate(template)
-  if (this._showing) {
-    this._requestRedraw()
-  }
-}
-
-Gauge.prototype._computeTheme = function (theme) {
-  if (!theme) {
-    theme = {}
-  }
-  if (typeof theme === 'string') {
-    theme = this._themes.getTheme(theme)
-  } else if (
-    Object.keys(theme).length === 0 || theme.hasUnicode != null || theme.hasColor != null
-  ) {
-    var useUnicode = theme.hasUnicode == null ? hasUnicode() : theme.hasUnicode
-    var useColor = theme.hasColor == null ? hasColor : theme.hasColor
-    theme = this._themes.getDefault({
-      hasUnicode: useUnicode,
-      hasColor: useColor,
-      platform: theme.platform,
-    })
-  }
-  return theme
-}
-
-Gauge.prototype.setThemeset = function (themes) {
-  this._themes = themes
-  this.setTheme(this._theme)
-}
-
-Gauge.prototype.setTheme = function (theme) {
-  this._gauge.setTheme(this._computeTheme(theme))
-  if (this._showing) {
-    this._requestRedraw()
-  }
-  this._theme = theme
-}
-
-Gauge.prototype._requestRedraw = function () {
-  this._needsRedraw = true
-  if (!this._fixedFramerate) {
-    this._doRedraw()
-  }
-}
-
-Gauge.prototype.getWidth = function () {
-  return ((this._tty && this._tty.columns) || 80) - 1
-}
-
-Gauge.prototype.setWriteTo = function (writeTo, tty) {
-  var enabled = !this._disabled
-  if (enabled) {
-    this.disable()
-  }
-  this._writeTo = writeTo
-  this._tty = tty ||
-    (writeTo === process.stderr && process.stdout.isTTY && process.stdout) ||
-    (writeTo.isTTY && writeTo) ||
-    this._tty
-  if (this._gauge) {
-    this._gauge.setWidth(this.getWidth())
-  }
-  if (enabled) {
-    this.enable()
-  }
-}
-
-Gauge.prototype.enable = function () {
-  if (!this._disabled) {
-    return
-  }
-  this._disabled = false
-  if (this._tty) {
-    this._enableEvents()
-  }
-  if (this._showing) {
-    this.show()
-  }
-}
-
-Gauge.prototype.disable = function () {
-  if (this._disabled) {
-    return
-  }
-  if (this._showing) {
-    this._lastUpdateAt = null
-    this._showing = false
-    this._doRedraw()
-    this._showing = true
-  }
-  this._disabled = true
-  if (this._tty) {
-    this._disableEvents()
-  }
-}
-
-Gauge.prototype._enableEvents = function () {
-  if (this._cleanupOnExit) {
-    this._removeOnExit = onExit(callWith(this, this.disable))
-  }
-  this._tty.on('resize', this._$$handleSizeChange)
-  if (this._fixedFramerate) {
-    this.redrawTracker = setInterval(this._$$doRedraw, this._updateInterval)
-    if (this.redrawTracker.unref) {
-      this.redrawTracker.unref()
-    }
-  }
-}
-
-Gauge.prototype._disableEvents = function () {
-  this._tty.removeListener('resize', this._$$handleSizeChange)
-  if (this._fixedFramerate) {
-    clearInterval(this.redrawTracker)
-  }
-  if (this._removeOnExit) {
-    this._removeOnExit()
-  }
-}
-
-Gauge.prototype.hide = function (cb) {
-  if (this._disabled) {
-    return cb && process.nextTick(cb)
-  }
-  if (!this._showing) {
-    return cb && process.nextTick(cb)
-  }
-  this._showing = false
-  this._doRedraw()
-  cb && setImmediate(cb)
-}
-
-Gauge.prototype.show = function (section, completed) {
-  this._showing = true
-  if (typeof section === 'string') {
-    this._status.section = section
-  } else if (typeof section === 'object') {
-    var sectionKeys = Object.keys(section)
-    for (var ii = 0; ii < sectionKeys.length; ++ii) {
-      var key = sectionKeys[ii]
-      this._status[key] = section[key]
-    }
-  }
-  if (completed != null) {
-    this._status.completed = completed
-  }
-  if (this._disabled) {
-    return
-  }
-  this._requestRedraw()
-}
-
-Gauge.prototype.pulse = function (subsection) {
-  this._status.subsection = subsection || ''
-  this._status.spun++
-  if (this._disabled) {
-    return
-  }
-  if (!this._showing) {
-    return
-  }
-  this._requestRedraw()
-}
-
-Gauge.prototype._handleSizeChange = function () {
-  this._gauge.setWidth(this._tty.columns - 1)
-  this._requestRedraw()
-}
-
-Gauge.prototype._doRedraw = function () {
-  if (this._disabled || this._paused) {
-    return
-  }
-  if (!this._fixedFramerate) {
-    var now = Date.now()
-    if (this._lastUpdateAt && now - this._lastUpdateAt < this._updateInterval) {
-      return
-    }
-    this._lastUpdateAt = now
-  }
-  if (!this._showing && this._onScreen) {
-    this._onScreen = false
-    var result = this._gauge.hide()
-    if (this._hideCursor) {
-      result += this._gauge.showCursor()
-    }
-    return this._writeTo.write(result)
-  }
-  if (!this._showing && !this._onScreen) {
-    return
-  }
-  if (this._showing && !this._onScreen) {
-    this._onScreen = true
-    this._needsRedraw = true
-    if (this._hideCursor) {
-      this._writeTo.write(this._gauge.hideCursor())
-    }
-  }
-  if (!this._needsRedraw) {
-    return
-  }
-  if (!this._writeTo.write(this._gauge.show(this._status))) {
-    this._paused = true
-    this._writeTo.on('drain', callWith(this, function () {
-      this._paused = false
-      this._doRedraw()
-    }))
-  }
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/plumbing.js b/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/plumbing.js
deleted file mode 100644
index c4dc3e074b95e8..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/plumbing.js
+++ /dev/null
@@ -1,50 +0,0 @@
-'use strict'
-var consoleControl = require('console-control-strings')
-var renderTemplate = require('./render-template.js')
-var validate = require('aproba')
-
-var Plumbing = module.exports = function (theme, template, width) {
-  if (!width) {
-    width = 80
-  }
-  validate('OAN', [theme, template, width])
-  this.showing = false
-  this.theme = theme
-  this.width = width
-  this.template = template
-}
-Plumbing.prototype = {}
-
-Plumbing.prototype.setTheme = function (theme) {
-  validate('O', [theme])
-  this.theme = theme
-}
-
-Plumbing.prototype.setTemplate = function (template) {
-  validate('A', [template])
-  this.template = template
-}
-
-Plumbing.prototype.setWidth = function (width) {
-  validate('N', [width])
-  this.width = width
-}
-
-Plumbing.prototype.hide = function () {
-  return consoleControl.gotoSOL() + consoleControl.eraseLine()
-}
-
-Plumbing.prototype.hideCursor = consoleControl.hideCursor
-
-Plumbing.prototype.showCursor = consoleControl.showCursor
-
-Plumbing.prototype.show = function (status) {
-  var values = Object.create(this.theme)
-  for (var key in status) {
-    values[key] = status[key]
-  }
-
-  return renderTemplate(this.width, this.template, values).trim() +
-         consoleControl.color('reset') +
-         consoleControl.eraseLine() + consoleControl.gotoSOL()
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/process.js b/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/process.js
deleted file mode 100644
index 05e85694d755b6..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/process.js
+++ /dev/null
@@ -1,3 +0,0 @@
-'use strict'
-// this exists so we can replace it during testing
-module.exports = process
diff --git a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/progress-bar.js b/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/progress-bar.js
deleted file mode 100644
index 184ff2500aae4d..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/progress-bar.js
+++ /dev/null
@@ -1,41 +0,0 @@
-'use strict'
-var validate = require('aproba')
-var renderTemplate = require('./render-template.js')
-var wideTruncate = require('./wide-truncate')
-var stringWidth = require('string-width')
-
-module.exports = function (theme, width, completed) {
-  validate('ONN', [theme, width, completed])
-  if (completed < 0) {
-    completed = 0
-  }
-  if (completed > 1) {
-    completed = 1
-  }
-  if (width <= 0) {
-    return ''
-  }
-  var sofar = Math.round(width * completed)
-  var rest = width - sofar
-  var template = [
-    { type: 'complete', value: repeat(theme.complete, sofar), length: sofar },
-    { type: 'remaining', value: repeat(theme.remaining, rest), length: rest },
-  ]
-  return renderTemplate(width, template, theme)
-}
-
-// lodash's way of repeating
-function repeat (string, width) {
-  var result = ''
-  var n = width
-  do {
-    if (n % 2) {
-      result += string
-    }
-    n = Math.floor(n / 2)
-    /* eslint no-self-assign: 0 */
-    string += string
-  } while (n && stringWidth(result) < width)
-
-  return wideTruncate(result, width)
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/render-template.js b/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/render-template.js
deleted file mode 100644
index d1b52c0f48095a..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/render-template.js
+++ /dev/null
@@ -1,222 +0,0 @@
-'use strict'
-var align = require('wide-align')
-var validate = require('aproba')
-var wideTruncate = require('./wide-truncate')
-var error = require('./error')
-var TemplateItem = require('./template-item')
-
-function renderValueWithValues (values) {
-  return function (item) {
-    return renderValue(item, values)
-  }
-}
-
-var renderTemplate = module.exports = function (width, template, values) {
-  var items = prepareItems(width, template, values)
-  var rendered = items.map(renderValueWithValues(values)).join('')
-  return align.left(wideTruncate(rendered, width), width)
-}
-
-function preType (item) {
-  var cappedTypeName = item.type[0].toUpperCase() + item.type.slice(1)
-  return 'pre' + cappedTypeName
-}
-
-function postType (item) {
-  var cappedTypeName = item.type[0].toUpperCase() + item.type.slice(1)
-  return 'post' + cappedTypeName
-}
-
-function hasPreOrPost (item, values) {
-  if (!item.type) {
-    return
-  }
-  return values[preType(item)] || values[postType(item)]
-}
-
-function generatePreAndPost (baseItem, parentValues) {
-  var item = Object.assign({}, baseItem)
-  var values = Object.create(parentValues)
-  var template = []
-  var pre = preType(item)
-  var post = postType(item)
-  if (values[pre]) {
-    template.push({ value: values[pre] })
-    values[pre] = null
-  }
-  item.minLength = null
-  item.length = null
-  item.maxLength = null
-  template.push(item)
-  values[item.type] = values[item.type]
-  if (values[post]) {
-    template.push({ value: values[post] })
-    values[post] = null
-  }
-  return function ($1, $2, length) {
-    return renderTemplate(length, template, values)
-  }
-}
-
-function prepareItems (width, template, values) {
-  function cloneAndObjectify (item, index, arr) {
-    var cloned = new TemplateItem(item, width)
-    var type = cloned.type
-    if (cloned.value == null) {
-      if (!(type in values)) {
-        if (cloned.default == null) {
-          throw new error.MissingTemplateValue(cloned, values)
-        } else {
-          cloned.value = cloned.default
-        }
-      } else {
-        cloned.value = values[type]
-      }
-    }
-    if (cloned.value == null || cloned.value === '') {
-      return null
-    }
-    cloned.index = index
-    cloned.first = index === 0
-    cloned.last = index === arr.length - 1
-    if (hasPreOrPost(cloned, values)) {
-      cloned.value = generatePreAndPost(cloned, values)
-    }
-    return cloned
-  }
-
-  var output = template.map(cloneAndObjectify).filter(function (item) {
-    return item != null
-  })
-
-  var remainingSpace = width
-  var variableCount = output.length
-
-  function consumeSpace (length) {
-    if (length > remainingSpace) {
-      length = remainingSpace
-    }
-    remainingSpace -= length
-  }
-
-  function finishSizing (item, length) {
-    if (item.finished) {
-      throw new error.Internal('Tried to finish template item that was already finished')
-    }
-    if (length === Infinity) {
-      throw new error.Internal('Length of template item cannot be infinity')
-    }
-    if (length != null) {
-      item.length = length
-    }
-    item.minLength = null
-    item.maxLength = null
-    --variableCount
-    item.finished = true
-    if (item.length == null) {
-      item.length = item.getBaseLength()
-    }
-    if (item.length == null) {
-      throw new error.Internal('Finished template items must have a length')
-    }
-    consumeSpace(item.getLength())
-  }
-
-  output.forEach(function (item) {
-    if (!item.kerning) {
-      return
-    }
-    var prevPadRight = item.first ? 0 : output[item.index - 1].padRight
-    if (!item.first && prevPadRight < item.kerning) {
-      item.padLeft = item.kerning - prevPadRight
-    }
-    if (!item.last) {
-      item.padRight = item.kerning
-    }
-  })
-
-  // Finish any that have a fixed (literal or intuited) length
-  output.forEach(function (item) {
-    if (item.getBaseLength() == null) {
-      return
-    }
-    finishSizing(item)
-  })
-
-  var resized = 0
-  var resizing
-  var hunkSize
-  do {
-    resizing = false
-    hunkSize = Math.round(remainingSpace / variableCount)
-    output.forEach(function (item) {
-      if (item.finished) {
-        return
-      }
-      if (!item.maxLength) {
-        return
-      }
-      if (item.getMaxLength() < hunkSize) {
-        finishSizing(item, item.maxLength)
-        resizing = true
-      }
-    })
-  } while (resizing && resized++ < output.length)
-  if (resizing) {
-    throw new error.Internal('Resize loop iterated too many times while determining maxLength')
-  }
-
-  resized = 0
-  do {
-    resizing = false
-    hunkSize = Math.round(remainingSpace / variableCount)
-    output.forEach(function (item) {
-      if (item.finished) {
-        return
-      }
-      if (!item.minLength) {
-        return
-      }
-      if (item.getMinLength() >= hunkSize) {
-        finishSizing(item, item.minLength)
-        resizing = true
-      }
-    })
-  } while (resizing && resized++ < output.length)
-  if (resizing) {
-    throw new error.Internal('Resize loop iterated too many times while determining minLength')
-  }
-
-  hunkSize = Math.round(remainingSpace / variableCount)
-  output.forEach(function (item) {
-    if (item.finished) {
-      return
-    }
-    finishSizing(item, hunkSize)
-  })
-
-  return output
-}
-
-function renderFunction (item, values, length) {
-  validate('OON', arguments)
-  if (item.type) {
-    return item.value(values, values[item.type + 'Theme'] || {}, length)
-  } else {
-    return item.value(values, {}, length)
-  }
-}
-
-function renderValue (item, values) {
-  var length = item.getBaseLength()
-  var value = typeof item.value === 'function' ? renderFunction(item, values, length) : item.value
-  if (value == null || value === '') {
-    return ''
-  }
-  var alignWith = align[item.align] || align.left
-  var leftPadding = item.padLeft ? align.left('', item.padLeft) : ''
-  var rightPadding = item.padRight ? align.right('', item.padRight) : ''
-  var truncated = wideTruncate(String(value), length)
-  var aligned = alignWith(truncated, length)
-  return leftPadding + aligned + rightPadding
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/set-immediate.js b/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/set-immediate.js
deleted file mode 100644
index 6650a485c49933..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/set-immediate.js
+++ /dev/null
@@ -1,7 +0,0 @@
-'use strict'
-var process = require('./process')
-try {
-  module.exports = setImmediate
-} catch (ex) {
-  module.exports = process.nextTick
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/set-interval.js b/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/set-interval.js
deleted file mode 100644
index 576198793c5504..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/set-interval.js
+++ /dev/null
@@ -1,3 +0,0 @@
-'use strict'
-// this exists so we can replace it during testing
-module.exports = setInterval
diff --git a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/spin.js b/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/spin.js
deleted file mode 100644
index 34142ee31acc7c..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/spin.js
+++ /dev/null
@@ -1,5 +0,0 @@
-'use strict'
-
-module.exports = function spin (spinstr, spun) {
-  return spinstr[spun % spinstr.length]
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/template-item.js b/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/template-item.js
deleted file mode 100644
index e307e9b7421e73..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/template-item.js
+++ /dev/null
@@ -1,87 +0,0 @@
-'use strict'
-var stringWidth = require('string-width')
-
-module.exports = TemplateItem
-
-function isPercent (num) {
-  if (typeof num !== 'string') {
-    return false
-  }
-  return num.slice(-1) === '%'
-}
-
-function percent (num) {
-  return Number(num.slice(0, -1)) / 100
-}
-
-function TemplateItem (values, outputLength) {
-  this.overallOutputLength = outputLength
-  this.finished = false
-  this.type = null
-  this.value = null
-  this.length = null
-  this.maxLength = null
-  this.minLength = null
-  this.kerning = null
-  this.align = 'left'
-  this.padLeft = 0
-  this.padRight = 0
-  this.index = null
-  this.first = null
-  this.last = null
-  if (typeof values === 'string') {
-    this.value = values
-  } else {
-    for (var prop in values) {
-      this[prop] = values[prop]
-    }
-  }
-  // Realize percents
-  if (isPercent(this.length)) {
-    this.length = Math.round(this.overallOutputLength * percent(this.length))
-  }
-  if (isPercent(this.minLength)) {
-    this.minLength = Math.round(this.overallOutputLength * percent(this.minLength))
-  }
-  if (isPercent(this.maxLength)) {
-    this.maxLength = Math.round(this.overallOutputLength * percent(this.maxLength))
-  }
-  return this
-}
-
-TemplateItem.prototype = {}
-
-TemplateItem.prototype.getBaseLength = function () {
-  var length = this.length
-  if (
-    length == null &&
-    typeof this.value === 'string' &&
-    this.maxLength == null &&
-    this.minLength == null
-  ) {
-    length = stringWidth(this.value)
-  }
-  return length
-}
-
-TemplateItem.prototype.getLength = function () {
-  var length = this.getBaseLength()
-  if (length == null) {
-    return null
-  }
-  return length + this.padLeft + this.padRight
-}
-
-TemplateItem.prototype.getMaxLength = function () {
-  if (this.maxLength == null) {
-    return null
-  }
-  return this.maxLength + this.padLeft + this.padRight
-}
-
-TemplateItem.prototype.getMinLength = function () {
-  if (this.minLength == null) {
-    return null
-  }
-  return this.minLength + this.padLeft + this.padRight
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/theme-set.js b/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/theme-set.js
deleted file mode 100644
index 643d7dbb1da346..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/theme-set.js
+++ /dev/null
@@ -1,122 +0,0 @@
-'use strict'
-
-module.exports = function () {
-  return ThemeSetProto.newThemeSet()
-}
-
-var ThemeSetProto = {}
-
-ThemeSetProto.baseTheme = require('./base-theme.js')
-
-ThemeSetProto.newTheme = function (parent, theme) {
-  if (!theme) {
-    theme = parent
-    parent = this.baseTheme
-  }
-  return Object.assign({}, parent, theme)
-}
-
-ThemeSetProto.getThemeNames = function () {
-  return Object.keys(this.themes)
-}
-
-ThemeSetProto.addTheme = function (name, parent, theme) {
-  this.themes[name] = this.newTheme(parent, theme)
-}
-
-ThemeSetProto.addToAllThemes = function (theme) {
-  var themes = this.themes
-  Object.keys(themes).forEach(function (name) {
-    Object.assign(themes[name], theme)
-  })
-  Object.assign(this.baseTheme, theme)
-}
-
-ThemeSetProto.getTheme = function (name) {
-  if (!this.themes[name]) {
-    throw this.newMissingThemeError(name)
-  }
-  return this.themes[name]
-}
-
-ThemeSetProto.setDefault = function (opts, name) {
-  if (name == null) {
-    name = opts
-    opts = {}
-  }
-  var platform = opts.platform == null ? 'fallback' : opts.platform
-  var hasUnicode = !!opts.hasUnicode
-  var hasColor = !!opts.hasColor
-  if (!this.defaults[platform]) {
-    this.defaults[platform] = { true: {}, false: {} }
-  }
-  this.defaults[platform][hasUnicode][hasColor] = name
-}
-
-ThemeSetProto.getDefault = function (opts) {
-  if (!opts) {
-    opts = {}
-  }
-  var platformName = opts.platform || process.platform
-  var platform = this.defaults[platformName] || this.defaults.fallback
-  var hasUnicode = !!opts.hasUnicode
-  var hasColor = !!opts.hasColor
-  if (!platform) {
-    throw this.newMissingDefaultThemeError(platformName, hasUnicode, hasColor)
-  }
-  if (!platform[hasUnicode][hasColor]) {
-    if (hasUnicode && hasColor && platform[!hasUnicode][hasColor]) {
-      hasUnicode = false
-    } else if (hasUnicode && hasColor && platform[hasUnicode][!hasColor]) {
-      hasColor = false
-    } else if (hasUnicode && hasColor && platform[!hasUnicode][!hasColor]) {
-      hasUnicode = false
-      hasColor = false
-    } else if (hasUnicode && !hasColor && platform[!hasUnicode][hasColor]) {
-      hasUnicode = false
-    } else if (!hasUnicode && hasColor && platform[hasUnicode][!hasColor]) {
-      hasColor = false
-    } else if (platform === this.defaults.fallback) {
-      throw this.newMissingDefaultThemeError(platformName, hasUnicode, hasColor)
-    }
-  }
-  if (platform[hasUnicode][hasColor]) {
-    return this.getTheme(platform[hasUnicode][hasColor])
-  } else {
-    return this.getDefault(Object.assign({}, opts, { platform: 'fallback' }))
-  }
-}
-
-ThemeSetProto.newMissingThemeError = function newMissingThemeError (name) {
-  var err = new Error('Could not find a gauge theme named "' + name + '"')
-  Error.captureStackTrace.call(err, newMissingThemeError)
-  err.theme = name
-  err.code = 'EMISSINGTHEME'
-  return err
-}
-
-ThemeSetProto.newMissingDefaultThemeError =
-  function newMissingDefaultThemeError (platformName, hasUnicode, hasColor) {
-    var err = new Error(
-      'Could not find a gauge theme for your platform/unicode/color use combo:\n' +
-    '    platform = ' + platformName + '\n' +
-    '    hasUnicode = ' + hasUnicode + '\n' +
-    '    hasColor = ' + hasColor)
-    Error.captureStackTrace.call(err, newMissingDefaultThemeError)
-    err.platform = platformName
-    err.hasUnicode = hasUnicode
-    err.hasColor = hasColor
-    err.code = 'EMISSINGTHEME'
-    return err
-  }
-
-ThemeSetProto.newThemeSet = function () {
-  var themeset = function (opts) {
-    return themeset.getDefault(opts)
-  }
-  return Object.assign(themeset, ThemeSetProto, {
-    themes: Object.assign({}, this.themes),
-    baseTheme: Object.assign({}, this.baseTheme),
-    defaults: JSON.parse(JSON.stringify(this.defaults || {})),
-  })
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/themes.js b/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/themes.js
deleted file mode 100644
index d2e62bbccb3d82..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/themes.js
+++ /dev/null
@@ -1,56 +0,0 @@
-'use strict'
-var color = require('console-control-strings').color
-var ThemeSet = require('./theme-set.js')
-
-var themes = module.exports = new ThemeSet()
-
-themes.addTheme('ASCII', {
-  preProgressbar: '[',
-  postProgressbar: ']',
-  progressbarTheme: {
-    complete: '#',
-    remaining: '.',
-  },
-  activityIndicatorTheme: '-\\|/',
-  preSubsection: '>',
-})
-
-themes.addTheme('colorASCII', themes.getTheme('ASCII'), {
-  progressbarTheme: {
-    preComplete: color('bgBrightWhite', 'brightWhite'),
-    complete: '#',
-    postComplete: color('reset'),
-    preRemaining: color('bgBrightBlack', 'brightBlack'),
-    remaining: '.',
-    postRemaining: color('reset'),
-  },
-})
-
-themes.addTheme('brailleSpinner', {
-  preProgressbar: '(',
-  postProgressbar: ')',
-  progressbarTheme: {
-    complete: '#',
-    remaining: '⠂',
-  },
-  activityIndicatorTheme: '⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏',
-  preSubsection: '>',
-})
-
-themes.addTheme('colorBrailleSpinner', themes.getTheme('brailleSpinner'), {
-  progressbarTheme: {
-    preComplete: color('bgBrightWhite', 'brightWhite'),
-    complete: '#',
-    postComplete: color('reset'),
-    preRemaining: color('bgBrightBlack', 'brightBlack'),
-    remaining: '⠂',
-    postRemaining: color('reset'),
-  },
-})
-
-themes.setDefault({}, 'ASCII')
-themes.setDefault({ hasColor: true }, 'colorASCII')
-themes.setDefault({ platform: 'darwin', hasUnicode: true }, 'brailleSpinner')
-themes.setDefault({ platform: 'darwin', hasUnicode: true, hasColor: true }, 'colorBrailleSpinner')
-themes.setDefault({ platform: 'linux', hasUnicode: true }, 'brailleSpinner')
-themes.setDefault({ platform: 'linux', hasUnicode: true, hasColor: true }, 'colorBrailleSpinner')
diff --git a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/wide-truncate.js b/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/wide-truncate.js
deleted file mode 100644
index 5284a699ac3fb5..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/gauge/lib/wide-truncate.js
+++ /dev/null
@@ -1,31 +0,0 @@
-'use strict'
-var stringWidth = require('string-width')
-var stripAnsi = require('strip-ansi')
-
-module.exports = wideTruncate
-
-function wideTruncate (str, target) {
-  if (stringWidth(str) === 0) {
-    return str
-  }
-  if (target <= 0) {
-    return ''
-  }
-  if (stringWidth(str) <= target) {
-    return str
-  }
-
-  // We compute the number of bytes of ansi sequences here and add
-  // that to our initial truncation to ensure that we don't slice one
-  // that we want to keep in half.
-  var noAnsi = stripAnsi(str)
-  var ansiSize = str.length + noAnsi.length
-  var truncated = str.slice(0, target + ansiSize)
-
-  // we have to shrink the result to account for our ansi sequence buffer
-  // (if an ansi sequence was truncated) and double width characters.
-  while (stringWidth(truncated) > target) {
-    truncated = truncated.slice(0, -1)
-  }
-  return truncated
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/gauge/package.json b/deps/npm/node_modules/node-gyp/node_modules/gauge/package.json
deleted file mode 100644
index bce3e68a33f699..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/gauge/package.json
+++ /dev/null
@@ -1,66 +0,0 @@
-{
-  "name": "gauge",
-  "version": "4.0.4",
-  "description": "A terminal based horizontal gauge",
-  "main": "lib",
-  "scripts": {
-    "test": "tap",
-    "lint": "eslint \"**/*.js\"",
-    "postlint": "template-oss-check",
-    "lintfix": "npm run lint -- --fix",
-    "preversion": "npm test",
-    "postversion": "npm publish",
-    "prepublishOnly": "git push origin --follow-tags",
-    "snap": "tap",
-    "posttest": "npm run lint",
-    "template-oss-apply": "template-oss-apply --force"
-  },
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/npm/gauge.git"
-  },
-  "keywords": [
-    "progressbar",
-    "progress",
-    "gauge"
-  ],
-  "author": "GitHub Inc.",
-  "license": "ISC",
-  "bugs": {
-    "url": "https://github.com/npm/gauge/issues"
-  },
-  "homepage": "https://github.com/npm/gauge",
-  "dependencies": {
-    "aproba": "^1.0.3 || ^2.0.0",
-    "color-support": "^1.1.3",
-    "console-control-strings": "^1.1.0",
-    "has-unicode": "^2.0.1",
-    "signal-exit": "^3.0.7",
-    "string-width": "^4.2.3",
-    "strip-ansi": "^6.0.1",
-    "wide-align": "^1.1.5"
-  },
-  "devDependencies": {
-    "@npmcli/eslint-config": "^3.0.1",
-    "@npmcli/template-oss": "3.2.0",
-    "readable-stream": "^3.6.0",
-    "tap": "^16.0.1"
-  },
-  "files": [
-    "bin/",
-    "lib/"
-  ],
-  "engines": {
-    "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
-  },
-  "tap": {
-    "branches": 79,
-    "statements": 89,
-    "functions": 92,
-    "lines": 90
-  },
-  "templateOSS": {
-    "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
-    "version": "3.2.0"
-  }
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/glob/LICENSE b/deps/npm/node_modules/node-gyp/node_modules/glob/LICENSE
deleted file mode 100644
index 42ca266df1d523..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/glob/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The ISC License
-
-Copyright (c) Isaac Z. Schlueter and Contributors
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-## Glob Logo
-
-Glob's logo created by Tanya Brassie , licensed
-under a Creative Commons Attribution-ShareAlike 4.0 International License
-https://creativecommons.org/licenses/by-sa/4.0/
diff --git a/deps/npm/node_modules/node-gyp/node_modules/glob/common.js b/deps/npm/node_modules/node-gyp/node_modules/glob/common.js
deleted file mode 100644
index 424c46e1dab1be..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/glob/common.js
+++ /dev/null
@@ -1,238 +0,0 @@
-exports.setopts = setopts
-exports.ownProp = ownProp
-exports.makeAbs = makeAbs
-exports.finish = finish
-exports.mark = mark
-exports.isIgnored = isIgnored
-exports.childrenIgnored = childrenIgnored
-
-function ownProp (obj, field) {
-  return Object.prototype.hasOwnProperty.call(obj, field)
-}
-
-var fs = require("fs")
-var path = require("path")
-var minimatch = require("minimatch")
-var isAbsolute = require("path-is-absolute")
-var Minimatch = minimatch.Minimatch
-
-function alphasort (a, b) {
-  return a.localeCompare(b, 'en')
-}
-
-function setupIgnores (self, options) {
-  self.ignore = options.ignore || []
-
-  if (!Array.isArray(self.ignore))
-    self.ignore = [self.ignore]
-
-  if (self.ignore.length) {
-    self.ignore = self.ignore.map(ignoreMap)
-  }
-}
-
-// ignore patterns are always in dot:true mode.
-function ignoreMap (pattern) {
-  var gmatcher = null
-  if (pattern.slice(-3) === '/**') {
-    var gpattern = pattern.replace(/(\/\*\*)+$/, '')
-    gmatcher = new Minimatch(gpattern, { dot: true })
-  }
-
-  return {
-    matcher: new Minimatch(pattern, { dot: true }),
-    gmatcher: gmatcher
-  }
-}
-
-function setopts (self, pattern, options) {
-  if (!options)
-    options = {}
-
-  // base-matching: just use globstar for that.
-  if (options.matchBase && -1 === pattern.indexOf("/")) {
-    if (options.noglobstar) {
-      throw new Error("base matching requires globstar")
-    }
-    pattern = "**/" + pattern
-  }
-
-  self.silent = !!options.silent
-  self.pattern = pattern
-  self.strict = options.strict !== false
-  self.realpath = !!options.realpath
-  self.realpathCache = options.realpathCache || Object.create(null)
-  self.follow = !!options.follow
-  self.dot = !!options.dot
-  self.mark = !!options.mark
-  self.nodir = !!options.nodir
-  if (self.nodir)
-    self.mark = true
-  self.sync = !!options.sync
-  self.nounique = !!options.nounique
-  self.nonull = !!options.nonull
-  self.nosort = !!options.nosort
-  self.nocase = !!options.nocase
-  self.stat = !!options.stat
-  self.noprocess = !!options.noprocess
-  self.absolute = !!options.absolute
-  self.fs = options.fs || fs
-
-  self.maxLength = options.maxLength || Infinity
-  self.cache = options.cache || Object.create(null)
-  self.statCache = options.statCache || Object.create(null)
-  self.symlinks = options.symlinks || Object.create(null)
-
-  setupIgnores(self, options)
-
-  self.changedCwd = false
-  var cwd = process.cwd()
-  if (!ownProp(options, "cwd"))
-    self.cwd = cwd
-  else {
-    self.cwd = path.resolve(options.cwd)
-    self.changedCwd = self.cwd !== cwd
-  }
-
-  self.root = options.root || path.resolve(self.cwd, "/")
-  self.root = path.resolve(self.root)
-  if (process.platform === "win32")
-    self.root = self.root.replace(/\\/g, "/")
-
-  // TODO: is an absolute `cwd` supposed to be resolved against `root`?
-  // e.g. { cwd: '/test', root: __dirname } === path.join(__dirname, '/test')
-  self.cwdAbs = isAbsolute(self.cwd) ? self.cwd : makeAbs(self, self.cwd)
-  if (process.platform === "win32")
-    self.cwdAbs = self.cwdAbs.replace(/\\/g, "/")
-  self.nomount = !!options.nomount
-
-  // disable comments and negation in Minimatch.
-  // Note that they are not supported in Glob itself anyway.
-  options.nonegate = true
-  options.nocomment = true
-  // always treat \ in patterns as escapes, not path separators
-  options.allowWindowsEscape = false
-
-  self.minimatch = new Minimatch(pattern, options)
-  self.options = self.minimatch.options
-}
-
-function finish (self) {
-  var nou = self.nounique
-  var all = nou ? [] : Object.create(null)
-
-  for (var i = 0, l = self.matches.length; i < l; i ++) {
-    var matches = self.matches[i]
-    if (!matches || Object.keys(matches).length === 0) {
-      if (self.nonull) {
-        // do like the shell, and spit out the literal glob
-        var literal = self.minimatch.globSet[i]
-        if (nou)
-          all.push(literal)
-        else
-          all[literal] = true
-      }
-    } else {
-      // had matches
-      var m = Object.keys(matches)
-      if (nou)
-        all.push.apply(all, m)
-      else
-        m.forEach(function (m) {
-          all[m] = true
-        })
-    }
-  }
-
-  if (!nou)
-    all = Object.keys(all)
-
-  if (!self.nosort)
-    all = all.sort(alphasort)
-
-  // at *some* point we statted all of these
-  if (self.mark) {
-    for (var i = 0; i < all.length; i++) {
-      all[i] = self._mark(all[i])
-    }
-    if (self.nodir) {
-      all = all.filter(function (e) {
-        var notDir = !(/\/$/.test(e))
-        var c = self.cache[e] || self.cache[makeAbs(self, e)]
-        if (notDir && c)
-          notDir = c !== 'DIR' && !Array.isArray(c)
-        return notDir
-      })
-    }
-  }
-
-  if (self.ignore.length)
-    all = all.filter(function(m) {
-      return !isIgnored(self, m)
-    })
-
-  self.found = all
-}
-
-function mark (self, p) {
-  var abs = makeAbs(self, p)
-  var c = self.cache[abs]
-  var m = p
-  if (c) {
-    var isDir = c === 'DIR' || Array.isArray(c)
-    var slash = p.slice(-1) === '/'
-
-    if (isDir && !slash)
-      m += '/'
-    else if (!isDir && slash)
-      m = m.slice(0, -1)
-
-    if (m !== p) {
-      var mabs = makeAbs(self, m)
-      self.statCache[mabs] = self.statCache[abs]
-      self.cache[mabs] = self.cache[abs]
-    }
-  }
-
-  return m
-}
-
-// lotta situps...
-function makeAbs (self, f) {
-  var abs = f
-  if (f.charAt(0) === '/') {
-    abs = path.join(self.root, f)
-  } else if (isAbsolute(f) || f === '') {
-    abs = f
-  } else if (self.changedCwd) {
-    abs = path.resolve(self.cwd, f)
-  } else {
-    abs = path.resolve(f)
-  }
-
-  if (process.platform === 'win32')
-    abs = abs.replace(/\\/g, '/')
-
-  return abs
-}
-
-
-// Return true, if pattern ends with globstar '**', for the accompanying parent directory.
-// Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents
-function isIgnored (self, path) {
-  if (!self.ignore.length)
-    return false
-
-  return self.ignore.some(function(item) {
-    return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path))
-  })
-}
-
-function childrenIgnored (self, path) {
-  if (!self.ignore.length)
-    return false
-
-  return self.ignore.some(function(item) {
-    return !!(item.gmatcher && item.gmatcher.match(path))
-  })
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/glob/glob.js b/deps/npm/node_modules/node-gyp/node_modules/glob/glob.js
deleted file mode 100644
index 37a4d7e60775a3..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/glob/glob.js
+++ /dev/null
@@ -1,790 +0,0 @@
-// Approach:
-//
-// 1. Get the minimatch set
-// 2. For each pattern in the set, PROCESS(pattern, false)
-// 3. Store matches per-set, then uniq them
-//
-// PROCESS(pattern, inGlobStar)
-// Get the first [n] items from pattern that are all strings
-// Join these together.  This is PREFIX.
-//   If there is no more remaining, then stat(PREFIX) and
-//   add to matches if it succeeds.  END.
-//
-// If inGlobStar and PREFIX is symlink and points to dir
-//   set ENTRIES = []
-// else readdir(PREFIX) as ENTRIES
-//   If fail, END
-//
-// with ENTRIES
-//   If pattern[n] is GLOBSTAR
-//     // handle the case where the globstar match is empty
-//     // by pruning it out, and testing the resulting pattern
-//     PROCESS(pattern[0..n] + pattern[n+1 .. $], false)
-//     // handle other cases.
-//     for ENTRY in ENTRIES (not dotfiles)
-//       // attach globstar + tail onto the entry
-//       // Mark that this entry is a globstar match
-//       PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true)
-//
-//   else // not globstar
-//     for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot)
-//       Test ENTRY against pattern[n]
-//       If fails, continue
-//       If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $])
-//
-// Caveat:
-//   Cache all stats and readdirs results to minimize syscall.  Since all
-//   we ever care about is existence and directory-ness, we can just keep
-//   `true` for files, and [children,...] for directories, or `false` for
-//   things that don't exist.
-
-module.exports = glob
-
-var rp = require('fs.realpath')
-var minimatch = require('minimatch')
-var Minimatch = minimatch.Minimatch
-var inherits = require('inherits')
-var EE = require('events').EventEmitter
-var path = require('path')
-var assert = require('assert')
-var isAbsolute = require('path-is-absolute')
-var globSync = require('./sync.js')
-var common = require('./common.js')
-var setopts = common.setopts
-var ownProp = common.ownProp
-var inflight = require('inflight')
-var util = require('util')
-var childrenIgnored = common.childrenIgnored
-var isIgnored = common.isIgnored
-
-var once = require('once')
-
-function glob (pattern, options, cb) {
-  if (typeof options === 'function') cb = options, options = {}
-  if (!options) options = {}
-
-  if (options.sync) {
-    if (cb)
-      throw new TypeError('callback provided to sync glob')
-    return globSync(pattern, options)
-  }
-
-  return new Glob(pattern, options, cb)
-}
-
-glob.sync = globSync
-var GlobSync = glob.GlobSync = globSync.GlobSync
-
-// old api surface
-glob.glob = glob
-
-function extend (origin, add) {
-  if (add === null || typeof add !== 'object') {
-    return origin
-  }
-
-  var keys = Object.keys(add)
-  var i = keys.length
-  while (i--) {
-    origin[keys[i]] = add[keys[i]]
-  }
-  return origin
-}
-
-glob.hasMagic = function (pattern, options_) {
-  var options = extend({}, options_)
-  options.noprocess = true
-
-  var g = new Glob(pattern, options)
-  var set = g.minimatch.set
-
-  if (!pattern)
-    return false
-
-  if (set.length > 1)
-    return true
-
-  for (var j = 0; j < set[0].length; j++) {
-    if (typeof set[0][j] !== 'string')
-      return true
-  }
-
-  return false
-}
-
-glob.Glob = Glob
-inherits(Glob, EE)
-function Glob (pattern, options, cb) {
-  if (typeof options === 'function') {
-    cb = options
-    options = null
-  }
-
-  if (options && options.sync) {
-    if (cb)
-      throw new TypeError('callback provided to sync glob')
-    return new GlobSync(pattern, options)
-  }
-
-  if (!(this instanceof Glob))
-    return new Glob(pattern, options, cb)
-
-  setopts(this, pattern, options)
-  this._didRealPath = false
-
-  // process each pattern in the minimatch set
-  var n = this.minimatch.set.length
-
-  // The matches are stored as {: true,...} so that
-  // duplicates are automagically pruned.
-  // Later, we do an Object.keys() on these.
-  // Keep them as a list so we can fill in when nonull is set.
-  this.matches = new Array(n)
-
-  if (typeof cb === 'function') {
-    cb = once(cb)
-    this.on('error', cb)
-    this.on('end', function (matches) {
-      cb(null, matches)
-    })
-  }
-
-  var self = this
-  this._processing = 0
-
-  this._emitQueue = []
-  this._processQueue = []
-  this.paused = false
-
-  if (this.noprocess)
-    return this
-
-  if (n === 0)
-    return done()
-
-  var sync = true
-  for (var i = 0; i < n; i ++) {
-    this._process(this.minimatch.set[i], i, false, done)
-  }
-  sync = false
-
-  function done () {
-    --self._processing
-    if (self._processing <= 0) {
-      if (sync) {
-        process.nextTick(function () {
-          self._finish()
-        })
-      } else {
-        self._finish()
-      }
-    }
-  }
-}
-
-Glob.prototype._finish = function () {
-  assert(this instanceof Glob)
-  if (this.aborted)
-    return
-
-  if (this.realpath && !this._didRealpath)
-    return this._realpath()
-
-  common.finish(this)
-  this.emit('end', this.found)
-}
-
-Glob.prototype._realpath = function () {
-  if (this._didRealpath)
-    return
-
-  this._didRealpath = true
-
-  var n = this.matches.length
-  if (n === 0)
-    return this._finish()
-
-  var self = this
-  for (var i = 0; i < this.matches.length; i++)
-    this._realpathSet(i, next)
-
-  function next () {
-    if (--n === 0)
-      self._finish()
-  }
-}
-
-Glob.prototype._realpathSet = function (index, cb) {
-  var matchset = this.matches[index]
-  if (!matchset)
-    return cb()
-
-  var found = Object.keys(matchset)
-  var self = this
-  var n = found.length
-
-  if (n === 0)
-    return cb()
-
-  var set = this.matches[index] = Object.create(null)
-  found.forEach(function (p, i) {
-    // If there's a problem with the stat, then it means that
-    // one or more of the links in the realpath couldn't be
-    // resolved.  just return the abs value in that case.
-    p = self._makeAbs(p)
-    rp.realpath(p, self.realpathCache, function (er, real) {
-      if (!er)
-        set[real] = true
-      else if (er.syscall === 'stat')
-        set[p] = true
-      else
-        self.emit('error', er) // srsly wtf right here
-
-      if (--n === 0) {
-        self.matches[index] = set
-        cb()
-      }
-    })
-  })
-}
-
-Glob.prototype._mark = function (p) {
-  return common.mark(this, p)
-}
-
-Glob.prototype._makeAbs = function (f) {
-  return common.makeAbs(this, f)
-}
-
-Glob.prototype.abort = function () {
-  this.aborted = true
-  this.emit('abort')
-}
-
-Glob.prototype.pause = function () {
-  if (!this.paused) {
-    this.paused = true
-    this.emit('pause')
-  }
-}
-
-Glob.prototype.resume = function () {
-  if (this.paused) {
-    this.emit('resume')
-    this.paused = false
-    if (this._emitQueue.length) {
-      var eq = this._emitQueue.slice(0)
-      this._emitQueue.length = 0
-      for (var i = 0; i < eq.length; i ++) {
-        var e = eq[i]
-        this._emitMatch(e[0], e[1])
-      }
-    }
-    if (this._processQueue.length) {
-      var pq = this._processQueue.slice(0)
-      this._processQueue.length = 0
-      for (var i = 0; i < pq.length; i ++) {
-        var p = pq[i]
-        this._processing--
-        this._process(p[0], p[1], p[2], p[3])
-      }
-    }
-  }
-}
-
-Glob.prototype._process = function (pattern, index, inGlobStar, cb) {
-  assert(this instanceof Glob)
-  assert(typeof cb === 'function')
-
-  if (this.aborted)
-    return
-
-  this._processing++
-  if (this.paused) {
-    this._processQueue.push([pattern, index, inGlobStar, cb])
-    return
-  }
-
-  //console.error('PROCESS %d', this._processing, pattern)
-
-  // Get the first [n] parts of pattern that are all strings.
-  var n = 0
-  while (typeof pattern[n] === 'string') {
-    n ++
-  }
-  // now n is the index of the first one that is *not* a string.
-
-  // see if there's anything else
-  var prefix
-  switch (n) {
-    // if not, then this is rather simple
-    case pattern.length:
-      this._processSimple(pattern.join('/'), index, cb)
-      return
-
-    case 0:
-      // pattern *starts* with some non-trivial item.
-      // going to readdir(cwd), but not include the prefix in matches.
-      prefix = null
-      break
-
-    default:
-      // pattern has some string bits in the front.
-      // whatever it starts with, whether that's 'absolute' like /foo/bar,
-      // or 'relative' like '../baz'
-      prefix = pattern.slice(0, n).join('/')
-      break
-  }
-
-  var remain = pattern.slice(n)
-
-  // get the list of entries.
-  var read
-  if (prefix === null)
-    read = '.'
-  else if (isAbsolute(prefix) ||
-      isAbsolute(pattern.map(function (p) {
-        return typeof p === 'string' ? p : '[*]'
-      }).join('/'))) {
-    if (!prefix || !isAbsolute(prefix))
-      prefix = '/' + prefix
-    read = prefix
-  } else
-    read = prefix
-
-  var abs = this._makeAbs(read)
-
-  //if ignored, skip _processing
-  if (childrenIgnored(this, read))
-    return cb()
-
-  var isGlobStar = remain[0] === minimatch.GLOBSTAR
-  if (isGlobStar)
-    this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb)
-  else
-    this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb)
-}
-
-Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) {
-  var self = this
-  this._readdir(abs, inGlobStar, function (er, entries) {
-    return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
-  })
-}
-
-Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
-
-  // if the abs isn't a dir, then nothing can match!
-  if (!entries)
-    return cb()
-
-  // It will only match dot entries if it starts with a dot, or if
-  // dot is set.  Stuff like @(.foo|.bar) isn't allowed.
-  var pn = remain[0]
-  var negate = !!this.minimatch.negate
-  var rawGlob = pn._glob
-  var dotOk = this.dot || rawGlob.charAt(0) === '.'
-
-  var matchedEntries = []
-  for (var i = 0; i < entries.length; i++) {
-    var e = entries[i]
-    if (e.charAt(0) !== '.' || dotOk) {
-      var m
-      if (negate && !prefix) {
-        m = !e.match(pn)
-      } else {
-        m = e.match(pn)
-      }
-      if (m)
-        matchedEntries.push(e)
-    }
-  }
-
-  //console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries)
-
-  var len = matchedEntries.length
-  // If there are no matched entries, then nothing matches.
-  if (len === 0)
-    return cb()
-
-  // if this is the last remaining pattern bit, then no need for
-  // an additional stat *unless* the user has specified mark or
-  // stat explicitly.  We know they exist, since readdir returned
-  // them.
-
-  if (remain.length === 1 && !this.mark && !this.stat) {
-    if (!this.matches[index])
-      this.matches[index] = Object.create(null)
-
-    for (var i = 0; i < len; i ++) {
-      var e = matchedEntries[i]
-      if (prefix) {
-        if (prefix !== '/')
-          e = prefix + '/' + e
-        else
-          e = prefix + e
-      }
-
-      if (e.charAt(0) === '/' && !this.nomount) {
-        e = path.join(this.root, e)
-      }
-      this._emitMatch(index, e)
-    }
-    // This was the last one, and no stats were needed
-    return cb()
-  }
-
-  // now test all matched entries as stand-ins for that part
-  // of the pattern.
-  remain.shift()
-  for (var i = 0; i < len; i ++) {
-    var e = matchedEntries[i]
-    var newPattern
-    if (prefix) {
-      if (prefix !== '/')
-        e = prefix + '/' + e
-      else
-        e = prefix + e
-    }
-    this._process([e].concat(remain), index, inGlobStar, cb)
-  }
-  cb()
-}
-
-Glob.prototype._emitMatch = function (index, e) {
-  if (this.aborted)
-    return
-
-  if (isIgnored(this, e))
-    return
-
-  if (this.paused) {
-    this._emitQueue.push([index, e])
-    return
-  }
-
-  var abs = isAbsolute(e) ? e : this._makeAbs(e)
-
-  if (this.mark)
-    e = this._mark(e)
-
-  if (this.absolute)
-    e = abs
-
-  if (this.matches[index][e])
-    return
-
-  if (this.nodir) {
-    var c = this.cache[abs]
-    if (c === 'DIR' || Array.isArray(c))
-      return
-  }
-
-  this.matches[index][e] = true
-
-  var st = this.statCache[abs]
-  if (st)
-    this.emit('stat', e, st)
-
-  this.emit('match', e)
-}
-
-Glob.prototype._readdirInGlobStar = function (abs, cb) {
-  if (this.aborted)
-    return
-
-  // follow all symlinked directories forever
-  // just proceed as if this is a non-globstar situation
-  if (this.follow)
-    return this._readdir(abs, false, cb)
-
-  var lstatkey = 'lstat\0' + abs
-  var self = this
-  var lstatcb = inflight(lstatkey, lstatcb_)
-
-  if (lstatcb)
-    self.fs.lstat(abs, lstatcb)
-
-  function lstatcb_ (er, lstat) {
-    if (er && er.code === 'ENOENT')
-      return cb()
-
-    var isSym = lstat && lstat.isSymbolicLink()
-    self.symlinks[abs] = isSym
-
-    // If it's not a symlink or a dir, then it's definitely a regular file.
-    // don't bother doing a readdir in that case.
-    if (!isSym && lstat && !lstat.isDirectory()) {
-      self.cache[abs] = 'FILE'
-      cb()
-    } else
-      self._readdir(abs, false, cb)
-  }
-}
-
-Glob.prototype._readdir = function (abs, inGlobStar, cb) {
-  if (this.aborted)
-    return
-
-  cb = inflight('readdir\0'+abs+'\0'+inGlobStar, cb)
-  if (!cb)
-    return
-
-  //console.error('RD %j %j', +inGlobStar, abs)
-  if (inGlobStar && !ownProp(this.symlinks, abs))
-    return this._readdirInGlobStar(abs, cb)
-
-  if (ownProp(this.cache, abs)) {
-    var c = this.cache[abs]
-    if (!c || c === 'FILE')
-      return cb()
-
-    if (Array.isArray(c))
-      return cb(null, c)
-  }
-
-  var self = this
-  self.fs.readdir(abs, readdirCb(this, abs, cb))
-}
-
-function readdirCb (self, abs, cb) {
-  return function (er, entries) {
-    if (er)
-      self._readdirError(abs, er, cb)
-    else
-      self._readdirEntries(abs, entries, cb)
-  }
-}
-
-Glob.prototype._readdirEntries = function (abs, entries, cb) {
-  if (this.aborted)
-    return
-
-  // if we haven't asked to stat everything, then just
-  // assume that everything in there exists, so we can avoid
-  // having to stat it a second time.
-  if (!this.mark && !this.stat) {
-    for (var i = 0; i < entries.length; i ++) {
-      var e = entries[i]
-      if (abs === '/')
-        e = abs + e
-      else
-        e = abs + '/' + e
-      this.cache[e] = true
-    }
-  }
-
-  this.cache[abs] = entries
-  return cb(null, entries)
-}
-
-Glob.prototype._readdirError = function (f, er, cb) {
-  if (this.aborted)
-    return
-
-  // handle errors, and cache the information
-  switch (er.code) {
-    case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205
-    case 'ENOTDIR': // totally normal. means it *does* exist.
-      var abs = this._makeAbs(f)
-      this.cache[abs] = 'FILE'
-      if (abs === this.cwdAbs) {
-        var error = new Error(er.code + ' invalid cwd ' + this.cwd)
-        error.path = this.cwd
-        error.code = er.code
-        this.emit('error', error)
-        this.abort()
-      }
-      break
-
-    case 'ENOENT': // not terribly unusual
-    case 'ELOOP':
-    case 'ENAMETOOLONG':
-    case 'UNKNOWN':
-      this.cache[this._makeAbs(f)] = false
-      break
-
-    default: // some unusual error.  Treat as failure.
-      this.cache[this._makeAbs(f)] = false
-      if (this.strict) {
-        this.emit('error', er)
-        // If the error is handled, then we abort
-        // if not, we threw out of here
-        this.abort()
-      }
-      if (!this.silent)
-        console.error('glob error', er)
-      break
-  }
-
-  return cb()
-}
-
-Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) {
-  var self = this
-  this._readdir(abs, inGlobStar, function (er, entries) {
-    self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
-  })
-}
-
-
-Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
-  //console.error('pgs2', prefix, remain[0], entries)
-
-  // no entries means not a dir, so it can never have matches
-  // foo.txt/** doesn't match foo.txt
-  if (!entries)
-    return cb()
-
-  // test without the globstar, and with every child both below
-  // and replacing the globstar.
-  var remainWithoutGlobStar = remain.slice(1)
-  var gspref = prefix ? [ prefix ] : []
-  var noGlobStar = gspref.concat(remainWithoutGlobStar)
-
-  // the noGlobStar pattern exits the inGlobStar state
-  this._process(noGlobStar, index, false, cb)
-
-  var isSym = this.symlinks[abs]
-  var len = entries.length
-
-  // If it's a symlink, and we're in a globstar, then stop
-  if (isSym && inGlobStar)
-    return cb()
-
-  for (var i = 0; i < len; i++) {
-    var e = entries[i]
-    if (e.charAt(0) === '.' && !this.dot)
-      continue
-
-    // these two cases enter the inGlobStar state
-    var instead = gspref.concat(entries[i], remainWithoutGlobStar)
-    this._process(instead, index, true, cb)
-
-    var below = gspref.concat(entries[i], remain)
-    this._process(below, index, true, cb)
-  }
-
-  cb()
-}
-
-Glob.prototype._processSimple = function (prefix, index, cb) {
-  // XXX review this.  Shouldn't it be doing the mounting etc
-  // before doing stat?  kinda weird?
-  var self = this
-  this._stat(prefix, function (er, exists) {
-    self._processSimple2(prefix, index, er, exists, cb)
-  })
-}
-Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) {
-
-  //console.error('ps2', prefix, exists)
-
-  if (!this.matches[index])
-    this.matches[index] = Object.create(null)
-
-  // If it doesn't exist, then just mark the lack of results
-  if (!exists)
-    return cb()
-
-  if (prefix && isAbsolute(prefix) && !this.nomount) {
-    var trail = /[\/\\]$/.test(prefix)
-    if (prefix.charAt(0) === '/') {
-      prefix = path.join(this.root, prefix)
-    } else {
-      prefix = path.resolve(this.root, prefix)
-      if (trail)
-        prefix += '/'
-    }
-  }
-
-  if (process.platform === 'win32')
-    prefix = prefix.replace(/\\/g, '/')
-
-  // Mark this as a match
-  this._emitMatch(index, prefix)
-  cb()
-}
-
-// Returns either 'DIR', 'FILE', or false
-Glob.prototype._stat = function (f, cb) {
-  var abs = this._makeAbs(f)
-  var needDir = f.slice(-1) === '/'
-
-  if (f.length > this.maxLength)
-    return cb()
-
-  if (!this.stat && ownProp(this.cache, abs)) {
-    var c = this.cache[abs]
-
-    if (Array.isArray(c))
-      c = 'DIR'
-
-    // It exists, but maybe not how we need it
-    if (!needDir || c === 'DIR')
-      return cb(null, c)
-
-    if (needDir && c === 'FILE')
-      return cb()
-
-    // otherwise we have to stat, because maybe c=true
-    // if we know it exists, but not what it is.
-  }
-
-  var exists
-  var stat = this.statCache[abs]
-  if (stat !== undefined) {
-    if (stat === false)
-      return cb(null, stat)
-    else {
-      var type = stat.isDirectory() ? 'DIR' : 'FILE'
-      if (needDir && type === 'FILE')
-        return cb()
-      else
-        return cb(null, type, stat)
-    }
-  }
-
-  var self = this
-  var statcb = inflight('stat\0' + abs, lstatcb_)
-  if (statcb)
-    self.fs.lstat(abs, statcb)
-
-  function lstatcb_ (er, lstat) {
-    if (lstat && lstat.isSymbolicLink()) {
-      // If it's a symlink, then treat it as the target, unless
-      // the target does not exist, then treat it as a file.
-      return self.fs.stat(abs, function (er, stat) {
-        if (er)
-          self._stat2(f, abs, null, lstat, cb)
-        else
-          self._stat2(f, abs, er, stat, cb)
-      })
-    } else {
-      self._stat2(f, abs, er, lstat, cb)
-    }
-  }
-}
-
-Glob.prototype._stat2 = function (f, abs, er, stat, cb) {
-  if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) {
-    this.statCache[abs] = false
-    return cb()
-  }
-
-  var needDir = f.slice(-1) === '/'
-  this.statCache[abs] = stat
-
-  if (abs.slice(-1) === '/' && stat && !stat.isDirectory())
-    return cb(null, false, stat)
-
-  var c = true
-  if (stat)
-    c = stat.isDirectory() ? 'DIR' : 'FILE'
-  this.cache[abs] = this.cache[abs] || c
-
-  if (needDir && c === 'FILE')
-    return cb()
-
-  return cb(null, c, stat)
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/glob/package.json b/deps/npm/node_modules/node-gyp/node_modules/glob/package.json
deleted file mode 100644
index 5940b649b7e65a..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/glob/package.json
+++ /dev/null
@@ -1,55 +0,0 @@
-{
-  "author": "Isaac Z. Schlueter  (http://blog.izs.me/)",
-  "name": "glob",
-  "description": "a little globber",
-  "version": "7.2.3",
-  "publishConfig": {
-    "tag": "v7-legacy"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/node-glob.git"
-  },
-  "main": "glob.js",
-  "files": [
-    "glob.js",
-    "sync.js",
-    "common.js"
-  ],
-  "engines": {
-    "node": "*"
-  },
-  "dependencies": {
-    "fs.realpath": "^1.0.0",
-    "inflight": "^1.0.4",
-    "inherits": "2",
-    "minimatch": "^3.1.1",
-    "once": "^1.3.0",
-    "path-is-absolute": "^1.0.0"
-  },
-  "devDependencies": {
-    "memfs": "^3.2.0",
-    "mkdirp": "0",
-    "rimraf": "^2.2.8",
-    "tap": "^15.0.6",
-    "tick": "0.0.6"
-  },
-  "tap": {
-    "before": "test/00-setup.js",
-    "after": "test/zz-cleanup.js",
-    "jobs": 1
-  },
-  "scripts": {
-    "prepublish": "npm run benchclean",
-    "profclean": "rm -f v8.log profile.txt",
-    "test": "tap",
-    "test-regen": "npm run profclean && TEST_REGEN=1 node test/00-setup.js",
-    "bench": "bash benchmark.sh",
-    "prof": "bash prof.sh && cat profile.txt",
-    "benchclean": "node benchclean.js"
-  },
-  "license": "ISC",
-  "funding": {
-    "url": "https://github.com/sponsors/isaacs"
-  }
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/glob/sync.js b/deps/npm/node_modules/node-gyp/node_modules/glob/sync.js
deleted file mode 100644
index 2c4f480192d28d..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/glob/sync.js
+++ /dev/null
@@ -1,486 +0,0 @@
-module.exports = globSync
-globSync.GlobSync = GlobSync
-
-var rp = require('fs.realpath')
-var minimatch = require('minimatch')
-var Minimatch = minimatch.Minimatch
-var Glob = require('./glob.js').Glob
-var util = require('util')
-var path = require('path')
-var assert = require('assert')
-var isAbsolute = require('path-is-absolute')
-var common = require('./common.js')
-var setopts = common.setopts
-var ownProp = common.ownProp
-var childrenIgnored = common.childrenIgnored
-var isIgnored = common.isIgnored
-
-function globSync (pattern, options) {
-  if (typeof options === 'function' || arguments.length === 3)
-    throw new TypeError('callback provided to sync glob\n'+
-                        'See: https://github.com/isaacs/node-glob/issues/167')
-
-  return new GlobSync(pattern, options).found
-}
-
-function GlobSync (pattern, options) {
-  if (!pattern)
-    throw new Error('must provide pattern')
-
-  if (typeof options === 'function' || arguments.length === 3)
-    throw new TypeError('callback provided to sync glob\n'+
-                        'See: https://github.com/isaacs/node-glob/issues/167')
-
-  if (!(this instanceof GlobSync))
-    return new GlobSync(pattern, options)
-
-  setopts(this, pattern, options)
-
-  if (this.noprocess)
-    return this
-
-  var n = this.minimatch.set.length
-  this.matches = new Array(n)
-  for (var i = 0; i < n; i ++) {
-    this._process(this.minimatch.set[i], i, false)
-  }
-  this._finish()
-}
-
-GlobSync.prototype._finish = function () {
-  assert.ok(this instanceof GlobSync)
-  if (this.realpath) {
-    var self = this
-    this.matches.forEach(function (matchset, index) {
-      var set = self.matches[index] = Object.create(null)
-      for (var p in matchset) {
-        try {
-          p = self._makeAbs(p)
-          var real = rp.realpathSync(p, self.realpathCache)
-          set[real] = true
-        } catch (er) {
-          if (er.syscall === 'stat')
-            set[self._makeAbs(p)] = true
-          else
-            throw er
-        }
-      }
-    })
-  }
-  common.finish(this)
-}
-
-
-GlobSync.prototype._process = function (pattern, index, inGlobStar) {
-  assert.ok(this instanceof GlobSync)
-
-  // Get the first [n] parts of pattern that are all strings.
-  var n = 0
-  while (typeof pattern[n] === 'string') {
-    n ++
-  }
-  // now n is the index of the first one that is *not* a string.
-
-  // See if there's anything else
-  var prefix
-  switch (n) {
-    // if not, then this is rather simple
-    case pattern.length:
-      this._processSimple(pattern.join('/'), index)
-      return
-
-    case 0:
-      // pattern *starts* with some non-trivial item.
-      // going to readdir(cwd), but not include the prefix in matches.
-      prefix = null
-      break
-
-    default:
-      // pattern has some string bits in the front.
-      // whatever it starts with, whether that's 'absolute' like /foo/bar,
-      // or 'relative' like '../baz'
-      prefix = pattern.slice(0, n).join('/')
-      break
-  }
-
-  var remain = pattern.slice(n)
-
-  // get the list of entries.
-  var read
-  if (prefix === null)
-    read = '.'
-  else if (isAbsolute(prefix) ||
-      isAbsolute(pattern.map(function (p) {
-        return typeof p === 'string' ? p : '[*]'
-      }).join('/'))) {
-    if (!prefix || !isAbsolute(prefix))
-      prefix = '/' + prefix
-    read = prefix
-  } else
-    read = prefix
-
-  var abs = this._makeAbs(read)
-
-  //if ignored, skip processing
-  if (childrenIgnored(this, read))
-    return
-
-  var isGlobStar = remain[0] === minimatch.GLOBSTAR
-  if (isGlobStar)
-    this._processGlobStar(prefix, read, abs, remain, index, inGlobStar)
-  else
-    this._processReaddir(prefix, read, abs, remain, index, inGlobStar)
-}
-
-
-GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) {
-  var entries = this._readdir(abs, inGlobStar)
-
-  // if the abs isn't a dir, then nothing can match!
-  if (!entries)
-    return
-
-  // It will only match dot entries if it starts with a dot, or if
-  // dot is set.  Stuff like @(.foo|.bar) isn't allowed.
-  var pn = remain[0]
-  var negate = !!this.minimatch.negate
-  var rawGlob = pn._glob
-  var dotOk = this.dot || rawGlob.charAt(0) === '.'
-
-  var matchedEntries = []
-  for (var i = 0; i < entries.length; i++) {
-    var e = entries[i]
-    if (e.charAt(0) !== '.' || dotOk) {
-      var m
-      if (negate && !prefix) {
-        m = !e.match(pn)
-      } else {
-        m = e.match(pn)
-      }
-      if (m)
-        matchedEntries.push(e)
-    }
-  }
-
-  var len = matchedEntries.length
-  // If there are no matched entries, then nothing matches.
-  if (len === 0)
-    return
-
-  // if this is the last remaining pattern bit, then no need for
-  // an additional stat *unless* the user has specified mark or
-  // stat explicitly.  We know they exist, since readdir returned
-  // them.
-
-  if (remain.length === 1 && !this.mark && !this.stat) {
-    if (!this.matches[index])
-      this.matches[index] = Object.create(null)
-
-    for (var i = 0; i < len; i ++) {
-      var e = matchedEntries[i]
-      if (prefix) {
-        if (prefix.slice(-1) !== '/')
-          e = prefix + '/' + e
-        else
-          e = prefix + e
-      }
-
-      if (e.charAt(0) === '/' && !this.nomount) {
-        e = path.join(this.root, e)
-      }
-      this._emitMatch(index, e)
-    }
-    // This was the last one, and no stats were needed
-    return
-  }
-
-  // now test all matched entries as stand-ins for that part
-  // of the pattern.
-  remain.shift()
-  for (var i = 0; i < len; i ++) {
-    var e = matchedEntries[i]
-    var newPattern
-    if (prefix)
-      newPattern = [prefix, e]
-    else
-      newPattern = [e]
-    this._process(newPattern.concat(remain), index, inGlobStar)
-  }
-}
-
-
-GlobSync.prototype._emitMatch = function (index, e) {
-  if (isIgnored(this, e))
-    return
-
-  var abs = this._makeAbs(e)
-
-  if (this.mark)
-    e = this._mark(e)
-
-  if (this.absolute) {
-    e = abs
-  }
-
-  if (this.matches[index][e])
-    return
-
-  if (this.nodir) {
-    var c = this.cache[abs]
-    if (c === 'DIR' || Array.isArray(c))
-      return
-  }
-
-  this.matches[index][e] = true
-
-  if (this.stat)
-    this._stat(e)
-}
-
-
-GlobSync.prototype._readdirInGlobStar = function (abs) {
-  // follow all symlinked directories forever
-  // just proceed as if this is a non-globstar situation
-  if (this.follow)
-    return this._readdir(abs, false)
-
-  var entries
-  var lstat
-  var stat
-  try {
-    lstat = this.fs.lstatSync(abs)
-  } catch (er) {
-    if (er.code === 'ENOENT') {
-      // lstat failed, doesn't exist
-      return null
-    }
-  }
-
-  var isSym = lstat && lstat.isSymbolicLink()
-  this.symlinks[abs] = isSym
-
-  // If it's not a symlink or a dir, then it's definitely a regular file.
-  // don't bother doing a readdir in that case.
-  if (!isSym && lstat && !lstat.isDirectory())
-    this.cache[abs] = 'FILE'
-  else
-    entries = this._readdir(abs, false)
-
-  return entries
-}
-
-GlobSync.prototype._readdir = function (abs, inGlobStar) {
-  var entries
-
-  if (inGlobStar && !ownProp(this.symlinks, abs))
-    return this._readdirInGlobStar(abs)
-
-  if (ownProp(this.cache, abs)) {
-    var c = this.cache[abs]
-    if (!c || c === 'FILE')
-      return null
-
-    if (Array.isArray(c))
-      return c
-  }
-
-  try {
-    return this._readdirEntries(abs, this.fs.readdirSync(abs))
-  } catch (er) {
-    this._readdirError(abs, er)
-    return null
-  }
-}
-
-GlobSync.prototype._readdirEntries = function (abs, entries) {
-  // if we haven't asked to stat everything, then just
-  // assume that everything in there exists, so we can avoid
-  // having to stat it a second time.
-  if (!this.mark && !this.stat) {
-    for (var i = 0; i < entries.length; i ++) {
-      var e = entries[i]
-      if (abs === '/')
-        e = abs + e
-      else
-        e = abs + '/' + e
-      this.cache[e] = true
-    }
-  }
-
-  this.cache[abs] = entries
-
-  // mark and cache dir-ness
-  return entries
-}
-
-GlobSync.prototype._readdirError = function (f, er) {
-  // handle errors, and cache the information
-  switch (er.code) {
-    case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205
-    case 'ENOTDIR': // totally normal. means it *does* exist.
-      var abs = this._makeAbs(f)
-      this.cache[abs] = 'FILE'
-      if (abs === this.cwdAbs) {
-        var error = new Error(er.code + ' invalid cwd ' + this.cwd)
-        error.path = this.cwd
-        error.code = er.code
-        throw error
-      }
-      break
-
-    case 'ENOENT': // not terribly unusual
-    case 'ELOOP':
-    case 'ENAMETOOLONG':
-    case 'UNKNOWN':
-      this.cache[this._makeAbs(f)] = false
-      break
-
-    default: // some unusual error.  Treat as failure.
-      this.cache[this._makeAbs(f)] = false
-      if (this.strict)
-        throw er
-      if (!this.silent)
-        console.error('glob error', er)
-      break
-  }
-}
-
-GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) {
-
-  var entries = this._readdir(abs, inGlobStar)
-
-  // no entries means not a dir, so it can never have matches
-  // foo.txt/** doesn't match foo.txt
-  if (!entries)
-    return
-
-  // test without the globstar, and with every child both below
-  // and replacing the globstar.
-  var remainWithoutGlobStar = remain.slice(1)
-  var gspref = prefix ? [ prefix ] : []
-  var noGlobStar = gspref.concat(remainWithoutGlobStar)
-
-  // the noGlobStar pattern exits the inGlobStar state
-  this._process(noGlobStar, index, false)
-
-  var len = entries.length
-  var isSym = this.symlinks[abs]
-
-  // If it's a symlink, and we're in a globstar, then stop
-  if (isSym && inGlobStar)
-    return
-
-  for (var i = 0; i < len; i++) {
-    var e = entries[i]
-    if (e.charAt(0) === '.' && !this.dot)
-      continue
-
-    // these two cases enter the inGlobStar state
-    var instead = gspref.concat(entries[i], remainWithoutGlobStar)
-    this._process(instead, index, true)
-
-    var below = gspref.concat(entries[i], remain)
-    this._process(below, index, true)
-  }
-}
-
-GlobSync.prototype._processSimple = function (prefix, index) {
-  // XXX review this.  Shouldn't it be doing the mounting etc
-  // before doing stat?  kinda weird?
-  var exists = this._stat(prefix)
-
-  if (!this.matches[index])
-    this.matches[index] = Object.create(null)
-
-  // If it doesn't exist, then just mark the lack of results
-  if (!exists)
-    return
-
-  if (prefix && isAbsolute(prefix) && !this.nomount) {
-    var trail = /[\/\\]$/.test(prefix)
-    if (prefix.charAt(0) === '/') {
-      prefix = path.join(this.root, prefix)
-    } else {
-      prefix = path.resolve(this.root, prefix)
-      if (trail)
-        prefix += '/'
-    }
-  }
-
-  if (process.platform === 'win32')
-    prefix = prefix.replace(/\\/g, '/')
-
-  // Mark this as a match
-  this._emitMatch(index, prefix)
-}
-
-// Returns either 'DIR', 'FILE', or false
-GlobSync.prototype._stat = function (f) {
-  var abs = this._makeAbs(f)
-  var needDir = f.slice(-1) === '/'
-
-  if (f.length > this.maxLength)
-    return false
-
-  if (!this.stat && ownProp(this.cache, abs)) {
-    var c = this.cache[abs]
-
-    if (Array.isArray(c))
-      c = 'DIR'
-
-    // It exists, but maybe not how we need it
-    if (!needDir || c === 'DIR')
-      return c
-
-    if (needDir && c === 'FILE')
-      return false
-
-    // otherwise we have to stat, because maybe c=true
-    // if we know it exists, but not what it is.
-  }
-
-  var exists
-  var stat = this.statCache[abs]
-  if (!stat) {
-    var lstat
-    try {
-      lstat = this.fs.lstatSync(abs)
-    } catch (er) {
-      if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) {
-        this.statCache[abs] = false
-        return false
-      }
-    }
-
-    if (lstat && lstat.isSymbolicLink()) {
-      try {
-        stat = this.fs.statSync(abs)
-      } catch (er) {
-        stat = lstat
-      }
-    } else {
-      stat = lstat
-    }
-  }
-
-  this.statCache[abs] = stat
-
-  var c = true
-  if (stat)
-    c = stat.isDirectory() ? 'DIR' : 'FILE'
-
-  this.cache[abs] = this.cache[abs] || c
-
-  if (needDir && c === 'FILE')
-    return false
-
-  return c
-}
-
-GlobSync.prototype._mark = function (p) {
-  return common.mark(this, p)
-}
-
-GlobSync.prototype._makeAbs = function (f) {
-  return common.makeAbs(this, f)
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/minimatch/LICENSE b/deps/npm/node_modules/node-gyp/node_modules/minimatch/LICENSE
deleted file mode 100644
index 19129e315fe593..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/minimatch/LICENSE
+++ /dev/null
@@ -1,15 +0,0 @@
-The ISC License
-
-Copyright (c) Isaac Z. Schlueter and Contributors
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/deps/npm/node_modules/node-gyp/node_modules/minimatch/minimatch.js b/deps/npm/node_modules/node-gyp/node_modules/minimatch/minimatch.js
deleted file mode 100644
index fda45ade7cfc35..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/minimatch/minimatch.js
+++ /dev/null
@@ -1,947 +0,0 @@
-module.exports = minimatch
-minimatch.Minimatch = Minimatch
-
-var path = (function () { try { return require('path') } catch (e) {}}()) || {
-  sep: '/'
-}
-minimatch.sep = path.sep
-
-var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
-var expand = require('brace-expansion')
-
-var plTypes = {
-  '!': { open: '(?:(?!(?:', close: '))[^/]*?)'},
-  '?': { open: '(?:', close: ')?' },
-  '+': { open: '(?:', close: ')+' },
-  '*': { open: '(?:', close: ')*' },
-  '@': { open: '(?:', close: ')' }
-}
-
-// any single thing other than /
-// don't need to escape / when using new RegExp()
-var qmark = '[^/]'
-
-// * => any number of characters
-var star = qmark + '*?'
-
-// ** when dots are allowed.  Anything goes, except .. and .
-// not (^ or / followed by one or two dots followed by $ or /),
-// followed by anything, any number of times.
-var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?'
-
-// not a ^ or / followed by a dot,
-// followed by anything, any number of times.
-var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?'
-
-// characters that need to be escaped in RegExp.
-var reSpecials = charSet('().*{}+?[]^$\\!')
-
-// "abc" -> { a:true, b:true, c:true }
-function charSet (s) {
-  return s.split('').reduce(function (set, c) {
-    set[c] = true
-    return set
-  }, {})
-}
-
-// normalizes slashes.
-var slashSplit = /\/+/
-
-minimatch.filter = filter
-function filter (pattern, options) {
-  options = options || {}
-  return function (p, i, list) {
-    return minimatch(p, pattern, options)
-  }
-}
-
-function ext (a, b) {
-  b = b || {}
-  var t = {}
-  Object.keys(a).forEach(function (k) {
-    t[k] = a[k]
-  })
-  Object.keys(b).forEach(function (k) {
-    t[k] = b[k]
-  })
-  return t
-}
-
-minimatch.defaults = function (def) {
-  if (!def || typeof def !== 'object' || !Object.keys(def).length) {
-    return minimatch
-  }
-
-  var orig = minimatch
-
-  var m = function minimatch (p, pattern, options) {
-    return orig(p, pattern, ext(def, options))
-  }
-
-  m.Minimatch = function Minimatch (pattern, options) {
-    return new orig.Minimatch(pattern, ext(def, options))
-  }
-  m.Minimatch.defaults = function defaults (options) {
-    return orig.defaults(ext(def, options)).Minimatch
-  }
-
-  m.filter = function filter (pattern, options) {
-    return orig.filter(pattern, ext(def, options))
-  }
-
-  m.defaults = function defaults (options) {
-    return orig.defaults(ext(def, options))
-  }
-
-  m.makeRe = function makeRe (pattern, options) {
-    return orig.makeRe(pattern, ext(def, options))
-  }
-
-  m.braceExpand = function braceExpand (pattern, options) {
-    return orig.braceExpand(pattern, ext(def, options))
-  }
-
-  m.match = function (list, pattern, options) {
-    return orig.match(list, pattern, ext(def, options))
-  }
-
-  return m
-}
-
-Minimatch.defaults = function (def) {
-  return minimatch.defaults(def).Minimatch
-}
-
-function minimatch (p, pattern, options) {
-  assertValidPattern(pattern)
-
-  if (!options) options = {}
-
-  // shortcut: comments match nothing.
-  if (!options.nocomment && pattern.charAt(0) === '#') {
-    return false
-  }
-
-  return new Minimatch(pattern, options).match(p)
-}
-
-function Minimatch (pattern, options) {
-  if (!(this instanceof Minimatch)) {
-    return new Minimatch(pattern, options)
-  }
-
-  assertValidPattern(pattern)
-
-  if (!options) options = {}
-
-  pattern = pattern.trim()
-
-  // windows support: need to use /, not \
-  if (!options.allowWindowsEscape && path.sep !== '/') {
-    pattern = pattern.split(path.sep).join('/')
-  }
-
-  this.options = options
-  this.set = []
-  this.pattern = pattern
-  this.regexp = null
-  this.negate = false
-  this.comment = false
-  this.empty = false
-  this.partial = !!options.partial
-
-  // make the set of regexps etc.
-  this.make()
-}
-
-Minimatch.prototype.debug = function () {}
-
-Minimatch.prototype.make = make
-function make () {
-  var pattern = this.pattern
-  var options = this.options
-
-  // empty patterns and comments match nothing.
-  if (!options.nocomment && pattern.charAt(0) === '#') {
-    this.comment = true
-    return
-  }
-  if (!pattern) {
-    this.empty = true
-    return
-  }
-
-  // step 1: figure out negation, etc.
-  this.parseNegate()
-
-  // step 2: expand braces
-  var set = this.globSet = this.braceExpand()
-
-  if (options.debug) this.debug = function debug() { console.error.apply(console, arguments) }
-
-  this.debug(this.pattern, set)
-
-  // step 3: now we have a set, so turn each one into a series of path-portion
-  // matching patterns.
-  // These will be regexps, except in the case of "**", which is
-  // set to the GLOBSTAR object for globstar behavior,
-  // and will not contain any / characters
-  set = this.globParts = set.map(function (s) {
-    return s.split(slashSplit)
-  })
-
-  this.debug(this.pattern, set)
-
-  // glob --> regexps
-  set = set.map(function (s, si, set) {
-    return s.map(this.parse, this)
-  }, this)
-
-  this.debug(this.pattern, set)
-
-  // filter out everything that didn't compile properly.
-  set = set.filter(function (s) {
-    return s.indexOf(false) === -1
-  })
-
-  this.debug(this.pattern, set)
-
-  this.set = set
-}
-
-Minimatch.prototype.parseNegate = parseNegate
-function parseNegate () {
-  var pattern = this.pattern
-  var negate = false
-  var options = this.options
-  var negateOffset = 0
-
-  if (options.nonegate) return
-
-  for (var i = 0, l = pattern.length
-    ; i < l && pattern.charAt(i) === '!'
-    ; i++) {
-    negate = !negate
-    negateOffset++
-  }
-
-  if (negateOffset) this.pattern = pattern.substr(negateOffset)
-  this.negate = negate
-}
-
-// Brace expansion:
-// a{b,c}d -> abd acd
-// a{b,}c -> abc ac
-// a{0..3}d -> a0d a1d a2d a3d
-// a{b,c{d,e}f}g -> abg acdfg acefg
-// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
-//
-// Invalid sets are not expanded.
-// a{2..}b -> a{2..}b
-// a{b}c -> a{b}c
-minimatch.braceExpand = function (pattern, options) {
-  return braceExpand(pattern, options)
-}
-
-Minimatch.prototype.braceExpand = braceExpand
-
-function braceExpand (pattern, options) {
-  if (!options) {
-    if (this instanceof Minimatch) {
-      options = this.options
-    } else {
-      options = {}
-    }
-  }
-
-  pattern = typeof pattern === 'undefined'
-    ? this.pattern : pattern
-
-  assertValidPattern(pattern)
-
-  // Thanks to Yeting Li  for
-  // improving this regexp to avoid a ReDOS vulnerability.
-  if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
-    // shortcut. no need to expand.
-    return [pattern]
-  }
-
-  return expand(pattern)
-}
-
-var MAX_PATTERN_LENGTH = 1024 * 64
-var assertValidPattern = function (pattern) {
-  if (typeof pattern !== 'string') {
-    throw new TypeError('invalid pattern')
-  }
-
-  if (pattern.length > MAX_PATTERN_LENGTH) {
-    throw new TypeError('pattern is too long')
-  }
-}
-
-// parse a component of the expanded set.
-// At this point, no pattern may contain "/" in it
-// so we're going to return a 2d array, where each entry is the full
-// pattern, split on '/', and then turned into a regular expression.
-// A regexp is made at the end which joins each array with an
-// escaped /, and another full one which joins each regexp with |.
-//
-// Following the lead of Bash 4.1, note that "**" only has special meaning
-// when it is the *only* thing in a path portion.  Otherwise, any series
-// of * is equivalent to a single *.  Globstar behavior is enabled by
-// default, and can be disabled by setting options.noglobstar.
-Minimatch.prototype.parse = parse
-var SUBPARSE = {}
-function parse (pattern, isSub) {
-  assertValidPattern(pattern)
-
-  var options = this.options
-
-  // shortcuts
-  if (pattern === '**') {
-    if (!options.noglobstar)
-      return GLOBSTAR
-    else
-      pattern = '*'
-  }
-  if (pattern === '') return ''
-
-  var re = ''
-  var hasMagic = !!options.nocase
-  var escaping = false
-  // ? => one single character
-  var patternListStack = []
-  var negativeLists = []
-  var stateChar
-  var inClass = false
-  var reClassStart = -1
-  var classStart = -1
-  // . and .. never match anything that doesn't start with .,
-  // even when options.dot is set.
-  var patternStart = pattern.charAt(0) === '.' ? '' // anything
-  // not (start or / followed by . or .. followed by / or end)
-  : options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))'
-  : '(?!\\.)'
-  var self = this
-
-  function clearStateChar () {
-    if (stateChar) {
-      // we had some state-tracking character
-      // that wasn't consumed by this pass.
-      switch (stateChar) {
-        case '*':
-          re += star
-          hasMagic = true
-        break
-        case '?':
-          re += qmark
-          hasMagic = true
-        break
-        default:
-          re += '\\' + stateChar
-        break
-      }
-      self.debug('clearStateChar %j %j', stateChar, re)
-      stateChar = false
-    }
-  }
-
-  for (var i = 0, len = pattern.length, c
-    ; (i < len) && (c = pattern.charAt(i))
-    ; i++) {
-    this.debug('%s\t%s %s %j', pattern, i, re, c)
-
-    // skip over any that are escaped.
-    if (escaping && reSpecials[c]) {
-      re += '\\' + c
-      escaping = false
-      continue
-    }
-
-    switch (c) {
-      /* istanbul ignore next */
-      case '/': {
-        // completely not allowed, even escaped.
-        // Should already be path-split by now.
-        return false
-      }
-
-      case '\\':
-        clearStateChar()
-        escaping = true
-      continue
-
-      // the various stateChar values
-      // for the "extglob" stuff.
-      case '?':
-      case '*':
-      case '+':
-      case '@':
-      case '!':
-        this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c)
-
-        // all of those are literals inside a class, except that
-        // the glob [!a] means [^a] in regexp
-        if (inClass) {
-          this.debug('  in class')
-          if (c === '!' && i === classStart + 1) c = '^'
-          re += c
-          continue
-        }
-
-        // if we already have a stateChar, then it means
-        // that there was something like ** or +? in there.
-        // Handle the stateChar, then proceed with this one.
-        self.debug('call clearStateChar %j', stateChar)
-        clearStateChar()
-        stateChar = c
-        // if extglob is disabled, then +(asdf|foo) isn't a thing.
-        // just clear the statechar *now*, rather than even diving into
-        // the patternList stuff.
-        if (options.noext) clearStateChar()
-      continue
-
-      case '(':
-        if (inClass) {
-          re += '('
-          continue
-        }
-
-        if (!stateChar) {
-          re += '\\('
-          continue
-        }
-
-        patternListStack.push({
-          type: stateChar,
-          start: i - 1,
-          reStart: re.length,
-          open: plTypes[stateChar].open,
-          close: plTypes[stateChar].close
-        })
-        // negation is (?:(?!js)[^/]*)
-        re += stateChar === '!' ? '(?:(?!(?:' : '(?:'
-        this.debug('plType %j %j', stateChar, re)
-        stateChar = false
-      continue
-
-      case ')':
-        if (inClass || !patternListStack.length) {
-          re += '\\)'
-          continue
-        }
-
-        clearStateChar()
-        hasMagic = true
-        var pl = patternListStack.pop()
-        // negation is (?:(?!js)[^/]*)
-        // The others are (?:)
-        re += pl.close
-        if (pl.type === '!') {
-          negativeLists.push(pl)
-        }
-        pl.reEnd = re.length
-      continue
-
-      case '|':
-        if (inClass || !patternListStack.length || escaping) {
-          re += '\\|'
-          escaping = false
-          continue
-        }
-
-        clearStateChar()
-        re += '|'
-      continue
-
-      // these are mostly the same in regexp and glob
-      case '[':
-        // swallow any state-tracking char before the [
-        clearStateChar()
-
-        if (inClass) {
-          re += '\\' + c
-          continue
-        }
-
-        inClass = true
-        classStart = i
-        reClassStart = re.length
-        re += c
-      continue
-
-      case ']':
-        //  a right bracket shall lose its special
-        //  meaning and represent itself in
-        //  a bracket expression if it occurs
-        //  first in the list.  -- POSIX.2 2.8.3.2
-        if (i === classStart + 1 || !inClass) {
-          re += '\\' + c
-          escaping = false
-          continue
-        }
-
-        // handle the case where we left a class open.
-        // "[z-a]" is valid, equivalent to "\[z-a\]"
-        // split where the last [ was, make sure we don't have
-        // an invalid re. if so, re-walk the contents of the
-        // would-be class to re-translate any characters that
-        // were passed through as-is
-        // TODO: It would probably be faster to determine this
-        // without a try/catch and a new RegExp, but it's tricky
-        // to do safely.  For now, this is safe and works.
-        var cs = pattern.substring(classStart + 1, i)
-        try {
-          RegExp('[' + cs + ']')
-        } catch (er) {
-          // not a valid class!
-          var sp = this.parse(cs, SUBPARSE)
-          re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'
-          hasMagic = hasMagic || sp[1]
-          inClass = false
-          continue
-        }
-
-        // finish up the class.
-        hasMagic = true
-        inClass = false
-        re += c
-      continue
-
-      default:
-        // swallow any state char that wasn't consumed
-        clearStateChar()
-
-        if (escaping) {
-          // no need
-          escaping = false
-        } else if (reSpecials[c]
-          && !(c === '^' && inClass)) {
-          re += '\\'
-        }
-
-        re += c
-
-    } // switch
-  } // for
-
-  // handle the case where we left a class open.
-  // "[abc" is valid, equivalent to "\[abc"
-  if (inClass) {
-    // split where the last [ was, and escape it
-    // this is a huge pita.  We now have to re-walk
-    // the contents of the would-be class to re-translate
-    // any characters that were passed through as-is
-    cs = pattern.substr(classStart + 1)
-    sp = this.parse(cs, SUBPARSE)
-    re = re.substr(0, reClassStart) + '\\[' + sp[0]
-    hasMagic = hasMagic || sp[1]
-  }
-
-  // handle the case where we had a +( thing at the *end*
-  // of the pattern.
-  // each pattern list stack adds 3 chars, and we need to go through
-  // and escape any | chars that were passed through as-is for the regexp.
-  // Go through and escape them, taking care not to double-escape any
-  // | chars that were already escaped.
-  for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
-    var tail = re.slice(pl.reStart + pl.open.length)
-    this.debug('setting tail', re, pl)
-    // maybe some even number of \, then maybe 1 \, followed by a |
-    tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) {
-      if (!$2) {
-        // the | isn't already escaped, so escape it.
-        $2 = '\\'
-      }
-
-      // need to escape all those slashes *again*, without escaping the
-      // one that we need for escaping the | character.  As it works out,
-      // escaping an even number of slashes can be done by simply repeating
-      // it exactly after itself.  That's why this trick works.
-      //
-      // I am sorry that you have to see this.
-      return $1 + $1 + $2 + '|'
-    })
-
-    this.debug('tail=%j\n   %s', tail, tail, pl, re)
-    var t = pl.type === '*' ? star
-      : pl.type === '?' ? qmark
-      : '\\' + pl.type
-
-    hasMagic = true
-    re = re.slice(0, pl.reStart) + t + '\\(' + tail
-  }
-
-  // handle trailing things that only matter at the very end.
-  clearStateChar()
-  if (escaping) {
-    // trailing \\
-    re += '\\\\'
-  }
-
-  // only need to apply the nodot start if the re starts with
-  // something that could conceivably capture a dot
-  var addPatternStart = false
-  switch (re.charAt(0)) {
-    case '[': case '.': case '(': addPatternStart = true
-  }
-
-  // Hack to work around lack of negative lookbehind in JS
-  // A pattern like: *.!(x).!(y|z) needs to ensure that a name
-  // like 'a.xyz.yz' doesn't match.  So, the first negative
-  // lookahead, has to look ALL the way ahead, to the end of
-  // the pattern.
-  for (var n = negativeLists.length - 1; n > -1; n--) {
-    var nl = negativeLists[n]
-
-    var nlBefore = re.slice(0, nl.reStart)
-    var nlFirst = re.slice(nl.reStart, nl.reEnd - 8)
-    var nlLast = re.slice(nl.reEnd - 8, nl.reEnd)
-    var nlAfter = re.slice(nl.reEnd)
-
-    nlLast += nlAfter
-
-    // Handle nested stuff like *(*.js|!(*.json)), where open parens
-    // mean that we should *not* include the ) in the bit that is considered
-    // "after" the negated section.
-    var openParensBefore = nlBefore.split('(').length - 1
-    var cleanAfter = nlAfter
-    for (i = 0; i < openParensBefore; i++) {
-      cleanAfter = cleanAfter.replace(/\)[+*?]?/, '')
-    }
-    nlAfter = cleanAfter
-
-    var dollar = ''
-    if (nlAfter === '' && isSub !== SUBPARSE) {
-      dollar = '$'
-    }
-    var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast
-    re = newRe
-  }
-
-  // if the re is not "" at this point, then we need to make sure
-  // it doesn't match against an empty path part.
-  // Otherwise a/* will match a/, which it should not.
-  if (re !== '' && hasMagic) {
-    re = '(?=.)' + re
-  }
-
-  if (addPatternStart) {
-    re = patternStart + re
-  }
-
-  // parsing just a piece of a larger pattern.
-  if (isSub === SUBPARSE) {
-    return [re, hasMagic]
-  }
-
-  // skip the regexp for non-magical patterns
-  // unescape anything in it, though, so that it'll be
-  // an exact match against a file etc.
-  if (!hasMagic) {
-    return globUnescape(pattern)
-  }
-
-  var flags = options.nocase ? 'i' : ''
-  try {
-    var regExp = new RegExp('^' + re + '$', flags)
-  } catch (er) /* istanbul ignore next - should be impossible */ {
-    // If it was an invalid regular expression, then it can't match
-    // anything.  This trick looks for a character after the end of
-    // the string, which is of course impossible, except in multi-line
-    // mode, but it's not a /m regex.
-    return new RegExp('$.')
-  }
-
-  regExp._glob = pattern
-  regExp._src = re
-
-  return regExp
-}
-
-minimatch.makeRe = function (pattern, options) {
-  return new Minimatch(pattern, options || {}).makeRe()
-}
-
-Minimatch.prototype.makeRe = makeRe
-function makeRe () {
-  if (this.regexp || this.regexp === false) return this.regexp
-
-  // at this point, this.set is a 2d array of partial
-  // pattern strings, or "**".
-  //
-  // It's better to use .match().  This function shouldn't
-  // be used, really, but it's pretty convenient sometimes,
-  // when you just want to work with a regex.
-  var set = this.set
-
-  if (!set.length) {
-    this.regexp = false
-    return this.regexp
-  }
-  var options = this.options
-
-  var twoStar = options.noglobstar ? star
-    : options.dot ? twoStarDot
-    : twoStarNoDot
-  var flags = options.nocase ? 'i' : ''
-
-  var re = set.map(function (pattern) {
-    return pattern.map(function (p) {
-      return (p === GLOBSTAR) ? twoStar
-      : (typeof p === 'string') ? regExpEscape(p)
-      : p._src
-    }).join('\\\/')
-  }).join('|')
-
-  // must match entire pattern
-  // ending in a * or ** will make it less strict.
-  re = '^(?:' + re + ')$'
-
-  // can match anything, as long as it's not this.
-  if (this.negate) re = '^(?!' + re + ').*$'
-
-  try {
-    this.regexp = new RegExp(re, flags)
-  } catch (ex) /* istanbul ignore next - should be impossible */ {
-    this.regexp = false
-  }
-  return this.regexp
-}
-
-minimatch.match = function (list, pattern, options) {
-  options = options || {}
-  var mm = new Minimatch(pattern, options)
-  list = list.filter(function (f) {
-    return mm.match(f)
-  })
-  if (mm.options.nonull && !list.length) {
-    list.push(pattern)
-  }
-  return list
-}
-
-Minimatch.prototype.match = function match (f, partial) {
-  if (typeof partial === 'undefined') partial = this.partial
-  this.debug('match', f, this.pattern)
-  // short-circuit in the case of busted things.
-  // comments, etc.
-  if (this.comment) return false
-  if (this.empty) return f === ''
-
-  if (f === '/' && partial) return true
-
-  var options = this.options
-
-  // windows: need to use /, not \
-  if (path.sep !== '/') {
-    f = f.split(path.sep).join('/')
-  }
-
-  // treat the test path as a set of pathparts.
-  f = f.split(slashSplit)
-  this.debug(this.pattern, 'split', f)
-
-  // just ONE of the pattern sets in this.set needs to match
-  // in order for it to be valid.  If negating, then just one
-  // match means that we have failed.
-  // Either way, return on the first hit.
-
-  var set = this.set
-  this.debug(this.pattern, 'set', set)
-
-  // Find the basename of the path by looking for the last non-empty segment
-  var filename
-  var i
-  for (i = f.length - 1; i >= 0; i--) {
-    filename = f[i]
-    if (filename) break
-  }
-
-  for (i = 0; i < set.length; i++) {
-    var pattern = set[i]
-    var file = f
-    if (options.matchBase && pattern.length === 1) {
-      file = [filename]
-    }
-    var hit = this.matchOne(file, pattern, partial)
-    if (hit) {
-      if (options.flipNegate) return true
-      return !this.negate
-    }
-  }
-
-  // didn't get any hits.  this is success if it's a negative
-  // pattern, failure otherwise.
-  if (options.flipNegate) return false
-  return this.negate
-}
-
-// set partial to true to test if, for example,
-// "/a/b" matches the start of "/*/b/*/d"
-// Partial means, if you run out of file before you run
-// out of pattern, then that's fine, as long as all
-// the parts match.
-Minimatch.prototype.matchOne = function (file, pattern, partial) {
-  var options = this.options
-
-  this.debug('matchOne',
-    { 'this': this, file: file, pattern: pattern })
-
-  this.debug('matchOne', file.length, pattern.length)
-
-  for (var fi = 0,
-      pi = 0,
-      fl = file.length,
-      pl = pattern.length
-      ; (fi < fl) && (pi < pl)
-      ; fi++, pi++) {
-    this.debug('matchOne loop')
-    var p = pattern[pi]
-    var f = file[fi]
-
-    this.debug(pattern, p, f)
-
-    // should be impossible.
-    // some invalid regexp stuff in the set.
-    /* istanbul ignore if */
-    if (p === false) return false
-
-    if (p === GLOBSTAR) {
-      this.debug('GLOBSTAR', [pattern, p, f])
-
-      // "**"
-      // a/**/b/**/c would match the following:
-      // a/b/x/y/z/c
-      // a/x/y/z/b/c
-      // a/b/x/b/x/c
-      // a/b/c
-      // To do this, take the rest of the pattern after
-      // the **, and see if it would match the file remainder.
-      // If so, return success.
-      // If not, the ** "swallows" a segment, and try again.
-      // This is recursively awful.
-      //
-      // a/**/b/**/c matching a/b/x/y/z/c
-      // - a matches a
-      // - doublestar
-      //   - matchOne(b/x/y/z/c, b/**/c)
-      //     - b matches b
-      //     - doublestar
-      //       - matchOne(x/y/z/c, c) -> no
-      //       - matchOne(y/z/c, c) -> no
-      //       - matchOne(z/c, c) -> no
-      //       - matchOne(c, c) yes, hit
-      var fr = fi
-      var pr = pi + 1
-      if (pr === pl) {
-        this.debug('** at the end')
-        // a ** at the end will just swallow the rest.
-        // We have found a match.
-        // however, it will not swallow /.x, unless
-        // options.dot is set.
-        // . and .. are *never* matched by **, for explosively
-        // exponential reasons.
-        for (; fi < fl; fi++) {
-          if (file[fi] === '.' || file[fi] === '..' ||
-            (!options.dot && file[fi].charAt(0) === '.')) return false
-        }
-        return true
-      }
-
-      // ok, let's see if we can swallow whatever we can.
-      while (fr < fl) {
-        var swallowee = file[fr]
-
-        this.debug('\nglobstar while', file, fr, pattern, pr, swallowee)
-
-        // XXX remove this slice.  Just pass the start index.
-        if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
-          this.debug('globstar found match!', fr, fl, swallowee)
-          // found a match.
-          return true
-        } else {
-          // can't swallow "." or ".." ever.
-          // can only swallow ".foo" when explicitly asked.
-          if (swallowee === '.' || swallowee === '..' ||
-            (!options.dot && swallowee.charAt(0) === '.')) {
-            this.debug('dot detected!', file, fr, pattern, pr)
-            break
-          }
-
-          // ** swallows a segment, and continue.
-          this.debug('globstar swallow a segment, and continue')
-          fr++
-        }
-      }
-
-      // no match was found.
-      // However, in partial mode, we can't say this is necessarily over.
-      // If there's more *pattern* left, then
-      /* istanbul ignore if */
-      if (partial) {
-        // ran out of file
-        this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
-        if (fr === fl) return true
-      }
-      return false
-    }
-
-    // something other than **
-    // non-magic patterns just have to match exactly
-    // patterns with magic have been turned into regexps.
-    var hit
-    if (typeof p === 'string') {
-      hit = f === p
-      this.debug('string match', p, f, hit)
-    } else {
-      hit = f.match(p)
-      this.debug('pattern match', p, f, hit)
-    }
-
-    if (!hit) return false
-  }
-
-  // Note: ending in / means that we'll get a final ""
-  // at the end of the pattern.  This can only match a
-  // corresponding "" at the end of the file.
-  // If the file ends in /, then it can only match a
-  // a pattern that ends in /, unless the pattern just
-  // doesn't have any more for it. But, a/b/ should *not*
-  // match "a/b/*", even though "" matches against the
-  // [^/]*? pattern, except in partial mode, where it might
-  // simply not be reached yet.
-  // However, a/b/ should still satisfy a/*
-
-  // now either we fell off the end of the pattern, or we're done.
-  if (fi === fl && pi === pl) {
-    // ran out of pattern and filename at the same time.
-    // an exact hit!
-    return true
-  } else if (fi === fl) {
-    // ran out of file, but still had pattern left.
-    // this is ok if we're doing the match as part of
-    // a glob fs traversal.
-    return partial
-  } else /* istanbul ignore else */ if (pi === pl) {
-    // ran out of pattern, still have file left.
-    // this is only acceptable if we're on the very last
-    // empty segment of a file with a trailing slash.
-    // a/* should match a/b/
-    return (fi === fl - 1) && (file[fi] === '')
-  }
-
-  // should be unreachable.
-  /* istanbul ignore next */
-  throw new Error('wtf?')
-}
-
-// replace stuff like \* with *
-function globUnescape (s) {
-  return s.replace(/\\(.)/g, '$1')
-}
-
-function regExpEscape (s) {
-  return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/minimatch/package.json b/deps/npm/node_modules/node-gyp/node_modules/minimatch/package.json
deleted file mode 100644
index 566efdfe45cb80..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/minimatch/package.json
+++ /dev/null
@@ -1,33 +0,0 @@
-{
-  "author": "Isaac Z. Schlueter  (http://blog.izs.me)",
-  "name": "minimatch",
-  "description": "a glob matcher in javascript",
-  "version": "3.1.2",
-  "publishConfig": {
-    "tag": "v3-legacy"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/minimatch.git"
-  },
-  "main": "minimatch.js",
-  "scripts": {
-    "test": "tap",
-    "preversion": "npm test",
-    "postversion": "npm publish",
-    "postpublish": "git push origin --all; git push origin --tags"
-  },
-  "engines": {
-    "node": "*"
-  },
-  "dependencies": {
-    "brace-expansion": "^1.1.7"
-  },
-  "devDependencies": {
-    "tap": "^15.1.6"
-  },
-  "license": "ISC",
-  "files": [
-    "minimatch.js"
-  ]
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/nopt/LICENSE b/deps/npm/node_modules/node-gyp/node_modules/nopt/LICENSE
deleted file mode 100644
index 19129e315fe593..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/nopt/LICENSE
+++ /dev/null
@@ -1,15 +0,0 @@
-The ISC License
-
-Copyright (c) Isaac Z. Schlueter and Contributors
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/deps/npm/node_modules/node-gyp/node_modules/nopt/README.md b/deps/npm/node_modules/node-gyp/node_modules/nopt/README.md
deleted file mode 100644
index a99531c04655fe..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/nopt/README.md
+++ /dev/null
@@ -1,213 +0,0 @@
-If you want to write an option parser, and have it be good, there are
-two ways to do it.  The Right Way, and the Wrong Way.
-
-The Wrong Way is to sit down and write an option parser.  We've all done
-that.
-
-The Right Way is to write some complex configurable program with so many
-options that you hit the limit of your frustration just trying to
-manage them all, and defer it with duct-tape solutions until you see
-exactly to the core of the problem, and finally snap and write an
-awesome option parser.
-
-If you want to write an option parser, don't write an option parser.
-Write a package manager, or a source control system, or a service
-restarter, or an operating system.  You probably won't end up with a
-good one of those, but if you don't give up, and you are relentless and
-diligent enough in your procrastination, you may just end up with a very
-nice option parser.
-
-## USAGE
-
-```javascript
-// my-program.js
-var nopt = require("nopt")
-  , Stream = require("stream").Stream
-  , path = require("path")
-  , knownOpts = { "foo" : [String, null]
-                , "bar" : [Stream, Number]
-                , "baz" : path
-                , "bloo" : [ "big", "medium", "small" ]
-                , "flag" : Boolean
-                , "pick" : Boolean
-                , "many1" : [String, Array]
-                , "many2" : [path, Array]
-                }
-  , shortHands = { "foofoo" : ["--foo", "Mr. Foo"]
-                 , "b7" : ["--bar", "7"]
-                 , "m" : ["--bloo", "medium"]
-                 , "p" : ["--pick"]
-                 , "f" : ["--flag"]
-                 }
-             // everything is optional.
-             // knownOpts and shorthands default to {}
-             // arg list defaults to process.argv
-             // slice defaults to 2
-  , parsed = nopt(knownOpts, shortHands, process.argv, 2)
-console.log(parsed)
-```
-
-This would give you support for any of the following:
-
-```console
-$ node my-program.js --foo "blerp" --no-flag
-{ "foo" : "blerp", "flag" : false }
-
-$ node my-program.js ---bar 7 --foo "Mr. Hand" --flag
-{ bar: 7, foo: "Mr. Hand", flag: true }
-
-$ node my-program.js --foo "blerp" -f -----p
-{ foo: "blerp", flag: true, pick: true }
-
-$ node my-program.js -fp --foofoo
-{ foo: "Mr. Foo", flag: true, pick: true }
-
-$ node my-program.js --foofoo -- -fp  # -- stops the flag parsing.
-{ foo: "Mr. Foo", argv: { remain: ["-fp"] } }
-
-$ node my-program.js --blatzk -fp # unknown opts are ok.
-{ blatzk: true, flag: true, pick: true }
-
-$ node my-program.js --blatzk=1000 -fp # but you need to use = if they have a value
-{ blatzk: 1000, flag: true, pick: true }
-
-$ node my-program.js --no-blatzk -fp # unless they start with "no-"
-{ blatzk: false, flag: true, pick: true }
-
-$ node my-program.js --baz b/a/z # known paths are resolved.
-{ baz: "/Users/isaacs/b/a/z" }
-
-# if Array is one of the types, then it can take many
-# values, and will always be an array.  The other types provided
-# specify what types are allowed in the list.
-
-$ node my-program.js --many1 5 --many1 null --many1 foo
-{ many1: ["5", "null", "foo"] }
-
-$ node my-program.js --many2 foo --many2 bar
-{ many2: ["/path/to/foo", "path/to/bar"] }
-```
-
-Read the tests at the bottom of `lib/nopt.js` for more examples of
-what this puppy can do.
-
-## Types
-
-The following types are supported, and defined on `nopt.typeDefs`
-
-* String: A normal string.  No parsing is done.
-* path: A file system path.  Gets resolved against cwd if not absolute.
-* url: A url.  If it doesn't parse, it isn't accepted.
-* Number: Must be numeric.
-* Date: Must parse as a date. If it does, and `Date` is one of the options,
-  then it will return a Date object, not a string.
-* Boolean: Must be either `true` or `false`.  If an option is a boolean,
-  then it does not need a value, and its presence will imply `true` as
-  the value.  To negate boolean flags, do `--no-whatever` or `--whatever
-  false`
-* NaN: Means that the option is strictly not allowed.  Any value will
-  fail.
-* Stream: An object matching the "Stream" class in node.  Valuable
-  for use when validating programmatically.  (npm uses this to let you
-  supply any WriteStream on the `outfd` and `logfd` config options.)
-* Array: If `Array` is specified as one of the types, then the value
-  will be parsed as a list of options.  This means that multiple values
-  can be specified, and that the value will always be an array.
-
-If a type is an array of values not on this list, then those are
-considered valid values.  For instance, in the example above, the
-`--bloo` option can only be one of `"big"`, `"medium"`, or `"small"`,
-and any other value will be rejected.
-
-When parsing unknown fields, `"true"`, `"false"`, and `"null"` will be
-interpreted as their JavaScript equivalents.
-
-You can also mix types and values, or multiple types, in a list.  For
-instance `{ blah: [Number, null] }` would allow a value to be set to
-either a Number or null.  When types are ordered, this implies a
-preference, and the first type that can be used to properly interpret
-the value will be used.
-
-To define a new type, add it to `nopt.typeDefs`.  Each item in that
-hash is an object with a `type` member and a `validate` method.  The
-`type` member is an object that matches what goes in the type list.  The
-`validate` method is a function that gets called with `validate(data,
-key, val)`.  Validate methods should assign `data[key]` to the valid
-value of `val` if it can be handled properly, or return boolean
-`false` if it cannot.
-
-You can also call `nopt.clean(data, types, typeDefs)` to clean up a
-config object and remove its invalid properties.
-
-## Error Handling
-
-By default, nopt outputs a warning to standard error when invalid values for
-known options are found.  You can change this behavior by assigning a method
-to `nopt.invalidHandler`.  This method will be called with
-the offending `nopt.invalidHandler(key, val, types)`.
-
-If no `nopt.invalidHandler` is assigned, then it will console.error
-its whining.  If it is assigned to boolean `false` then the warning is
-suppressed.
-
-## Abbreviations
-
-Yes, they are supported.  If you define options like this:
-
-```javascript
-{ "foolhardyelephants" : Boolean
-, "pileofmonkeys" : Boolean }
-```
-
-Then this will work:
-
-```bash
-node program.js --foolhar --pil
-node program.js --no-f --pileofmon
-# etc.
-```
-
-## Shorthands
-
-Shorthands are a hash of shorter option names to a snippet of args that
-they expand to.
-
-If multiple one-character shorthands are all combined, and the
-combination does not unambiguously match any other option or shorthand,
-then they will be broken up into their constituent parts.  For example:
-
-```json
-{ "s" : ["--loglevel", "silent"]
-, "g" : "--global"
-, "f" : "--force"
-, "p" : "--parseable"
-, "l" : "--long"
-}
-```
-
-```bash
-npm ls -sgflp
-# just like doing this:
-npm ls --loglevel silent --global --force --long --parseable
-```
-
-## The Rest of the args
-
-The config object returned by nopt is given a special member called
-`argv`, which is an object with the following fields:
-
-* `remain`: The remaining args after all the parsing has occurred.
-* `original`: The args as they originally appeared.
-* `cooked`: The args after flags and shorthands are expanded.
-
-## Slicing
-
-Node programs are called with more or less the exact argv as it appears
-in C land, after the v8 and node-specific options have been plucked off.
-As such, `argv[0]` is always `node` and `argv[1]` is always the
-JavaScript program being run.
-
-That's usually not very useful to you.  So they're sliced off by
-default.  If you want them, then you can pass in `0` as the last
-argument, or any other number that you'd like to slice off the start of
-the list.
diff --git a/deps/npm/node_modules/node-gyp/node_modules/nopt/bin/nopt.js b/deps/npm/node_modules/node-gyp/node_modules/nopt/bin/nopt.js
deleted file mode 100755
index bb04291c607acf..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/nopt/bin/nopt.js
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env node
-var nopt = require('../lib/nopt')
-var path = require('path')
-var types = { num: Number,
-  bool: Boolean,
-  help: Boolean,
-  list: Array,
-  'num-list': [Number, Array],
-  'str-list': [String, Array],
-  'bool-list': [Boolean, Array],
-  str: String,
-  clear: Boolean,
-  config: Boolean,
-  length: Number,
-  file: path,
-}
-var shorthands = { s: ['--str', 'astring'],
-  b: ['--bool'],
-  nb: ['--no-bool'],
-  tft: ['--bool-list', '--no-bool-list', '--bool-list', 'true'],
-  '?': ['--help'],
-  h: ['--help'],
-  H: ['--help'],
-  n: ['--num', '125'],
-  c: ['--config'],
-  l: ['--length'],
-  f: ['--file'],
-}
-var parsed = nopt(types
-  , shorthands
-  , process.argv
-  , 2)
-
-console.log('parsed', parsed)
-
-if (parsed.help) {
-  console.log('')
-  console.log('nopt cli tester')
-  console.log('')
-  console.log('types')
-  console.log(Object.keys(types).map(function M (t) {
-    var type = types[t]
-    if (Array.isArray(type)) {
-      return [t, type.map(function (mappedType) {
-        return mappedType.name
-      })]
-    }
-    return [t, type && type.name]
-  }).reduce(function (s, i) {
-    s[i[0]] = i[1]
-    return s
-  }, {}))
-  console.log('')
-  console.log('shorthands')
-  console.log(shorthands)
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/nopt/lib/nopt.js b/deps/npm/node_modules/node-gyp/node_modules/nopt/lib/nopt.js
deleted file mode 100644
index 5829c2fe0f6379..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/nopt/lib/nopt.js
+++ /dev/null
@@ -1,515 +0,0 @@
-// info about each config option.
-
-var debug = process.env.DEBUG_NOPT || process.env.NOPT_DEBUG
-  ? function () {
-    console.error.apply(console, arguments)
-  }
-  : function () {}
-
-var url = require('url')
-var path = require('path')
-var Stream = require('stream').Stream
-var abbrev = require('abbrev')
-var os = require('os')
-
-module.exports = exports = nopt
-exports.clean = clean
-
-exports.typeDefs =
-  { String: { type: String, validate: validateString },
-    Boolean: { type: Boolean, validate: validateBoolean },
-    url: { type: url, validate: validateUrl },
-    Number: { type: Number, validate: validateNumber },
-    path: { type: path, validate: validatePath },
-    Stream: { type: Stream, validate: validateStream },
-    Date: { type: Date, validate: validateDate },
-  }
-
-function nopt (types, shorthands, args, slice) {
-  args = args || process.argv
-  types = types || {}
-  shorthands = shorthands || {}
-  if (typeof slice !== 'number') {
-    slice = 2
-  }
-
-  debug(types, shorthands, args, slice)
-
-  args = args.slice(slice)
-  var data = {}
-  var argv = {
-    remain: [],
-    cooked: args,
-    original: args.slice(0),
-  }
-
-  parse(args, data, argv.remain, types, shorthands)
-  // now data is full
-  clean(data, types, exports.typeDefs)
-  data.argv = argv
-  Object.defineProperty(data.argv, 'toString', { value: function () {
-    return this.original.map(JSON.stringify).join(' ')
-  },
-  enumerable: false })
-  return data
-}
-
-function clean (data, types, typeDefs) {
-  typeDefs = typeDefs || exports.typeDefs
-  var remove = {}
-  var typeDefault = [false, true, null, String, Array]
-
-  Object.keys(data).forEach(function (k) {
-    if (k === 'argv') {
-      return
-    }
-    var val = data[k]
-    var isArray = Array.isArray(val)
-    var type = types[k]
-    if (!isArray) {
-      val = [val]
-    }
-    if (!type) {
-      type = typeDefault
-    }
-    if (type === Array) {
-      type = typeDefault.concat(Array)
-    }
-    if (!Array.isArray(type)) {
-      type = [type]
-    }
-
-    debug('val=%j', val)
-    debug('types=', type)
-    val = val.map(function (v) {
-      // if it's an unknown value, then parse false/true/null/numbers/dates
-      if (typeof v === 'string') {
-        debug('string %j', v)
-        v = v.trim()
-        if ((v === 'null' && ~type.indexOf(null))
-            || (v === 'true' &&
-               (~type.indexOf(true) || ~type.indexOf(Boolean)))
-            || (v === 'false' &&
-               (~type.indexOf(false) || ~type.indexOf(Boolean)))) {
-          v = JSON.parse(v)
-          debug('jsonable %j', v)
-        } else if (~type.indexOf(Number) && !isNaN(v)) {
-          debug('convert to number', v)
-          v = +v
-        } else if (~type.indexOf(Date) && !isNaN(Date.parse(v))) {
-          debug('convert to date', v)
-          v = new Date(v)
-        }
-      }
-
-      if (!Object.prototype.hasOwnProperty.call(types, k)) {
-        return v
-      }
-
-      // allow `--no-blah` to set 'blah' to null if null is allowed
-      if (v === false && ~type.indexOf(null) &&
-          !(~type.indexOf(false) || ~type.indexOf(Boolean))) {
-        v = null
-      }
-
-      var d = {}
-      d[k] = v
-      debug('prevalidated val', d, v, types[k])
-      if (!validate(d, k, v, types[k], typeDefs)) {
-        if (exports.invalidHandler) {
-          exports.invalidHandler(k, v, types[k], data)
-        } else if (exports.invalidHandler !== false) {
-          debug('invalid: ' + k + '=' + v, types[k])
-        }
-        return remove
-      }
-      debug('validated v', d, v, types[k])
-      return d[k]
-    }).filter(function (v) {
-      return v !== remove
-    })
-
-    // if we allow Array specifically, then an empty array is how we
-    // express 'no value here', not null.  Allow it.
-    if (!val.length && type.indexOf(Array) === -1) {
-      debug('VAL HAS NO LENGTH, DELETE IT', val, k, type.indexOf(Array))
-      delete data[k]
-    } else if (isArray) {
-      debug(isArray, data[k], val)
-      data[k] = val
-    } else {
-      data[k] = val[0]
-    }
-
-    debug('k=%s val=%j', k, val, data[k])
-  })
-}
-
-function validateString (data, k, val) {
-  data[k] = String(val)
-}
-
-function validatePath (data, k, val) {
-  if (val === true) {
-    return false
-  }
-  if (val === null) {
-    return true
-  }
-
-  val = String(val)
-
-  var isWin = process.platform === 'win32'
-  var homePattern = isWin ? /^~(\/|\\)/ : /^~\//
-  var home = os.homedir()
-
-  if (home && val.match(homePattern)) {
-    data[k] = path.resolve(home, val.slice(2))
-  } else {
-    data[k] = path.resolve(val)
-  }
-  return true
-}
-
-function validateNumber (data, k, val) {
-  debug('validate Number %j %j %j', k, val, isNaN(val))
-  if (isNaN(val)) {
-    return false
-  }
-  data[k] = +val
-}
-
-function validateDate (data, k, val) {
-  var s = Date.parse(val)
-  debug('validate Date %j %j %j', k, val, s)
-  if (isNaN(s)) {
-    return false
-  }
-  data[k] = new Date(val)
-}
-
-function validateBoolean (data, k, val) {
-  if (val instanceof Boolean) {
-    val = val.valueOf()
-  } else if (typeof val === 'string') {
-    if (!isNaN(val)) {
-      val = !!(+val)
-    } else if (val === 'null' || val === 'false') {
-      val = false
-    } else {
-      val = true
-    }
-  } else {
-    val = !!val
-  }
-  data[k] = val
-}
-
-function validateUrl (data, k, val) {
-  // Changing this would be a breaking change in the npm cli
-  /* eslint-disable-next-line node/no-deprecated-api */
-  val = url.parse(String(val))
-  if (!val.host) {
-    return false
-  }
-  data[k] = val.href
-}
-
-function validateStream (data, k, val) {
-  if (!(val instanceof Stream)) {
-    return false
-  }
-  data[k] = val
-}
-
-function validate (data, k, val, type, typeDefs) {
-  // arrays are lists of types.
-  if (Array.isArray(type)) {
-    for (let i = 0, l = type.length; i < l; i++) {
-      if (type[i] === Array) {
-        continue
-      }
-      if (validate(data, k, val, type[i], typeDefs)) {
-        return true
-      }
-    }
-    delete data[k]
-    return false
-  }
-
-  // an array of anything?
-  if (type === Array) {
-    return true
-  }
-
-  // Original comment:
-  // NaN is poisonous.  Means that something is not allowed.
-  // New comment: Changing this to an isNaN check breaks a lot of tests.
-  // Something is being assumed here that is not actually what happens in
-  // practice.  Fixing it is outside the scope of getting linting to pass in
-  // this repo. Leaving as-is for now.
-  /* eslint-disable-next-line no-self-compare */
-  if (type !== type) {
-    debug('Poison NaN', k, val, type)
-    delete data[k]
-    return false
-  }
-
-  // explicit list of values
-  if (val === type) {
-    debug('Explicitly allowed %j', val)
-    // if (isArray) (data[k] = data[k] || []).push(val)
-    // else data[k] = val
-    data[k] = val
-    return true
-  }
-
-  // now go through the list of typeDefs, validate against each one.
-  var ok = false
-  var types = Object.keys(typeDefs)
-  for (let i = 0, l = types.length; i < l; i++) {
-    debug('test type %j %j %j', k, val, types[i])
-    var t = typeDefs[types[i]]
-    if (t && (
-      (type && type.name && t.type && t.type.name) ?
-        (type.name === t.type.name) :
-        (type === t.type)
-    )) {
-      var d = {}
-      ok = t.validate(d, k, val) !== false
-      val = d[k]
-      if (ok) {
-        // if (isArray) (data[k] = data[k] || []).push(val)
-        // else data[k] = val
-        data[k] = val
-        break
-      }
-    }
-  }
-  debug('OK? %j (%j %j %j)', ok, k, val, types[types.length - 1])
-
-  if (!ok) {
-    delete data[k]
-  }
-  return ok
-}
-
-function parse (args, data, remain, types, shorthands) {
-  debug('parse', args, data, remain)
-
-  var abbrevs = abbrev(Object.keys(types))
-  var shortAbbr = abbrev(Object.keys(shorthands))
-
-  for (var i = 0; i < args.length; i++) {
-    var arg = args[i]
-    debug('arg', arg)
-
-    if (arg.match(/^-{2,}$/)) {
-      // done with keys.
-      // the rest are args.
-      remain.push.apply(remain, args.slice(i + 1))
-      args[i] = '--'
-      break
-    }
-    var hadEq = false
-    if (arg.charAt(0) === '-' && arg.length > 1) {
-      var at = arg.indexOf('=')
-      if (at > -1) {
-        hadEq = true
-        var v = arg.slice(at + 1)
-        arg = arg.slice(0, at)
-        args.splice(i, 1, arg, v)
-      }
-
-      // see if it's a shorthand
-      // if so, splice and back up to re-parse it.
-      var shRes = resolveShort(arg, shorthands, shortAbbr, abbrevs)
-      debug('arg=%j shRes=%j', arg, shRes)
-      if (shRes) {
-        debug(arg, shRes)
-        args.splice.apply(args, [i, 1].concat(shRes))
-        if (arg !== shRes[0]) {
-          i--
-          continue
-        }
-      }
-      arg = arg.replace(/^-+/, '')
-      var no = null
-      while (arg.toLowerCase().indexOf('no-') === 0) {
-        no = !no
-        arg = arg.slice(3)
-      }
-
-      if (abbrevs[arg]) {
-        arg = abbrevs[arg]
-      }
-
-      var argType = types[arg]
-      var isTypeArray = Array.isArray(argType)
-      if (isTypeArray && argType.length === 1) {
-        isTypeArray = false
-        argType = argType[0]
-      }
-
-      var isArray = argType === Array ||
-        isTypeArray && argType.indexOf(Array) !== -1
-
-      // allow unknown things to be arrays if specified multiple times.
-      if (
-        !Object.prototype.hasOwnProperty.call(types, arg) &&
-        Object.prototype.hasOwnProperty.call(data, arg)
-      ) {
-        if (!Array.isArray(data[arg])) {
-          data[arg] = [data[arg]]
-        }
-        isArray = true
-      }
-
-      var val
-      var la = args[i + 1]
-
-      var isBool = typeof no === 'boolean' ||
-        argType === Boolean ||
-        isTypeArray && argType.indexOf(Boolean) !== -1 ||
-        (typeof argType === 'undefined' && !hadEq) ||
-        (la === 'false' &&
-         (argType === null ||
-          isTypeArray && ~argType.indexOf(null)))
-
-      if (isBool) {
-        // just set and move along
-        val = !no
-        // however, also support --bool true or --bool false
-        if (la === 'true' || la === 'false') {
-          val = JSON.parse(la)
-          la = null
-          if (no) {
-            val = !val
-          }
-          i++
-        }
-
-        // also support "foo":[Boolean, "bar"] and "--foo bar"
-        if (isTypeArray && la) {
-          if (~argType.indexOf(la)) {
-            // an explicit type
-            val = la
-            i++
-          } else if (la === 'null' && ~argType.indexOf(null)) {
-            // null allowed
-            val = null
-            i++
-          } else if (!la.match(/^-{2,}[^-]/) &&
-                      !isNaN(la) &&
-                      ~argType.indexOf(Number)) {
-            // number
-            val = +la
-            i++
-          } else if (!la.match(/^-[^-]/) && ~argType.indexOf(String)) {
-            // string
-            val = la
-            i++
-          }
-        }
-
-        if (isArray) {
-          (data[arg] = data[arg] || []).push(val)
-        } else {
-          data[arg] = val
-        }
-
-        continue
-      }
-
-      if (argType === String) {
-        if (la === undefined) {
-          la = ''
-        } else if (la.match(/^-{1,2}[^-]+/)) {
-          la = ''
-          i--
-        }
-      }
-
-      if (la && la.match(/^-{2,}$/)) {
-        la = undefined
-        i--
-      }
-
-      val = la === undefined ? true : la
-      if (isArray) {
-        (data[arg] = data[arg] || []).push(val)
-      } else {
-        data[arg] = val
-      }
-
-      i++
-      continue
-    }
-    remain.push(arg)
-  }
-}
-
-function resolveShort (arg, shorthands, shortAbbr, abbrevs) {
-  // handle single-char shorthands glommed together, like
-  // npm ls -glp, but only if there is one dash, and only if
-  // all of the chars are single-char shorthands, and it's
-  // not a match to some other abbrev.
-  arg = arg.replace(/^-+/, '')
-
-  // if it's an exact known option, then don't go any further
-  if (abbrevs[arg] === arg) {
-    return null
-  }
-
-  // if it's an exact known shortopt, same deal
-  if (shorthands[arg]) {
-    // make it an array, if it's a list of words
-    if (shorthands[arg] && !Array.isArray(shorthands[arg])) {
-      shorthands[arg] = shorthands[arg].split(/\s+/)
-    }
-
-    return shorthands[arg]
-  }
-
-  // first check to see if this arg is a set of single-char shorthands
-  var singles = shorthands.___singles
-  if (!singles) {
-    singles = Object.keys(shorthands).filter(function (s) {
-      return s.length === 1
-    }).reduce(function (l, r) {
-      l[r] = true
-      return l
-    }, {})
-    shorthands.___singles = singles
-    debug('shorthand singles', singles)
-  }
-
-  var chrs = arg.split('').filter(function (c) {
-    return singles[c]
-  })
-
-  if (chrs.join('') === arg) {
-    return chrs.map(function (c) {
-      return shorthands[c]
-    }).reduce(function (l, r) {
-      return l.concat(r)
-    }, [])
-  }
-
-  // if it's an arg abbrev, and not a literal shorthand, then prefer the arg
-  if (abbrevs[arg] && !shorthands[arg]) {
-    return null
-  }
-
-  // if it's an abbr for a shorthand, then use that
-  if (shortAbbr[arg]) {
-    arg = shortAbbr[arg]
-  }
-
-  // make it an array, if it's a list of words
-  if (shorthands[arg] && !Array.isArray(shorthands[arg])) {
-    shorthands[arg] = shorthands[arg].split(/\s+/)
-  }
-
-  return shorthands[arg]
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/nopt/package.json b/deps/npm/node_modules/node-gyp/node_modules/nopt/package.json
deleted file mode 100644
index a3cd13d8c714bd..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/nopt/package.json
+++ /dev/null
@@ -1,53 +0,0 @@
-{
-  "name": "nopt",
-  "version": "6.0.0",
-  "description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.",
-  "author": "GitHub Inc.",
-  "main": "lib/nopt.js",
-  "scripts": {
-    "preversion": "npm test",
-    "postversion": "npm publish",
-    "prepublishOnly": "git push origin --follow-tags",
-    "test": "tap",
-    "lint": "eslint \"**/*.js\"",
-    "postlint": "template-oss-check",
-    "template-oss-apply": "template-oss-apply --force",
-    "lintfix": "npm run lint -- --fix",
-    "snap": "tap",
-    "posttest": "npm run lint"
-  },
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/npm/nopt.git"
-  },
-  "bin": {
-    "nopt": "bin/nopt.js"
-  },
-  "license": "ISC",
-  "dependencies": {
-    "abbrev": "^1.0.0"
-  },
-  "devDependencies": {
-    "@npmcli/eslint-config": "^3.0.1",
-    "@npmcli/template-oss": "3.5.0",
-    "tap": "^16.3.0"
-  },
-  "tap": {
-    "lines": 87,
-    "functions": 91,
-    "branches": 81,
-    "statements": 87
-  },
-  "files": [
-    "bin/",
-    "lib/"
-  ],
-  "engines": {
-    "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
-  },
-  "templateOSS": {
-    "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
-    "windowsCI": false,
-    "version": "3.5.0"
-  }
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/npmlog/LICENSE.md b/deps/npm/node_modules/node-gyp/node_modules/npmlog/LICENSE.md
deleted file mode 100644
index 5fc208ff122e08..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/npmlog/LICENSE.md
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-ISC License
-
-Copyright npm, Inc.
-
-Permission to use, copy, modify, and/or distribute this
-software for any purpose with or without fee is hereby
-granted, provided that the above copyright notice and this
-permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND NPM DISCLAIMS ALL
-WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
-EVENT SHALL NPM BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
-USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/deps/npm/node_modules/node-gyp/node_modules/npmlog/lib/log.js b/deps/npm/node_modules/node-gyp/node_modules/npmlog/lib/log.js
deleted file mode 100644
index be650c6a426080..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/npmlog/lib/log.js
+++ /dev/null
@@ -1,404 +0,0 @@
-'use strict'
-var Progress = require('are-we-there-yet')
-var Gauge = require('gauge')
-var EE = require('events').EventEmitter
-var log = exports = module.exports = new EE()
-var util = require('util')
-
-var setBlocking = require('set-blocking')
-var consoleControl = require('console-control-strings')
-
-setBlocking(true)
-var stream = process.stderr
-Object.defineProperty(log, 'stream', {
-  set: function (newStream) {
-    stream = newStream
-    if (this.gauge) {
-      this.gauge.setWriteTo(stream, stream)
-    }
-  },
-  get: function () {
-    return stream
-  },
-})
-
-// by default, decide based on tty-ness.
-var colorEnabled
-log.useColor = function () {
-  return colorEnabled != null ? colorEnabled : stream.isTTY
-}
-
-log.enableColor = function () {
-  colorEnabled = true
-  this.gauge.setTheme({ hasColor: colorEnabled, hasUnicode: unicodeEnabled })
-}
-log.disableColor = function () {
-  colorEnabled = false
-  this.gauge.setTheme({ hasColor: colorEnabled, hasUnicode: unicodeEnabled })
-}
-
-// default level
-log.level = 'info'
-
-log.gauge = new Gauge(stream, {
-  enabled: false, // no progress bars unless asked
-  theme: { hasColor: log.useColor() },
-  template: [
-    { type: 'progressbar', length: 20 },
-    { type: 'activityIndicator', kerning: 1, length: 1 },
-    { type: 'section', default: '' },
-    ':',
-    { type: 'logline', kerning: 1, default: '' },
-  ],
-})
-
-log.tracker = new Progress.TrackerGroup()
-
-// we track this separately as we may need to temporarily disable the
-// display of the status bar for our own loggy purposes.
-log.progressEnabled = log.gauge.isEnabled()
-
-var unicodeEnabled
-
-log.enableUnicode = function () {
-  unicodeEnabled = true
-  this.gauge.setTheme({ hasColor: this.useColor(), hasUnicode: unicodeEnabled })
-}
-
-log.disableUnicode = function () {
-  unicodeEnabled = false
-  this.gauge.setTheme({ hasColor: this.useColor(), hasUnicode: unicodeEnabled })
-}
-
-log.setGaugeThemeset = function (themes) {
-  this.gauge.setThemeset(themes)
-}
-
-log.setGaugeTemplate = function (template) {
-  this.gauge.setTemplate(template)
-}
-
-log.enableProgress = function () {
-  if (this.progressEnabled) {
-    return
-  }
-
-  this.progressEnabled = true
-  this.tracker.on('change', this.showProgress)
-  if (this._paused) {
-    return
-  }
-
-  this.gauge.enable()
-}
-
-log.disableProgress = function () {
-  if (!this.progressEnabled) {
-    return
-  }
-  this.progressEnabled = false
-  this.tracker.removeListener('change', this.showProgress)
-  this.gauge.disable()
-}
-
-var trackerConstructors = ['newGroup', 'newItem', 'newStream']
-
-var mixinLog = function (tracker) {
-  // mixin the public methods from log into the tracker
-  // (except: conflicts and one's we handle specially)
-  Object.keys(log).forEach(function (P) {
-    if (P[0] === '_') {
-      return
-    }
-
-    if (trackerConstructors.filter(function (C) {
-      return C === P
-    }).length) {
-      return
-    }
-
-    if (tracker[P]) {
-      return
-    }
-
-    if (typeof log[P] !== 'function') {
-      return
-    }
-
-    var func = log[P]
-    tracker[P] = function () {
-      return func.apply(log, arguments)
-    }
-  })
-  // if the new tracker is a group, make sure any subtrackers get
-  // mixed in too
-  if (tracker instanceof Progress.TrackerGroup) {
-    trackerConstructors.forEach(function (C) {
-      var func = tracker[C]
-      tracker[C] = function () {
-        return mixinLog(func.apply(tracker, arguments))
-      }
-    })
-  }
-  return tracker
-}
-
-// Add tracker constructors to the top level log object
-trackerConstructors.forEach(function (C) {
-  log[C] = function () {
-    return mixinLog(this.tracker[C].apply(this.tracker, arguments))
-  }
-})
-
-log.clearProgress = function (cb) {
-  if (!this.progressEnabled) {
-    return cb && process.nextTick(cb)
-  }
-
-  this.gauge.hide(cb)
-}
-
-log.showProgress = function (name, completed) {
-  if (!this.progressEnabled) {
-    return
-  }
-
-  var values = {}
-  if (name) {
-    values.section = name
-  }
-
-  var last = log.record[log.record.length - 1]
-  if (last) {
-    values.subsection = last.prefix
-    var disp = log.disp[last.level] || last.level
-    var logline = this._format(disp, log.style[last.level])
-    if (last.prefix) {
-      logline += ' ' + this._format(last.prefix, this.prefixStyle)
-    }
-
-    logline += ' ' + last.message.split(/\r?\n/)[0]
-    values.logline = logline
-  }
-  values.completed = completed || this.tracker.completed()
-  this.gauge.show(values)
-}.bind(log) // bind for use in tracker's on-change listener
-
-// temporarily stop emitting, but don't drop
-log.pause = function () {
-  this._paused = true
-  if (this.progressEnabled) {
-    this.gauge.disable()
-  }
-}
-
-log.resume = function () {
-  if (!this._paused) {
-    return
-  }
-
-  this._paused = false
-
-  var b = this._buffer
-  this._buffer = []
-  b.forEach(function (m) {
-    this.emitLog(m)
-  }, this)
-  if (this.progressEnabled) {
-    this.gauge.enable()
-  }
-}
-
-log._buffer = []
-
-var id = 0
-log.record = []
-log.maxRecordSize = 10000
-log.log = function (lvl, prefix, message) {
-  var l = this.levels[lvl]
-  if (l === undefined) {
-    return this.emit('error', new Error(util.format(
-      'Undefined log level: %j', lvl)))
-  }
-
-  var a = new Array(arguments.length - 2)
-  var stack = null
-  for (var i = 2; i < arguments.length; i++) {
-    var arg = a[i - 2] = arguments[i]
-
-    // resolve stack traces to a plain string.
-    if (typeof arg === 'object' && arg instanceof Error && arg.stack) {
-      Object.defineProperty(arg, 'stack', {
-        value: stack = arg.stack + '',
-        enumerable: true,
-        writable: true,
-      })
-    }
-  }
-  if (stack) {
-    a.unshift(stack + '\n')
-  }
-  message = util.format.apply(util, a)
-
-  var m = {
-    id: id++,
-    level: lvl,
-    prefix: String(prefix || ''),
-    message: message,
-    messageRaw: a,
-  }
-
-  this.emit('log', m)
-  this.emit('log.' + lvl, m)
-  if (m.prefix) {
-    this.emit(m.prefix, m)
-  }
-
-  this.record.push(m)
-  var mrs = this.maxRecordSize
-  var n = this.record.length - mrs
-  if (n > mrs / 10) {
-    var newSize = Math.floor(mrs * 0.9)
-    this.record = this.record.slice(-1 * newSize)
-  }
-
-  this.emitLog(m)
-}.bind(log)
-
-log.emitLog = function (m) {
-  if (this._paused) {
-    this._buffer.push(m)
-    return
-  }
-  if (this.progressEnabled) {
-    this.gauge.pulse(m.prefix)
-  }
-
-  var l = this.levels[m.level]
-  if (l === undefined) {
-    return
-  }
-
-  if (l < this.levels[this.level]) {
-    return
-  }
-
-  if (l > 0 && !isFinite(l)) {
-    return
-  }
-
-  // If 'disp' is null or undefined, use the lvl as a default
-  // Allows: '', 0 as valid disp
-  var disp = log.disp[m.level] != null ? log.disp[m.level] : m.level
-  this.clearProgress()
-  m.message.split(/\r?\n/).forEach(function (line) {
-    var heading = this.heading
-    if (heading) {
-      this.write(heading, this.headingStyle)
-      this.write(' ')
-    }
-    this.write(disp, log.style[m.level])
-    var p = m.prefix || ''
-    if (p) {
-      this.write(' ')
-    }
-
-    this.write(p, this.prefixStyle)
-    this.write(' ' + line + '\n')
-  }, this)
-  this.showProgress()
-}
-
-log._format = function (msg, style) {
-  if (!stream) {
-    return
-  }
-
-  var output = ''
-  if (this.useColor()) {
-    style = style || {}
-    var settings = []
-    if (style.fg) {
-      settings.push(style.fg)
-    }
-
-    if (style.bg) {
-      settings.push('bg' + style.bg[0].toUpperCase() + style.bg.slice(1))
-    }
-
-    if (style.bold) {
-      settings.push('bold')
-    }
-
-    if (style.underline) {
-      settings.push('underline')
-    }
-
-    if (style.inverse) {
-      settings.push('inverse')
-    }
-
-    if (settings.length) {
-      output += consoleControl.color(settings)
-    }
-
-    if (style.beep) {
-      output += consoleControl.beep()
-    }
-  }
-  output += msg
-  if (this.useColor()) {
-    output += consoleControl.color('reset')
-  }
-
-  return output
-}
-
-log.write = function (msg, style) {
-  if (!stream) {
-    return
-  }
-
-  stream.write(this._format(msg, style))
-}
-
-log.addLevel = function (lvl, n, style, disp) {
-  // If 'disp' is null or undefined, use the lvl as a default
-  if (disp == null) {
-    disp = lvl
-  }
-
-  this.levels[lvl] = n
-  this.style[lvl] = style
-  if (!this[lvl]) {
-    this[lvl] = function () {
-      var a = new Array(arguments.length + 1)
-      a[0] = lvl
-      for (var i = 0; i < arguments.length; i++) {
-        a[i + 1] = arguments[i]
-      }
-
-      return this.log.apply(this, a)
-    }.bind(this)
-  }
-  this.disp[lvl] = disp
-}
-
-log.prefixStyle = { fg: 'magenta' }
-log.headingStyle = { fg: 'white', bg: 'black' }
-
-log.style = {}
-log.levels = {}
-log.disp = {}
-log.addLevel('silly', -Infinity, { inverse: true }, 'sill')
-log.addLevel('verbose', 1000, { fg: 'cyan', bg: 'black' }, 'verb')
-log.addLevel('info', 2000, { fg: 'green' })
-log.addLevel('timing', 2500, { fg: 'green', bg: 'black' })
-log.addLevel('http', 3000, { fg: 'green', bg: 'black' })
-log.addLevel('notice', 3500, { fg: 'cyan', bg: 'black' })
-log.addLevel('warn', 4000, { fg: 'black', bg: 'yellow' }, 'WARN')
-log.addLevel('error', 5000, { fg: 'red', bg: 'black' }, 'ERR!')
-log.addLevel('silent', Infinity)
-
-// allow 'error' prefix
-log.on('error', function () {})
diff --git a/deps/npm/node_modules/node-gyp/node_modules/npmlog/package.json b/deps/npm/node_modules/node-gyp/node_modules/npmlog/package.json
deleted file mode 100644
index bdb5a384781ce8..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/npmlog/package.json
+++ /dev/null
@@ -1,51 +0,0 @@
-{
-  "author": "GitHub Inc.",
-  "name": "npmlog",
-  "description": "logger for npm",
-  "version": "6.0.2",
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/npm/npmlog.git"
-  },
-  "main": "lib/log.js",
-  "files": [
-    "bin/",
-    "lib/"
-  ],
-  "scripts": {
-    "test": "tap",
-    "npmclilint": "npmcli-lint",
-    "lint": "eslint \"**/*.js\"",
-    "lintfix": "npm run lint -- --fix",
-    "posttest": "npm run lint",
-    "postsnap": "npm run lintfix --",
-    "postlint": "template-oss-check",
-    "preversion": "npm test",
-    "postversion": "npm publish",
-    "prepublishOnly": "git push origin --follow-tags",
-    "snap": "tap",
-    "template-oss-apply": "template-oss-apply --force"
-  },
-  "dependencies": {
-    "are-we-there-yet": "^3.0.0",
-    "console-control-strings": "^1.1.0",
-    "gauge": "^4.0.3",
-    "set-blocking": "^2.0.0"
-  },
-  "devDependencies": {
-    "@npmcli/eslint-config": "^3.0.1",
-    "@npmcli/template-oss": "3.4.1",
-    "tap": "^16.0.1"
-  },
-  "license": "ISC",
-  "engines": {
-    "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
-  },
-  "tap": {
-    "branches": 95
-  },
-  "templateOSS": {
-    "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
-    "version": "3.4.1"
-  }
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/CONTRIBUTING.md b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/CONTRIBUTING.md
deleted file mode 100644
index f478d58dca85b2..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/CONTRIBUTING.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# Developer's Certificate of Origin 1.1
-
-By making a contribution to this project, I certify that:
-
-* (a) The contribution was created in whole or in part by me and I
-  have the right to submit it under the open source license
-  indicated in the file; or
-
-* (b) The contribution is based upon previous work that, to the best
-  of my knowledge, is covered under an appropriate open source
-  license and I have the right under that license to submit that
-  work with modifications, whether created in whole or in part
-  by me, under the same open source license (unless I am
-  permitted to submit under a different license), as indicated
-  in the file; or
-
-* (c) The contribution was provided directly to me by some other
-  person who certified (a), (b) or (c) and I have not modified
-  it.
-
-* (d) I understand and agree that this project and the contribution
-  are public and that a record of the contribution (including all
-  personal information I submit with it, including my sign-off) is
-  maintained indefinitely and may be redistributed consistent with
-  this project or the open source license(s) involved.
-
-## Moderation Policy
-
-The [Node.js Moderation Policy] applies to this WG.
-
-## Code of Conduct
-
-The [Node.js Code of Conduct][] applies to this WG.
-
-[Node.js Code of Conduct]:
-https://github.com/nodejs/node/blob/master/CODE_OF_CONDUCT.md
-[Node.js Moderation Policy]:
-https://github.com/nodejs/TSC/blob/master/Moderation-Policy.md
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/GOVERNANCE.md b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/GOVERNANCE.md
deleted file mode 100644
index 16ffb93f24bece..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/GOVERNANCE.md
+++ /dev/null
@@ -1,136 +0,0 @@
-### Streams Working Group
-
-The Node.js Streams is jointly governed by a Working Group
-(WG)
-that is responsible for high-level guidance of the project.
-
-The WG has final authority over this project including:
-
-* Technical direction
-* Project governance and process (including this policy)
-* Contribution policy
-* GitHub repository hosting
-* Conduct guidelines
-* Maintaining the list of additional Collaborators
-
-For the current list of WG members, see the project
-[README.md](./README.md#current-project-team-members).
-
-### Collaborators
-
-The readable-stream GitHub repository is
-maintained by the WG and additional Collaborators who are added by the
-WG on an ongoing basis.
-
-Individuals making significant and valuable contributions are made
-Collaborators and given commit-access to the project. These
-individuals are identified by the WG and their addition as
-Collaborators is discussed during the WG meeting.
-
-_Note:_ If you make a significant contribution and are not considered
-for commit-access log an issue or contact a WG member directly and it
-will be brought up in the next WG meeting.
-
-Modifications of the contents of the readable-stream repository are
-made on
-a collaborative basis. Anybody with a GitHub account may propose a
-modification via pull request and it will be considered by the project
-Collaborators. All pull requests must be reviewed and accepted by a
-Collaborator with sufficient expertise who is able to take full
-responsibility for the change. In the case of pull requests proposed
-by an existing Collaborator, an additional Collaborator is required
-for sign-off. Consensus should be sought if additional Collaborators
-participate and there is disagreement around a particular
-modification. See _Consensus Seeking Process_ below for further detail
-on the consensus model used for governance.
-
-Collaborators may opt to elevate significant or controversial
-modifications, or modifications that have not found consensus to the
-WG for discussion by assigning the ***WG-agenda*** tag to a pull
-request or issue. The WG should serve as the final arbiter where
-required.
-
-For the current list of Collaborators, see the project
-[README.md](./README.md#members).
-
-### WG Membership
-
-WG seats are not time-limited.  There is no fixed size of the WG.
-However, the expected target is between 6 and 12, to ensure adequate
-coverage of important areas of expertise, balanced with the ability to
-make decisions efficiently.
-
-There is no specific set of requirements or qualifications for WG
-membership beyond these rules.
-
-The WG may add additional members to the WG by unanimous consensus.
-
-A WG member may be removed from the WG by voluntary resignation, or by
-unanimous consensus of all other WG members.
-
-Changes to WG membership should be posted in the agenda, and may be
-suggested as any other agenda item (see "WG Meetings" below).
-
-If an addition or removal is proposed during a meeting, and the full
-WG is not in attendance to participate, then the addition or removal
-is added to the agenda for the subsequent meeting.  This is to ensure
-that all members are given the opportunity to participate in all
-membership decisions.  If a WG member is unable to attend a meeting
-where a planned membership decision is being made, then their consent
-is assumed.
-
-No more than 1/3 of the WG members may be affiliated with the same
-employer.  If removal or resignation of a WG member, or a change of
-employment by a WG member, creates a situation where more than 1/3 of
-the WG membership shares an employer, then the situation must be
-immediately remedied by the resignation or removal of one or more WG
-members affiliated with the over-represented employer(s).
-
-### WG Meetings
-
-The WG meets occasionally on a Google Hangout On Air. A designated moderator
-approved by the WG runs the meeting. Each meeting should be
-published to YouTube.
-
-Items are added to the WG agenda that are considered contentious or
-are modifications of governance, contribution policy, WG membership,
-or release process.
-
-The intention of the agenda is not to approve or review all patches;
-that should happen continuously on GitHub and be handled by the larger
-group of Collaborators.
-
-Any community member or contributor can ask that something be added to
-the next meeting's agenda by logging a GitHub Issue. Any Collaborator,
-WG member or the moderator can add the item to the agenda by adding
-the ***WG-agenda*** tag to the issue.
-
-Prior to each WG meeting the moderator will share the Agenda with
-members of the WG. WG members can add any items they like to the
-agenda at the beginning of each meeting. The moderator and the WG
-cannot veto or remove items.
-
-The WG may invite persons or representatives from certain projects to
-participate in a non-voting capacity.
-
-The moderator is responsible for summarizing the discussion of each
-agenda item and sends it as a pull request after the meeting.
-
-### Consensus Seeking Process
-
-The WG follows a
-[Consensus
-Seeking](http://en.wikipedia.org/wiki/Consensus-seeking_decision-making)
-decision-making model.
-
-When an agenda item has appeared to reach a consensus the moderator
-will ask "Does anyone object?" as a final call for dissent from the
-consensus.
-
-If an agenda item cannot reach a consensus a WG member can call for
-either a closing vote or a vote to table the issue to the next
-meeting. The call for a vote must be seconded by a majority of the WG
-or else the discussion will continue. Simple majority wins.
-
-Note that changes to WG membership require a majority consensus.  See
-"WG Membership" above.
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/LICENSE b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/LICENSE
deleted file mode 100644
index 2873b3b2e59507..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/LICENSE
+++ /dev/null
@@ -1,47 +0,0 @@
-Node.js is licensed for use as follows:
-
-"""
-Copyright Node.js 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.
-"""
-
-This license applies to parts of Node.js originating from the
-https://github.com/joyent/node repository:
-
-"""
-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.
-"""
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/errors-browser.js b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/errors-browser.js
deleted file mode 100644
index fb8e73e1893b10..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/errors-browser.js
+++ /dev/null
@@ -1,127 +0,0 @@
-'use strict';
-
-function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
-
-var codes = {};
-
-function createErrorType(code, message, Base) {
-  if (!Base) {
-    Base = Error;
-  }
-
-  function getMessage(arg1, arg2, arg3) {
-    if (typeof message === 'string') {
-      return message;
-    } else {
-      return message(arg1, arg2, arg3);
-    }
-  }
-
-  var NodeError =
-  /*#__PURE__*/
-  function (_Base) {
-    _inheritsLoose(NodeError, _Base);
-
-    function NodeError(arg1, arg2, arg3) {
-      return _Base.call(this, getMessage(arg1, arg2, arg3)) || this;
-    }
-
-    return NodeError;
-  }(Base);
-
-  NodeError.prototype.name = Base.name;
-  NodeError.prototype.code = code;
-  codes[code] = NodeError;
-} // https://github.com/nodejs/node/blob/v10.8.0/lib/internal/errors.js
-
-
-function oneOf(expected, thing) {
-  if (Array.isArray(expected)) {
-    var len = expected.length;
-    expected = expected.map(function (i) {
-      return String(i);
-    });
-
-    if (len > 2) {
-      return "one of ".concat(thing, " ").concat(expected.slice(0, len - 1).join(', '), ", or ") + expected[len - 1];
-    } else if (len === 2) {
-      return "one of ".concat(thing, " ").concat(expected[0], " or ").concat(expected[1]);
-    } else {
-      return "of ".concat(thing, " ").concat(expected[0]);
-    }
-  } else {
-    return "of ".concat(thing, " ").concat(String(expected));
-  }
-} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
-
-
-function startsWith(str, search, pos) {
-  return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search;
-} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
-
-
-function endsWith(str, search, this_len) {
-  if (this_len === undefined || this_len > str.length) {
-    this_len = str.length;
-  }
-
-  return str.substring(this_len - search.length, this_len) === search;
-} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes
-
-
-function includes(str, search, start) {
-  if (typeof start !== 'number') {
-    start = 0;
-  }
-
-  if (start + search.length > str.length) {
-    return false;
-  } else {
-    return str.indexOf(search, start) !== -1;
-  }
-}
-
-createErrorType('ERR_INVALID_OPT_VALUE', function (name, value) {
-  return 'The value "' + value + '" is invalid for option "' + name + '"';
-}, TypeError);
-createErrorType('ERR_INVALID_ARG_TYPE', function (name, expected, actual) {
-  // determiner: 'must be' or 'must not be'
-  var determiner;
-
-  if (typeof expected === 'string' && startsWith(expected, 'not ')) {
-    determiner = 'must not be';
-    expected = expected.replace(/^not /, '');
-  } else {
-    determiner = 'must be';
-  }
-
-  var msg;
-
-  if (endsWith(name, ' argument')) {
-    // For cases like 'first argument'
-    msg = "The ".concat(name, " ").concat(determiner, " ").concat(oneOf(expected, 'type'));
-  } else {
-    var type = includes(name, '.') ? 'property' : 'argument';
-    msg = "The \"".concat(name, "\" ").concat(type, " ").concat(determiner, " ").concat(oneOf(expected, 'type'));
-  }
-
-  msg += ". Received type ".concat(typeof actual);
-  return msg;
-}, TypeError);
-createErrorType('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF');
-createErrorType('ERR_METHOD_NOT_IMPLEMENTED', function (name) {
-  return 'The ' + name + ' method is not implemented';
-});
-createErrorType('ERR_STREAM_PREMATURE_CLOSE', 'Premature close');
-createErrorType('ERR_STREAM_DESTROYED', function (name) {
-  return 'Cannot call ' + name + ' after a stream was destroyed';
-});
-createErrorType('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times');
-createErrorType('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable');
-createErrorType('ERR_STREAM_WRITE_AFTER_END', 'write after end');
-createErrorType('ERR_STREAM_NULL_VALUES', 'May not write null values to stream', TypeError);
-createErrorType('ERR_UNKNOWN_ENCODING', function (arg) {
-  return 'Unknown encoding: ' + arg;
-}, TypeError);
-createErrorType('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', 'stream.unshift() after end event');
-module.exports.codes = codes;
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/errors.js b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/errors.js
deleted file mode 100644
index 8471526d6e7f75..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/errors.js
+++ /dev/null
@@ -1,116 +0,0 @@
-'use strict';
-
-const codes = {};
-
-function createErrorType(code, message, Base) {
-  if (!Base) {
-    Base = Error
-  }
-
-  function getMessage (arg1, arg2, arg3) {
-    if (typeof message === 'string') {
-      return message
-    } else {
-      return message(arg1, arg2, arg3)
-    }
-  }
-
-  class NodeError extends Base {
-    constructor (arg1, arg2, arg3) {
-      super(getMessage(arg1, arg2, arg3));
-    }
-  }
-
-  NodeError.prototype.name = Base.name;
-  NodeError.prototype.code = code;
-
-  codes[code] = NodeError;
-}
-
-// https://github.com/nodejs/node/blob/v10.8.0/lib/internal/errors.js
-function oneOf(expected, thing) {
-  if (Array.isArray(expected)) {
-    const len = expected.length;
-    expected = expected.map((i) => String(i));
-    if (len > 2) {
-      return `one of ${thing} ${expected.slice(0, len - 1).join(', ')}, or ` +
-             expected[len - 1];
-    } else if (len === 2) {
-      return `one of ${thing} ${expected[0]} or ${expected[1]}`;
-    } else {
-      return `of ${thing} ${expected[0]}`;
-    }
-  } else {
-    return `of ${thing} ${String(expected)}`;
-  }
-}
-
-// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
-function startsWith(str, search, pos) {
-	return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search;
-}
-
-// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
-function endsWith(str, search, this_len) {
-	if (this_len === undefined || this_len > str.length) {
-		this_len = str.length;
-	}
-	return str.substring(this_len - search.length, this_len) === search;
-}
-
-// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes
-function includes(str, search, start) {
-  if (typeof start !== 'number') {
-    start = 0;
-  }
-
-  if (start + search.length > str.length) {
-    return false;
-  } else {
-    return str.indexOf(search, start) !== -1;
-  }
-}
-
-createErrorType('ERR_INVALID_OPT_VALUE', function (name, value) {
-  return 'The value "' + value + '" is invalid for option "' + name + '"'
-}, TypeError);
-createErrorType('ERR_INVALID_ARG_TYPE', function (name, expected, actual) {
-  // determiner: 'must be' or 'must not be'
-  let determiner;
-  if (typeof expected === 'string' && startsWith(expected, 'not ')) {
-    determiner = 'must not be';
-    expected = expected.replace(/^not /, '');
-  } else {
-    determiner = 'must be';
-  }
-
-  let msg;
-  if (endsWith(name, ' argument')) {
-    // For cases like 'first argument'
-    msg = `The ${name} ${determiner} ${oneOf(expected, 'type')}`;
-  } else {
-    const type = includes(name, '.') ? 'property' : 'argument';
-    msg = `The "${name}" ${type} ${determiner} ${oneOf(expected, 'type')}`;
-  }
-
-  msg += `. Received type ${typeof actual}`;
-  return msg;
-}, TypeError);
-createErrorType('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF');
-createErrorType('ERR_METHOD_NOT_IMPLEMENTED', function (name) {
-  return 'The ' + name + ' method is not implemented'
-});
-createErrorType('ERR_STREAM_PREMATURE_CLOSE', 'Premature close');
-createErrorType('ERR_STREAM_DESTROYED', function (name) {
-  return 'Cannot call ' + name + ' after a stream was destroyed';
-});
-createErrorType('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times');
-createErrorType('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable');
-createErrorType('ERR_STREAM_WRITE_AFTER_END', 'write after end');
-createErrorType('ERR_STREAM_NULL_VALUES', 'May not write null values to stream', TypeError);
-createErrorType('ERR_UNKNOWN_ENCODING', function (arg) {
-  return 'Unknown encoding: ' + arg
-}, TypeError);
-createErrorType('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', 'stream.unshift() after end event');
-
-module.exports.codes = codes;
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/experimentalWarning.js b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/experimentalWarning.js
deleted file mode 100644
index 78e841495bf24d..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/experimentalWarning.js
+++ /dev/null
@@ -1,17 +0,0 @@
-'use strict'
-
-var experimentalWarnings = new Set();
-
-function emitExperimentalWarning(feature) {
-  if (experimentalWarnings.has(feature)) return;
-  var msg = feature + ' is an experimental feature. This feature could ' +
-       'change at any time';
-  experimentalWarnings.add(feature);
-  process.emitWarning(msg, 'ExperimentalWarning');
-}
-
-function noop() {}
-
-module.exports.emitExperimentalWarning = process.emitWarning
-  ? emitExperimentalWarning
-  : noop;
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/_stream_duplex.js b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/_stream_duplex.js
deleted file mode 100644
index 19abfa604d5ef7..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/_stream_duplex.js
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// 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.
-
-// a duplex stream is just a stream that is both readable and writable.
-// Since JS doesn't have multiple prototypal inheritance, this class
-// prototypally inherits from Readable, and then parasitically from
-// Writable.
-
-'use strict';
-
-/**/
-var objectKeys = Object.keys || function (obj) {
-  var keys = [];
-  for (var key in obj) keys.push(key);
-  return keys;
-};
-/**/
-
-module.exports = Duplex;
-var Readable = require('./_stream_readable');
-var Writable = require('./_stream_writable');
-require('inherits')(Duplex, Readable);
-{
-  // Allow the keys array to be GC'ed.
-  var keys = objectKeys(Writable.prototype);
-  for (var v = 0; v < keys.length; v++) {
-    var method = keys[v];
-    if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method];
-  }
-}
-function Duplex(options) {
-  if (!(this instanceof Duplex)) return new Duplex(options);
-  Readable.call(this, options);
-  Writable.call(this, options);
-  this.allowHalfOpen = true;
-  if (options) {
-    if (options.readable === false) this.readable = false;
-    if (options.writable === false) this.writable = false;
-    if (options.allowHalfOpen === false) {
-      this.allowHalfOpen = false;
-      this.once('end', onend);
-    }
-  }
-}
-Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', {
-  // making it explicit this property is not enumerable
-  // because otherwise some prototype manipulation in
-  // userland will fail
-  enumerable: false,
-  get: function get() {
-    return this._writableState.highWaterMark;
-  }
-});
-Object.defineProperty(Duplex.prototype, 'writableBuffer', {
-  // making it explicit this property is not enumerable
-  // because otherwise some prototype manipulation in
-  // userland will fail
-  enumerable: false,
-  get: function get() {
-    return this._writableState && this._writableState.getBuffer();
-  }
-});
-Object.defineProperty(Duplex.prototype, 'writableLength', {
-  // making it explicit this property is not enumerable
-  // because otherwise some prototype manipulation in
-  // userland will fail
-  enumerable: false,
-  get: function get() {
-    return this._writableState.length;
-  }
-});
-
-// the no-half-open enforcer
-function onend() {
-  // If the writable side ended, then we're ok.
-  if (this._writableState.ended) return;
-
-  // no more data can be written.
-  // But allow more writes to happen in this tick.
-  process.nextTick(onEndNT, this);
-}
-function onEndNT(self) {
-  self.end();
-}
-Object.defineProperty(Duplex.prototype, 'destroyed', {
-  // making it explicit this property is not enumerable
-  // because otherwise some prototype manipulation in
-  // userland will fail
-  enumerable: false,
-  get: function get() {
-    if (this._readableState === undefined || this._writableState === undefined) {
-      return false;
-    }
-    return this._readableState.destroyed && this._writableState.destroyed;
-  },
-  set: function set(value) {
-    // we ignore the value if the stream
-    // has not been initialized yet
-    if (this._readableState === undefined || this._writableState === undefined) {
-      return;
-    }
-
-    // backward compatibility, the user is explicitly
-    // managing destroyed
-    this._readableState.destroyed = value;
-    this._writableState.destroyed = value;
-  }
-});
\ No newline at end of file
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/_stream_passthrough.js b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/_stream_passthrough.js
deleted file mode 100644
index 24a6bdde2903fa..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/_stream_passthrough.js
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// 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.
-
-// a passthrough stream.
-// basically just the most minimal sort of Transform stream.
-// Every written chunk gets output as-is.
-
-'use strict';
-
-module.exports = PassThrough;
-var Transform = require('./_stream_transform');
-require('inherits')(PassThrough, Transform);
-function PassThrough(options) {
-  if (!(this instanceof PassThrough)) return new PassThrough(options);
-  Transform.call(this, options);
-}
-PassThrough.prototype._transform = function (chunk, encoding, cb) {
-  cb(null, chunk);
-};
\ No newline at end of file
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/_stream_readable.js b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/_stream_readable.js
deleted file mode 100644
index df1f608d532606..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/_stream_readable.js
+++ /dev/null
@@ -1,1027 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// 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.
-
-'use strict';
-
-module.exports = Readable;
-
-/**/
-var Duplex;
-/**/
-
-Readable.ReadableState = ReadableState;
-
-/**/
-var EE = require('events').EventEmitter;
-var EElistenerCount = function EElistenerCount(emitter, type) {
-  return emitter.listeners(type).length;
-};
-/**/
-
-/**/
-var Stream = require('./internal/streams/stream');
-/**/
-
-var Buffer = require('buffer').Buffer;
-var OurUint8Array = (typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : typeof self !== 'undefined' ? self : {}).Uint8Array || function () {};
-function _uint8ArrayToBuffer(chunk) {
-  return Buffer.from(chunk);
-}
-function _isUint8Array(obj) {
-  return Buffer.isBuffer(obj) || obj instanceof OurUint8Array;
-}
-
-/**/
-var debugUtil = require('util');
-var debug;
-if (debugUtil && debugUtil.debuglog) {
-  debug = debugUtil.debuglog('stream');
-} else {
-  debug = function debug() {};
-}
-/**/
-
-var BufferList = require('./internal/streams/buffer_list');
-var destroyImpl = require('./internal/streams/destroy');
-var _require = require('./internal/streams/state'),
-  getHighWaterMark = _require.getHighWaterMark;
-var _require$codes = require('../errors').codes,
-  ERR_INVALID_ARG_TYPE = _require$codes.ERR_INVALID_ARG_TYPE,
-  ERR_STREAM_PUSH_AFTER_EOF = _require$codes.ERR_STREAM_PUSH_AFTER_EOF,
-  ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED,
-  ERR_STREAM_UNSHIFT_AFTER_END_EVENT = _require$codes.ERR_STREAM_UNSHIFT_AFTER_END_EVENT;
-
-// Lazy loaded to improve the startup performance.
-var StringDecoder;
-var createReadableStreamAsyncIterator;
-var from;
-require('inherits')(Readable, Stream);
-var errorOrDestroy = destroyImpl.errorOrDestroy;
-var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume'];
-function prependListener(emitter, event, fn) {
-  // Sadly this is not cacheable as some libraries bundle their own
-  // event emitter implementation with them.
-  if (typeof emitter.prependListener === 'function') return emitter.prependListener(event, fn);
-
-  // This is a hack to make sure that our error handler is attached before any
-  // userland ones.  NEVER DO THIS. This is here only because this code needs
-  // to continue to work with older versions of Node.js that do not include
-  // the prependListener() method. The goal is to eventually remove this hack.
-  if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (Array.isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]];
-}
-function ReadableState(options, stream, isDuplex) {
-  Duplex = Duplex || require('./_stream_duplex');
-  options = options || {};
-
-  // Duplex streams are both readable and writable, but share
-  // the same options object.
-  // However, some cases require setting options to different
-  // values for the readable and the writable sides of the duplex stream.
-  // These options can be provided separately as readableXXX and writableXXX.
-  if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof Duplex;
-
-  // object stream flag. Used to make read(n) ignore n and to
-  // make all the buffer merging and length checks go away
-  this.objectMode = !!options.objectMode;
-  if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode;
-
-  // the point at which it stops calling _read() to fill the buffer
-  // Note: 0 is a valid value, means "don't call _read preemptively ever"
-  this.highWaterMark = getHighWaterMark(this, options, 'readableHighWaterMark', isDuplex);
-
-  // A linked list is used to store data chunks instead of an array because the
-  // linked list can remove elements from the beginning faster than
-  // array.shift()
-  this.buffer = new BufferList();
-  this.length = 0;
-  this.pipes = null;
-  this.pipesCount = 0;
-  this.flowing = null;
-  this.ended = false;
-  this.endEmitted = false;
-  this.reading = false;
-
-  // a flag to be able to tell if the event 'readable'/'data' is emitted
-  // immediately, or on a later tick.  We set this to true at first, because
-  // any actions that shouldn't happen until "later" should generally also
-  // not happen before the first read call.
-  this.sync = true;
-
-  // whenever we return null, then we set a flag to say
-  // that we're awaiting a 'readable' event emission.
-  this.needReadable = false;
-  this.emittedReadable = false;
-  this.readableListening = false;
-  this.resumeScheduled = false;
-  this.paused = true;
-
-  // Should close be emitted on destroy. Defaults to true.
-  this.emitClose = options.emitClose !== false;
-
-  // Should .destroy() be called after 'end' (and potentially 'finish')
-  this.autoDestroy = !!options.autoDestroy;
-
-  // has it been destroyed
-  this.destroyed = false;
-
-  // Crypto is kind of old and crusty.  Historically, its default string
-  // encoding is 'binary' so we have to make this configurable.
-  // Everything else in the universe uses 'utf8', though.
-  this.defaultEncoding = options.defaultEncoding || 'utf8';
-
-  // the number of writers that are awaiting a drain event in .pipe()s
-  this.awaitDrain = 0;
-
-  // if true, a maybeReadMore has been scheduled
-  this.readingMore = false;
-  this.decoder = null;
-  this.encoding = null;
-  if (options.encoding) {
-    if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder;
-    this.decoder = new StringDecoder(options.encoding);
-    this.encoding = options.encoding;
-  }
-}
-function Readable(options) {
-  Duplex = Duplex || require('./_stream_duplex');
-  if (!(this instanceof Readable)) return new Readable(options);
-
-  // Checking for a Stream.Duplex instance is faster here instead of inside
-  // the ReadableState constructor, at least with V8 6.5
-  var isDuplex = this instanceof Duplex;
-  this._readableState = new ReadableState(options, this, isDuplex);
-
-  // legacy
-  this.readable = true;
-  if (options) {
-    if (typeof options.read === 'function') this._read = options.read;
-    if (typeof options.destroy === 'function') this._destroy = options.destroy;
-  }
-  Stream.call(this);
-}
-Object.defineProperty(Readable.prototype, 'destroyed', {
-  // making it explicit this property is not enumerable
-  // because otherwise some prototype manipulation in
-  // userland will fail
-  enumerable: false,
-  get: function get() {
-    if (this._readableState === undefined) {
-      return false;
-    }
-    return this._readableState.destroyed;
-  },
-  set: function set(value) {
-    // we ignore the value if the stream
-    // has not been initialized yet
-    if (!this._readableState) {
-      return;
-    }
-
-    // backward compatibility, the user is explicitly
-    // managing destroyed
-    this._readableState.destroyed = value;
-  }
-});
-Readable.prototype.destroy = destroyImpl.destroy;
-Readable.prototype._undestroy = destroyImpl.undestroy;
-Readable.prototype._destroy = function (err, cb) {
-  cb(err);
-};
-
-// Manually shove something into the read() buffer.
-// This returns true if the highWaterMark has not been hit yet,
-// similar to how Writable.write() returns true if you should
-// write() some more.
-Readable.prototype.push = function (chunk, encoding) {
-  var state = this._readableState;
-  var skipChunkCheck;
-  if (!state.objectMode) {
-    if (typeof chunk === 'string') {
-      encoding = encoding || state.defaultEncoding;
-      if (encoding !== state.encoding) {
-        chunk = Buffer.from(chunk, encoding);
-        encoding = '';
-      }
-      skipChunkCheck = true;
-    }
-  } else {
-    skipChunkCheck = true;
-  }
-  return readableAddChunk(this, chunk, encoding, false, skipChunkCheck);
-};
-
-// Unshift should *always* be something directly out of read()
-Readable.prototype.unshift = function (chunk) {
-  return readableAddChunk(this, chunk, null, true, false);
-};
-function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) {
-  debug('readableAddChunk', chunk);
-  var state = stream._readableState;
-  if (chunk === null) {
-    state.reading = false;
-    onEofChunk(stream, state);
-  } else {
-    var er;
-    if (!skipChunkCheck) er = chunkInvalid(state, chunk);
-    if (er) {
-      errorOrDestroy(stream, er);
-    } else if (state.objectMode || chunk && chunk.length > 0) {
-      if (typeof chunk !== 'string' && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer.prototype) {
-        chunk = _uint8ArrayToBuffer(chunk);
-      }
-      if (addToFront) {
-        if (state.endEmitted) errorOrDestroy(stream, new ERR_STREAM_UNSHIFT_AFTER_END_EVENT());else addChunk(stream, state, chunk, true);
-      } else if (state.ended) {
-        errorOrDestroy(stream, new ERR_STREAM_PUSH_AFTER_EOF());
-      } else if (state.destroyed) {
-        return false;
-      } else {
-        state.reading = false;
-        if (state.decoder && !encoding) {
-          chunk = state.decoder.write(chunk);
-          if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);else maybeReadMore(stream, state);
-        } else {
-          addChunk(stream, state, chunk, false);
-        }
-      }
-    } else if (!addToFront) {
-      state.reading = false;
-      maybeReadMore(stream, state);
-    }
-  }
-
-  // We can push more data if we are below the highWaterMark.
-  // Also, if we have no data yet, we can stand some more bytes.
-  // This is to work around cases where hwm=0, such as the repl.
-  return !state.ended && (state.length < state.highWaterMark || state.length === 0);
-}
-function addChunk(stream, state, chunk, addToFront) {
-  if (state.flowing && state.length === 0 && !state.sync) {
-    state.awaitDrain = 0;
-    stream.emit('data', chunk);
-  } else {
-    // update the buffer info.
-    state.length += state.objectMode ? 1 : chunk.length;
-    if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk);
-    if (state.needReadable) emitReadable(stream);
-  }
-  maybeReadMore(stream, state);
-}
-function chunkInvalid(state, chunk) {
-  var er;
-  if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) {
-    er = new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer', 'Uint8Array'], chunk);
-  }
-  return er;
-}
-Readable.prototype.isPaused = function () {
-  return this._readableState.flowing === false;
-};
-
-// backwards compatibility.
-Readable.prototype.setEncoding = function (enc) {
-  if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder;
-  var decoder = new StringDecoder(enc);
-  this._readableState.decoder = decoder;
-  // If setEncoding(null), decoder.encoding equals utf8
-  this._readableState.encoding = this._readableState.decoder.encoding;
-
-  // Iterate over current buffer to convert already stored Buffers:
-  var p = this._readableState.buffer.head;
-  var content = '';
-  while (p !== null) {
-    content += decoder.write(p.data);
-    p = p.next;
-  }
-  this._readableState.buffer.clear();
-  if (content !== '') this._readableState.buffer.push(content);
-  this._readableState.length = content.length;
-  return this;
-};
-
-// Don't raise the hwm > 1GB
-var MAX_HWM = 0x40000000;
-function computeNewHighWaterMark(n) {
-  if (n >= MAX_HWM) {
-    // TODO(ronag): Throw ERR_VALUE_OUT_OF_RANGE.
-    n = MAX_HWM;
-  } else {
-    // Get the next highest power of 2 to prevent increasing hwm excessively in
-    // tiny amounts
-    n--;
-    n |= n >>> 1;
-    n |= n >>> 2;
-    n |= n >>> 4;
-    n |= n >>> 8;
-    n |= n >>> 16;
-    n++;
-  }
-  return n;
-}
-
-// This function is designed to be inlinable, so please take care when making
-// changes to the function body.
-function howMuchToRead(n, state) {
-  if (n <= 0 || state.length === 0 && state.ended) return 0;
-  if (state.objectMode) return 1;
-  if (n !== n) {
-    // Only flow one buffer at a time
-    if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length;
-  }
-  // If we're asking for more than the current hwm, then raise the hwm.
-  if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n);
-  if (n <= state.length) return n;
-  // Don't have enough
-  if (!state.ended) {
-    state.needReadable = true;
-    return 0;
-  }
-  return state.length;
-}
-
-// you can override either this method, or the async _read(n) below.
-Readable.prototype.read = function (n) {
-  debug('read', n);
-  n = parseInt(n, 10);
-  var state = this._readableState;
-  var nOrig = n;
-  if (n !== 0) state.emittedReadable = false;
-
-  // if we're doing read(0) to trigger a readable event, but we
-  // already have a bunch of data in the buffer, then just trigger
-  // the 'readable' event and move on.
-  if (n === 0 && state.needReadable && ((state.highWaterMark !== 0 ? state.length >= state.highWaterMark : state.length > 0) || state.ended)) {
-    debug('read: emitReadable', state.length, state.ended);
-    if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this);
-    return null;
-  }
-  n = howMuchToRead(n, state);
-
-  // if we've ended, and we're now clear, then finish it up.
-  if (n === 0 && state.ended) {
-    if (state.length === 0) endReadable(this);
-    return null;
-  }
-
-  // All the actual chunk generation logic needs to be
-  // *below* the call to _read.  The reason is that in certain
-  // synthetic stream cases, such as passthrough streams, _read
-  // may be a completely synchronous operation which may change
-  // the state of the read buffer, providing enough data when
-  // before there was *not* enough.
-  //
-  // So, the steps are:
-  // 1. Figure out what the state of things will be after we do
-  // a read from the buffer.
-  //
-  // 2. If that resulting state will trigger a _read, then call _read.
-  // Note that this may be asynchronous, or synchronous.  Yes, it is
-  // deeply ugly to write APIs this way, but that still doesn't mean
-  // that the Readable class should behave improperly, as streams are
-  // designed to be sync/async agnostic.
-  // Take note if the _read call is sync or async (ie, if the read call
-  // has returned yet), so that we know whether or not it's safe to emit
-  // 'readable' etc.
-  //
-  // 3. Actually pull the requested chunks out of the buffer and return.
-
-  // if we need a readable event, then we need to do some reading.
-  var doRead = state.needReadable;
-  debug('need readable', doRead);
-
-  // if we currently have less than the highWaterMark, then also read some
-  if (state.length === 0 || state.length - n < state.highWaterMark) {
-    doRead = true;
-    debug('length less than watermark', doRead);
-  }
-
-  // however, if we've ended, then there's no point, and if we're already
-  // reading, then it's unnecessary.
-  if (state.ended || state.reading) {
-    doRead = false;
-    debug('reading or ended', doRead);
-  } else if (doRead) {
-    debug('do read');
-    state.reading = true;
-    state.sync = true;
-    // if the length is currently zero, then we *need* a readable event.
-    if (state.length === 0) state.needReadable = true;
-    // call internal read method
-    this._read(state.highWaterMark);
-    state.sync = false;
-    // If _read pushed data synchronously, then `reading` will be false,
-    // and we need to re-evaluate how much data we can return to the user.
-    if (!state.reading) n = howMuchToRead(nOrig, state);
-  }
-  var ret;
-  if (n > 0) ret = fromList(n, state);else ret = null;
-  if (ret === null) {
-    state.needReadable = state.length <= state.highWaterMark;
-    n = 0;
-  } else {
-    state.length -= n;
-    state.awaitDrain = 0;
-  }
-  if (state.length === 0) {
-    // If we have nothing in the buffer, then we want to know
-    // as soon as we *do* get something into the buffer.
-    if (!state.ended) state.needReadable = true;
-
-    // If we tried to read() past the EOF, then emit end on the next tick.
-    if (nOrig !== n && state.ended) endReadable(this);
-  }
-  if (ret !== null) this.emit('data', ret);
-  return ret;
-};
-function onEofChunk(stream, state) {
-  debug('onEofChunk');
-  if (state.ended) return;
-  if (state.decoder) {
-    var chunk = state.decoder.end();
-    if (chunk && chunk.length) {
-      state.buffer.push(chunk);
-      state.length += state.objectMode ? 1 : chunk.length;
-    }
-  }
-  state.ended = true;
-  if (state.sync) {
-    // if we are sync, wait until next tick to emit the data.
-    // Otherwise we risk emitting data in the flow()
-    // the readable code triggers during a read() call
-    emitReadable(stream);
-  } else {
-    // emit 'readable' now to make sure it gets picked up.
-    state.needReadable = false;
-    if (!state.emittedReadable) {
-      state.emittedReadable = true;
-      emitReadable_(stream);
-    }
-  }
-}
-
-// Don't emit readable right away in sync mode, because this can trigger
-// another read() call => stack overflow.  This way, it might trigger
-// a nextTick recursion warning, but that's not so bad.
-function emitReadable(stream) {
-  var state = stream._readableState;
-  debug('emitReadable', state.needReadable, state.emittedReadable);
-  state.needReadable = false;
-  if (!state.emittedReadable) {
-    debug('emitReadable', state.flowing);
-    state.emittedReadable = true;
-    process.nextTick(emitReadable_, stream);
-  }
-}
-function emitReadable_(stream) {
-  var state = stream._readableState;
-  debug('emitReadable_', state.destroyed, state.length, state.ended);
-  if (!state.destroyed && (state.length || state.ended)) {
-    stream.emit('readable');
-    state.emittedReadable = false;
-  }
-
-  // The stream needs another readable event if
-  // 1. It is not flowing, as the flow mechanism will take
-  //    care of it.
-  // 2. It is not ended.
-  // 3. It is below the highWaterMark, so we can schedule
-  //    another readable later.
-  state.needReadable = !state.flowing && !state.ended && state.length <= state.highWaterMark;
-  flow(stream);
-}
-
-// at this point, the user has presumably seen the 'readable' event,
-// and called read() to consume some data.  that may have triggered
-// in turn another _read(n) call, in which case reading = true if
-// it's in progress.
-// However, if we're not ended, or reading, and the length < hwm,
-// then go ahead and try to read some more preemptively.
-function maybeReadMore(stream, state) {
-  if (!state.readingMore) {
-    state.readingMore = true;
-    process.nextTick(maybeReadMore_, stream, state);
-  }
-}
-function maybeReadMore_(stream, state) {
-  // Attempt to read more data if we should.
-  //
-  // The conditions for reading more data are (one of):
-  // - Not enough data buffered (state.length < state.highWaterMark). The loop
-  //   is responsible for filling the buffer with enough data if such data
-  //   is available. If highWaterMark is 0 and we are not in the flowing mode
-  //   we should _not_ attempt to buffer any extra data. We'll get more data
-  //   when the stream consumer calls read() instead.
-  // - No data in the buffer, and the stream is in flowing mode. In this mode
-  //   the loop below is responsible for ensuring read() is called. Failing to
-  //   call read here would abort the flow and there's no other mechanism for
-  //   continuing the flow if the stream consumer has just subscribed to the
-  //   'data' event.
-  //
-  // In addition to the above conditions to keep reading data, the following
-  // conditions prevent the data from being read:
-  // - The stream has ended (state.ended).
-  // - There is already a pending 'read' operation (state.reading). This is a
-  //   case where the the stream has called the implementation defined _read()
-  //   method, but they are processing the call asynchronously and have _not_
-  //   called push() with new data. In this case we skip performing more
-  //   read()s. The execution ends in this method again after the _read() ends
-  //   up calling push() with more data.
-  while (!state.reading && !state.ended && (state.length < state.highWaterMark || state.flowing && state.length === 0)) {
-    var len = state.length;
-    debug('maybeReadMore read 0');
-    stream.read(0);
-    if (len === state.length)
-      // didn't get any data, stop spinning.
-      break;
-  }
-  state.readingMore = false;
-}
-
-// abstract method.  to be overridden in specific implementation classes.
-// call cb(er, data) where data is <= n in length.
-// for virtual (non-string, non-buffer) streams, "length" is somewhat
-// arbitrary, and perhaps not very meaningful.
-Readable.prototype._read = function (n) {
-  errorOrDestroy(this, new ERR_METHOD_NOT_IMPLEMENTED('_read()'));
-};
-Readable.prototype.pipe = function (dest, pipeOpts) {
-  var src = this;
-  var state = this._readableState;
-  switch (state.pipesCount) {
-    case 0:
-      state.pipes = dest;
-      break;
-    case 1:
-      state.pipes = [state.pipes, dest];
-      break;
-    default:
-      state.pipes.push(dest);
-      break;
-  }
-  state.pipesCount += 1;
-  debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts);
-  var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr;
-  var endFn = doEnd ? onend : unpipe;
-  if (state.endEmitted) process.nextTick(endFn);else src.once('end', endFn);
-  dest.on('unpipe', onunpipe);
-  function onunpipe(readable, unpipeInfo) {
-    debug('onunpipe');
-    if (readable === src) {
-      if (unpipeInfo && unpipeInfo.hasUnpiped === false) {
-        unpipeInfo.hasUnpiped = true;
-        cleanup();
-      }
-    }
-  }
-  function onend() {
-    debug('onend');
-    dest.end();
-  }
-
-  // when the dest drains, it reduces the awaitDrain counter
-  // on the source.  This would be more elegant with a .once()
-  // handler in flow(), but adding and removing repeatedly is
-  // too slow.
-  var ondrain = pipeOnDrain(src);
-  dest.on('drain', ondrain);
-  var cleanedUp = false;
-  function cleanup() {
-    debug('cleanup');
-    // cleanup event handlers once the pipe is broken
-    dest.removeListener('close', onclose);
-    dest.removeListener('finish', onfinish);
-    dest.removeListener('drain', ondrain);
-    dest.removeListener('error', onerror);
-    dest.removeListener('unpipe', onunpipe);
-    src.removeListener('end', onend);
-    src.removeListener('end', unpipe);
-    src.removeListener('data', ondata);
-    cleanedUp = true;
-
-    // if the reader is waiting for a drain event from this
-    // specific writer, then it would cause it to never start
-    // flowing again.
-    // So, if this is awaiting a drain, then we just call it now.
-    // If we don't know, then assume that we are waiting for one.
-    if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain();
-  }
-  src.on('data', ondata);
-  function ondata(chunk) {
-    debug('ondata');
-    var ret = dest.write(chunk);
-    debug('dest.write', ret);
-    if (ret === false) {
-      // If the user unpiped during `dest.write()`, it is possible
-      // to get stuck in a permanently paused state if that write
-      // also returned false.
-      // => Check whether `dest` is still a piping destination.
-      if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) {
-        debug('false write response, pause', state.awaitDrain);
-        state.awaitDrain++;
-      }
-      src.pause();
-    }
-  }
-
-  // if the dest has an error, then stop piping into it.
-  // however, don't suppress the throwing behavior for this.
-  function onerror(er) {
-    debug('onerror', er);
-    unpipe();
-    dest.removeListener('error', onerror);
-    if (EElistenerCount(dest, 'error') === 0) errorOrDestroy(dest, er);
-  }
-
-  // Make sure our error handler is attached before userland ones.
-  prependListener(dest, 'error', onerror);
-
-  // Both close and finish should trigger unpipe, but only once.
-  function onclose() {
-    dest.removeListener('finish', onfinish);
-    unpipe();
-  }
-  dest.once('close', onclose);
-  function onfinish() {
-    debug('onfinish');
-    dest.removeListener('close', onclose);
-    unpipe();
-  }
-  dest.once('finish', onfinish);
-  function unpipe() {
-    debug('unpipe');
-    src.unpipe(dest);
-  }
-
-  // tell the dest that it's being piped to
-  dest.emit('pipe', src);
-
-  // start the flow if it hasn't been started already.
-  if (!state.flowing) {
-    debug('pipe resume');
-    src.resume();
-  }
-  return dest;
-};
-function pipeOnDrain(src) {
-  return function pipeOnDrainFunctionResult() {
-    var state = src._readableState;
-    debug('pipeOnDrain', state.awaitDrain);
-    if (state.awaitDrain) state.awaitDrain--;
-    if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) {
-      state.flowing = true;
-      flow(src);
-    }
-  };
-}
-Readable.prototype.unpipe = function (dest) {
-  var state = this._readableState;
-  var unpipeInfo = {
-    hasUnpiped: false
-  };
-
-  // if we're not piping anywhere, then do nothing.
-  if (state.pipesCount === 0) return this;
-
-  // just one destination.  most common case.
-  if (state.pipesCount === 1) {
-    // passed in one, but it's not the right one.
-    if (dest && dest !== state.pipes) return this;
-    if (!dest) dest = state.pipes;
-
-    // got a match.
-    state.pipes = null;
-    state.pipesCount = 0;
-    state.flowing = false;
-    if (dest) dest.emit('unpipe', this, unpipeInfo);
-    return this;
-  }
-
-  // slow case. multiple pipe destinations.
-
-  if (!dest) {
-    // remove all.
-    var dests = state.pipes;
-    var len = state.pipesCount;
-    state.pipes = null;
-    state.pipesCount = 0;
-    state.flowing = false;
-    for (var i = 0; i < len; i++) dests[i].emit('unpipe', this, {
-      hasUnpiped: false
-    });
-    return this;
-  }
-
-  // try to find the right one.
-  var index = indexOf(state.pipes, dest);
-  if (index === -1) return this;
-  state.pipes.splice(index, 1);
-  state.pipesCount -= 1;
-  if (state.pipesCount === 1) state.pipes = state.pipes[0];
-  dest.emit('unpipe', this, unpipeInfo);
-  return this;
-};
-
-// set up data events if they are asked for
-// Ensure readable listeners eventually get something
-Readable.prototype.on = function (ev, fn) {
-  var res = Stream.prototype.on.call(this, ev, fn);
-  var state = this._readableState;
-  if (ev === 'data') {
-    // update readableListening so that resume() may be a no-op
-    // a few lines down. This is needed to support once('readable').
-    state.readableListening = this.listenerCount('readable') > 0;
-
-    // Try start flowing on next tick if stream isn't explicitly paused
-    if (state.flowing !== false) this.resume();
-  } else if (ev === 'readable') {
-    if (!state.endEmitted && !state.readableListening) {
-      state.readableListening = state.needReadable = true;
-      state.flowing = false;
-      state.emittedReadable = false;
-      debug('on readable', state.length, state.reading);
-      if (state.length) {
-        emitReadable(this);
-      } else if (!state.reading) {
-        process.nextTick(nReadingNextTick, this);
-      }
-    }
-  }
-  return res;
-};
-Readable.prototype.addListener = Readable.prototype.on;
-Readable.prototype.removeListener = function (ev, fn) {
-  var res = Stream.prototype.removeListener.call(this, ev, fn);
-  if (ev === 'readable') {
-    // We need to check if there is someone still listening to
-    // readable and reset the state. However this needs to happen
-    // after readable has been emitted but before I/O (nextTick) to
-    // support once('readable', fn) cycles. This means that calling
-    // resume within the same tick will have no
-    // effect.
-    process.nextTick(updateReadableListening, this);
-  }
-  return res;
-};
-Readable.prototype.removeAllListeners = function (ev) {
-  var res = Stream.prototype.removeAllListeners.apply(this, arguments);
-  if (ev === 'readable' || ev === undefined) {
-    // We need to check if there is someone still listening to
-    // readable and reset the state. However this needs to happen
-    // after readable has been emitted but before I/O (nextTick) to
-    // support once('readable', fn) cycles. This means that calling
-    // resume within the same tick will have no
-    // effect.
-    process.nextTick(updateReadableListening, this);
-  }
-  return res;
-};
-function updateReadableListening(self) {
-  var state = self._readableState;
-  state.readableListening = self.listenerCount('readable') > 0;
-  if (state.resumeScheduled && !state.paused) {
-    // flowing needs to be set to true now, otherwise
-    // the upcoming resume will not flow.
-    state.flowing = true;
-
-    // crude way to check if we should resume
-  } else if (self.listenerCount('data') > 0) {
-    self.resume();
-  }
-}
-function nReadingNextTick(self) {
-  debug('readable nexttick read 0');
-  self.read(0);
-}
-
-// pause() and resume() are remnants of the legacy readable stream API
-// If the user uses them, then switch into old mode.
-Readable.prototype.resume = function () {
-  var state = this._readableState;
-  if (!state.flowing) {
-    debug('resume');
-    // we flow only if there is no one listening
-    // for readable, but we still have to call
-    // resume()
-    state.flowing = !state.readableListening;
-    resume(this, state);
-  }
-  state.paused = false;
-  return this;
-};
-function resume(stream, state) {
-  if (!state.resumeScheduled) {
-    state.resumeScheduled = true;
-    process.nextTick(resume_, stream, state);
-  }
-}
-function resume_(stream, state) {
-  debug('resume', state.reading);
-  if (!state.reading) {
-    stream.read(0);
-  }
-  state.resumeScheduled = false;
-  stream.emit('resume');
-  flow(stream);
-  if (state.flowing && !state.reading) stream.read(0);
-}
-Readable.prototype.pause = function () {
-  debug('call pause flowing=%j', this._readableState.flowing);
-  if (this._readableState.flowing !== false) {
-    debug('pause');
-    this._readableState.flowing = false;
-    this.emit('pause');
-  }
-  this._readableState.paused = true;
-  return this;
-};
-function flow(stream) {
-  var state = stream._readableState;
-  debug('flow', state.flowing);
-  while (state.flowing && stream.read() !== null);
-}
-
-// wrap an old-style stream as the async data source.
-// This is *not* part of the readable stream interface.
-// It is an ugly unfortunate mess of history.
-Readable.prototype.wrap = function (stream) {
-  var _this = this;
-  var state = this._readableState;
-  var paused = false;
-  stream.on('end', function () {
-    debug('wrapped end');
-    if (state.decoder && !state.ended) {
-      var chunk = state.decoder.end();
-      if (chunk && chunk.length) _this.push(chunk);
-    }
-    _this.push(null);
-  });
-  stream.on('data', function (chunk) {
-    debug('wrapped data');
-    if (state.decoder) chunk = state.decoder.write(chunk);
-
-    // don't skip over falsy values in objectMode
-    if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return;
-    var ret = _this.push(chunk);
-    if (!ret) {
-      paused = true;
-      stream.pause();
-    }
-  });
-
-  // proxy all the other methods.
-  // important when wrapping filters and duplexes.
-  for (var i in stream) {
-    if (this[i] === undefined && typeof stream[i] === 'function') {
-      this[i] = function methodWrap(method) {
-        return function methodWrapReturnFunction() {
-          return stream[method].apply(stream, arguments);
-        };
-      }(i);
-    }
-  }
-
-  // proxy certain important events.
-  for (var n = 0; n < kProxyEvents.length; n++) {
-    stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n]));
-  }
-
-  // when we try to consume some more bytes, simply unpause the
-  // underlying stream.
-  this._read = function (n) {
-    debug('wrapped _read', n);
-    if (paused) {
-      paused = false;
-      stream.resume();
-    }
-  };
-  return this;
-};
-if (typeof Symbol === 'function') {
-  Readable.prototype[Symbol.asyncIterator] = function () {
-    if (createReadableStreamAsyncIterator === undefined) {
-      createReadableStreamAsyncIterator = require('./internal/streams/async_iterator');
-    }
-    return createReadableStreamAsyncIterator(this);
-  };
-}
-Object.defineProperty(Readable.prototype, 'readableHighWaterMark', {
-  // making it explicit this property is not enumerable
-  // because otherwise some prototype manipulation in
-  // userland will fail
-  enumerable: false,
-  get: function get() {
-    return this._readableState.highWaterMark;
-  }
-});
-Object.defineProperty(Readable.prototype, 'readableBuffer', {
-  // making it explicit this property is not enumerable
-  // because otherwise some prototype manipulation in
-  // userland will fail
-  enumerable: false,
-  get: function get() {
-    return this._readableState && this._readableState.buffer;
-  }
-});
-Object.defineProperty(Readable.prototype, 'readableFlowing', {
-  // making it explicit this property is not enumerable
-  // because otherwise some prototype manipulation in
-  // userland will fail
-  enumerable: false,
-  get: function get() {
-    return this._readableState.flowing;
-  },
-  set: function set(state) {
-    if (this._readableState) {
-      this._readableState.flowing = state;
-    }
-  }
-});
-
-// exposed for testing purposes only.
-Readable._fromList = fromList;
-Object.defineProperty(Readable.prototype, 'readableLength', {
-  // making it explicit this property is not enumerable
-  // because otherwise some prototype manipulation in
-  // userland will fail
-  enumerable: false,
-  get: function get() {
-    return this._readableState.length;
-  }
-});
-
-// Pluck off n bytes from an array of buffers.
-// Length is the combined lengths of all the buffers in the list.
-// This function is designed to be inlinable, so please take care when making
-// changes to the function body.
-function fromList(n, state) {
-  // nothing buffered
-  if (state.length === 0) return null;
-  var ret;
-  if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) {
-    // read it all, truncate the list
-    if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.first();else ret = state.buffer.concat(state.length);
-    state.buffer.clear();
-  } else {
-    // read part of list
-    ret = state.buffer.consume(n, state.decoder);
-  }
-  return ret;
-}
-function endReadable(stream) {
-  var state = stream._readableState;
-  debug('endReadable', state.endEmitted);
-  if (!state.endEmitted) {
-    state.ended = true;
-    process.nextTick(endReadableNT, state, stream);
-  }
-}
-function endReadableNT(state, stream) {
-  debug('endReadableNT', state.endEmitted, state.length);
-
-  // Check that we didn't get one last unshift.
-  if (!state.endEmitted && state.length === 0) {
-    state.endEmitted = true;
-    stream.readable = false;
-    stream.emit('end');
-    if (state.autoDestroy) {
-      // In case of duplex streams we need a way to detect
-      // if the writable side is ready for autoDestroy as well
-      var wState = stream._writableState;
-      if (!wState || wState.autoDestroy && wState.finished) {
-        stream.destroy();
-      }
-    }
-  }
-}
-if (typeof Symbol === 'function') {
-  Readable.from = function (iterable, opts) {
-    if (from === undefined) {
-      from = require('./internal/streams/from');
-    }
-    return from(Readable, iterable, opts);
-  };
-}
-function indexOf(xs, x) {
-  for (var i = 0, l = xs.length; i < l; i++) {
-    if (xs[i] === x) return i;
-  }
-  return -1;
-}
\ No newline at end of file
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/_stream_transform.js b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/_stream_transform.js
deleted file mode 100644
index 1ccb7157be8b8c..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/_stream_transform.js
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// 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.
-
-// a transform stream is a readable/writable stream where you do
-// something with the data.  Sometimes it's called a "filter",
-// but that's not a great name for it, since that implies a thing where
-// some bits pass through, and others are simply ignored.  (That would
-// be a valid example of a transform, of course.)
-//
-// While the output is causally related to the input, it's not a
-// necessarily symmetric or synchronous transformation.  For example,
-// a zlib stream might take multiple plain-text writes(), and then
-// emit a single compressed chunk some time in the future.
-//
-// Here's how this works:
-//
-// The Transform stream has all the aspects of the readable and writable
-// stream classes.  When you write(chunk), that calls _write(chunk,cb)
-// internally, and returns false if there's a lot of pending writes
-// buffered up.  When you call read(), that calls _read(n) until
-// there's enough pending readable data buffered up.
-//
-// In a transform stream, the written data is placed in a buffer.  When
-// _read(n) is called, it transforms the queued up data, calling the
-// buffered _write cb's as it consumes chunks.  If consuming a single
-// written chunk would result in multiple output chunks, then the first
-// outputted bit calls the readcb, and subsequent chunks just go into
-// the read buffer, and will cause it to emit 'readable' if necessary.
-//
-// This way, back-pressure is actually determined by the reading side,
-// since _read has to be called to start processing a new chunk.  However,
-// a pathological inflate type of transform can cause excessive buffering
-// here.  For example, imagine a stream where every byte of input is
-// interpreted as an integer from 0-255, and then results in that many
-// bytes of output.  Writing the 4 bytes {ff,ff,ff,ff} would result in
-// 1kb of data being output.  In this case, you could write a very small
-// amount of input, and end up with a very large amount of output.  In
-// such a pathological inflating mechanism, there'd be no way to tell
-// the system to stop doing the transform.  A single 4MB write could
-// cause the system to run out of memory.
-//
-// However, even in such a pathological case, only a single written chunk
-// would be consumed, and then the rest would wait (un-transformed) until
-// the results of the previous transformed chunk were consumed.
-
-'use strict';
-
-module.exports = Transform;
-var _require$codes = require('../errors').codes,
-  ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED,
-  ERR_MULTIPLE_CALLBACK = _require$codes.ERR_MULTIPLE_CALLBACK,
-  ERR_TRANSFORM_ALREADY_TRANSFORMING = _require$codes.ERR_TRANSFORM_ALREADY_TRANSFORMING,
-  ERR_TRANSFORM_WITH_LENGTH_0 = _require$codes.ERR_TRANSFORM_WITH_LENGTH_0;
-var Duplex = require('./_stream_duplex');
-require('inherits')(Transform, Duplex);
-function afterTransform(er, data) {
-  var ts = this._transformState;
-  ts.transforming = false;
-  var cb = ts.writecb;
-  if (cb === null) {
-    return this.emit('error', new ERR_MULTIPLE_CALLBACK());
-  }
-  ts.writechunk = null;
-  ts.writecb = null;
-  if (data != null)
-    // single equals check for both `null` and `undefined`
-    this.push(data);
-  cb(er);
-  var rs = this._readableState;
-  rs.reading = false;
-  if (rs.needReadable || rs.length < rs.highWaterMark) {
-    this._read(rs.highWaterMark);
-  }
-}
-function Transform(options) {
-  if (!(this instanceof Transform)) return new Transform(options);
-  Duplex.call(this, options);
-  this._transformState = {
-    afterTransform: afterTransform.bind(this),
-    needTransform: false,
-    transforming: false,
-    writecb: null,
-    writechunk: null,
-    writeencoding: null
-  };
-
-  // start out asking for a readable event once data is transformed.
-  this._readableState.needReadable = true;
-
-  // we have implemented the _read method, and done the other things
-  // that Readable wants before the first _read call, so unset the
-  // sync guard flag.
-  this._readableState.sync = false;
-  if (options) {
-    if (typeof options.transform === 'function') this._transform = options.transform;
-    if (typeof options.flush === 'function') this._flush = options.flush;
-  }
-
-  // When the writable side finishes, then flush out anything remaining.
-  this.on('prefinish', prefinish);
-}
-function prefinish() {
-  var _this = this;
-  if (typeof this._flush === 'function' && !this._readableState.destroyed) {
-    this._flush(function (er, data) {
-      done(_this, er, data);
-    });
-  } else {
-    done(this, null, null);
-  }
-}
-Transform.prototype.push = function (chunk, encoding) {
-  this._transformState.needTransform = false;
-  return Duplex.prototype.push.call(this, chunk, encoding);
-};
-
-// This is the part where you do stuff!
-// override this function in implementation classes.
-// 'chunk' is an input chunk.
-//
-// Call `push(newChunk)` to pass along transformed output
-// to the readable side.  You may call 'push' zero or more times.
-//
-// Call `cb(err)` when you are done with this chunk.  If you pass
-// an error, then that'll put the hurt on the whole operation.  If you
-// never call cb(), then you'll never get another chunk.
-Transform.prototype._transform = function (chunk, encoding, cb) {
-  cb(new ERR_METHOD_NOT_IMPLEMENTED('_transform()'));
-};
-Transform.prototype._write = function (chunk, encoding, cb) {
-  var ts = this._transformState;
-  ts.writecb = cb;
-  ts.writechunk = chunk;
-  ts.writeencoding = encoding;
-  if (!ts.transforming) {
-    var rs = this._readableState;
-    if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark);
-  }
-};
-
-// Doesn't matter what the args are here.
-// _transform does all the work.
-// That we got here means that the readable side wants more data.
-Transform.prototype._read = function (n) {
-  var ts = this._transformState;
-  if (ts.writechunk !== null && !ts.transforming) {
-    ts.transforming = true;
-    this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
-  } else {
-    // mark that we need a transform, so that any data that comes in
-    // will get processed, now that we've asked for it.
-    ts.needTransform = true;
-  }
-};
-Transform.prototype._destroy = function (err, cb) {
-  Duplex.prototype._destroy.call(this, err, function (err2) {
-    cb(err2);
-  });
-};
-function done(stream, er, data) {
-  if (er) return stream.emit('error', er);
-  if (data != null)
-    // single equals check for both `null` and `undefined`
-    stream.push(data);
-
-  // TODO(BridgeAR): Write a test for these two error cases
-  // if there's nothing in the write buffer, then that means
-  // that nothing more will ever be provided
-  if (stream._writableState.length) throw new ERR_TRANSFORM_WITH_LENGTH_0();
-  if (stream._transformState.transforming) throw new ERR_TRANSFORM_ALREADY_TRANSFORMING();
-  return stream.push(null);
-}
\ No newline at end of file
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/_stream_writable.js b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/_stream_writable.js
deleted file mode 100644
index 292415e23a192b..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/_stream_writable.js
+++ /dev/null
@@ -1,641 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// 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.
-
-// A bit simpler than readable streams.
-// Implement an async ._write(chunk, encoding, cb), and it'll handle all
-// the drain event emission and buffering.
-
-'use strict';
-
-module.exports = Writable;
-
-/*  */
-function WriteReq(chunk, encoding, cb) {
-  this.chunk = chunk;
-  this.encoding = encoding;
-  this.callback = cb;
-  this.next = null;
-}
-
-// It seems a linked list but it is not
-// there will be only 2 of these for each stream
-function CorkedRequest(state) {
-  var _this = this;
-  this.next = null;
-  this.entry = null;
-  this.finish = function () {
-    onCorkedFinish(_this, state);
-  };
-}
-/*  */
-
-/**/
-var Duplex;
-/**/
-
-Writable.WritableState = WritableState;
-
-/**/
-var internalUtil = {
-  deprecate: require('util-deprecate')
-};
-/**/
-
-/**/
-var Stream = require('./internal/streams/stream');
-/**/
-
-var Buffer = require('buffer').Buffer;
-var OurUint8Array = (typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : typeof self !== 'undefined' ? self : {}).Uint8Array || function () {};
-function _uint8ArrayToBuffer(chunk) {
-  return Buffer.from(chunk);
-}
-function _isUint8Array(obj) {
-  return Buffer.isBuffer(obj) || obj instanceof OurUint8Array;
-}
-var destroyImpl = require('./internal/streams/destroy');
-var _require = require('./internal/streams/state'),
-  getHighWaterMark = _require.getHighWaterMark;
-var _require$codes = require('../errors').codes,
-  ERR_INVALID_ARG_TYPE = _require$codes.ERR_INVALID_ARG_TYPE,
-  ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED,
-  ERR_MULTIPLE_CALLBACK = _require$codes.ERR_MULTIPLE_CALLBACK,
-  ERR_STREAM_CANNOT_PIPE = _require$codes.ERR_STREAM_CANNOT_PIPE,
-  ERR_STREAM_DESTROYED = _require$codes.ERR_STREAM_DESTROYED,
-  ERR_STREAM_NULL_VALUES = _require$codes.ERR_STREAM_NULL_VALUES,
-  ERR_STREAM_WRITE_AFTER_END = _require$codes.ERR_STREAM_WRITE_AFTER_END,
-  ERR_UNKNOWN_ENCODING = _require$codes.ERR_UNKNOWN_ENCODING;
-var errorOrDestroy = destroyImpl.errorOrDestroy;
-require('inherits')(Writable, Stream);
-function nop() {}
-function WritableState(options, stream, isDuplex) {
-  Duplex = Duplex || require('./_stream_duplex');
-  options = options || {};
-
-  // Duplex streams are both readable and writable, but share
-  // the same options object.
-  // However, some cases require setting options to different
-  // values for the readable and the writable sides of the duplex stream,
-  // e.g. options.readableObjectMode vs. options.writableObjectMode, etc.
-  if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof Duplex;
-
-  // object stream flag to indicate whether or not this stream
-  // contains buffers or objects.
-  this.objectMode = !!options.objectMode;
-  if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode;
-
-  // the point at which write() starts returning false
-  // Note: 0 is a valid value, means that we always return false if
-  // the entire buffer is not flushed immediately on write()
-  this.highWaterMark = getHighWaterMark(this, options, 'writableHighWaterMark', isDuplex);
-
-  // if _final has been called
-  this.finalCalled = false;
-
-  // drain event flag.
-  this.needDrain = false;
-  // at the start of calling end()
-  this.ending = false;
-  // when end() has been called, and returned
-  this.ended = false;
-  // when 'finish' is emitted
-  this.finished = false;
-
-  // has it been destroyed
-  this.destroyed = false;
-
-  // should we decode strings into buffers before passing to _write?
-  // this is here so that some node-core streams can optimize string
-  // handling at a lower level.
-  var noDecode = options.decodeStrings === false;
-  this.decodeStrings = !noDecode;
-
-  // Crypto is kind of old and crusty.  Historically, its default string
-  // encoding is 'binary' so we have to make this configurable.
-  // Everything else in the universe uses 'utf8', though.
-  this.defaultEncoding = options.defaultEncoding || 'utf8';
-
-  // not an actual buffer we keep track of, but a measurement
-  // of how much we're waiting to get pushed to some underlying
-  // socket or file.
-  this.length = 0;
-
-  // a flag to see when we're in the middle of a write.
-  this.writing = false;
-
-  // when true all writes will be buffered until .uncork() call
-  this.corked = 0;
-
-  // a flag to be able to tell if the onwrite cb is called immediately,
-  // or on a later tick.  We set this to true at first, because any
-  // actions that shouldn't happen until "later" should generally also
-  // not happen before the first write call.
-  this.sync = true;
-
-  // a flag to know if we're processing previously buffered items, which
-  // may call the _write() callback in the same tick, so that we don't
-  // end up in an overlapped onwrite situation.
-  this.bufferProcessing = false;
-
-  // the callback that's passed to _write(chunk,cb)
-  this.onwrite = function (er) {
-    onwrite(stream, er);
-  };
-
-  // the callback that the user supplies to write(chunk,encoding,cb)
-  this.writecb = null;
-
-  // the amount that is being written when _write is called.
-  this.writelen = 0;
-  this.bufferedRequest = null;
-  this.lastBufferedRequest = null;
-
-  // number of pending user-supplied write callbacks
-  // this must be 0 before 'finish' can be emitted
-  this.pendingcb = 0;
-
-  // emit prefinish if the only thing we're waiting for is _write cbs
-  // This is relevant for synchronous Transform streams
-  this.prefinished = false;
-
-  // True if the error was already emitted and should not be thrown again
-  this.errorEmitted = false;
-
-  // Should close be emitted on destroy. Defaults to true.
-  this.emitClose = options.emitClose !== false;
-
-  // Should .destroy() be called after 'finish' (and potentially 'end')
-  this.autoDestroy = !!options.autoDestroy;
-
-  // count buffered requests
-  this.bufferedRequestCount = 0;
-
-  // allocate the first CorkedRequest, there is always
-  // one allocated and free to use, and we maintain at most two
-  this.corkedRequestsFree = new CorkedRequest(this);
-}
-WritableState.prototype.getBuffer = function getBuffer() {
-  var current = this.bufferedRequest;
-  var out = [];
-  while (current) {
-    out.push(current);
-    current = current.next;
-  }
-  return out;
-};
-(function () {
-  try {
-    Object.defineProperty(WritableState.prototype, 'buffer', {
-      get: internalUtil.deprecate(function writableStateBufferGetter() {
-        return this.getBuffer();
-      }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003')
-    });
-  } catch (_) {}
-})();
-
-// Test _writableState for inheritance to account for Duplex streams,
-// whose prototype chain only points to Readable.
-var realHasInstance;
-if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') {
-  realHasInstance = Function.prototype[Symbol.hasInstance];
-  Object.defineProperty(Writable, Symbol.hasInstance, {
-    value: function value(object) {
-      if (realHasInstance.call(this, object)) return true;
-      if (this !== Writable) return false;
-      return object && object._writableState instanceof WritableState;
-    }
-  });
-} else {
-  realHasInstance = function realHasInstance(object) {
-    return object instanceof this;
-  };
-}
-function Writable(options) {
-  Duplex = Duplex || require('./_stream_duplex');
-
-  // Writable ctor is applied to Duplexes, too.
-  // `realHasInstance` is necessary because using plain `instanceof`
-  // would return false, as no `_writableState` property is attached.
-
-  // Trying to use the custom `instanceof` for Writable here will also break the
-  // Node.js LazyTransform implementation, which has a non-trivial getter for
-  // `_writableState` that would lead to infinite recursion.
-
-  // Checking for a Stream.Duplex instance is faster here instead of inside
-  // the WritableState constructor, at least with V8 6.5
-  var isDuplex = this instanceof Duplex;
-  if (!isDuplex && !realHasInstance.call(Writable, this)) return new Writable(options);
-  this._writableState = new WritableState(options, this, isDuplex);
-
-  // legacy.
-  this.writable = true;
-  if (options) {
-    if (typeof options.write === 'function') this._write = options.write;
-    if (typeof options.writev === 'function') this._writev = options.writev;
-    if (typeof options.destroy === 'function') this._destroy = options.destroy;
-    if (typeof options.final === 'function') this._final = options.final;
-  }
-  Stream.call(this);
-}
-
-// Otherwise people can pipe Writable streams, which is just wrong.
-Writable.prototype.pipe = function () {
-  errorOrDestroy(this, new ERR_STREAM_CANNOT_PIPE());
-};
-function writeAfterEnd(stream, cb) {
-  var er = new ERR_STREAM_WRITE_AFTER_END();
-  // TODO: defer error events consistently everywhere, not just the cb
-  errorOrDestroy(stream, er);
-  process.nextTick(cb, er);
-}
-
-// Checks that a user-supplied chunk is valid, especially for the particular
-// mode the stream is in. Currently this means that `null` is never accepted
-// and undefined/non-string values are only allowed in object mode.
-function validChunk(stream, state, chunk, cb) {
-  var er;
-  if (chunk === null) {
-    er = new ERR_STREAM_NULL_VALUES();
-  } else if (typeof chunk !== 'string' && !state.objectMode) {
-    er = new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer'], chunk);
-  }
-  if (er) {
-    errorOrDestroy(stream, er);
-    process.nextTick(cb, er);
-    return false;
-  }
-  return true;
-}
-Writable.prototype.write = function (chunk, encoding, cb) {
-  var state = this._writableState;
-  var ret = false;
-  var isBuf = !state.objectMode && _isUint8Array(chunk);
-  if (isBuf && !Buffer.isBuffer(chunk)) {
-    chunk = _uint8ArrayToBuffer(chunk);
-  }
-  if (typeof encoding === 'function') {
-    cb = encoding;
-    encoding = null;
-  }
-  if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding;
-  if (typeof cb !== 'function') cb = nop;
-  if (state.ending) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) {
-    state.pendingcb++;
-    ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb);
-  }
-  return ret;
-};
-Writable.prototype.cork = function () {
-  this._writableState.corked++;
-};
-Writable.prototype.uncork = function () {
-  var state = this._writableState;
-  if (state.corked) {
-    state.corked--;
-    if (!state.writing && !state.corked && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state);
-  }
-};
-Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) {
-  // node::ParseEncoding() requires lower case.
-  if (typeof encoding === 'string') encoding = encoding.toLowerCase();
-  if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new ERR_UNKNOWN_ENCODING(encoding);
-  this._writableState.defaultEncoding = encoding;
-  return this;
-};
-Object.defineProperty(Writable.prototype, 'writableBuffer', {
-  // making it explicit this property is not enumerable
-  // because otherwise some prototype manipulation in
-  // userland will fail
-  enumerable: false,
-  get: function get() {
-    return this._writableState && this._writableState.getBuffer();
-  }
-});
-function decodeChunk(state, chunk, encoding) {
-  if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') {
-    chunk = Buffer.from(chunk, encoding);
-  }
-  return chunk;
-}
-Object.defineProperty(Writable.prototype, 'writableHighWaterMark', {
-  // making it explicit this property is not enumerable
-  // because otherwise some prototype manipulation in
-  // userland will fail
-  enumerable: false,
-  get: function get() {
-    return this._writableState.highWaterMark;
-  }
-});
-
-// if we're already writing something, then just put this
-// in the queue, and wait our turn.  Otherwise, call _write
-// If we return false, then we need a drain event, so set that flag.
-function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) {
-  if (!isBuf) {
-    var newChunk = decodeChunk(state, chunk, encoding);
-    if (chunk !== newChunk) {
-      isBuf = true;
-      encoding = 'buffer';
-      chunk = newChunk;
-    }
-  }
-  var len = state.objectMode ? 1 : chunk.length;
-  state.length += len;
-  var ret = state.length < state.highWaterMark;
-  // we must ensure that previous needDrain will not be reset to false.
-  if (!ret) state.needDrain = true;
-  if (state.writing || state.corked) {
-    var last = state.lastBufferedRequest;
-    state.lastBufferedRequest = {
-      chunk: chunk,
-      encoding: encoding,
-      isBuf: isBuf,
-      callback: cb,
-      next: null
-    };
-    if (last) {
-      last.next = state.lastBufferedRequest;
-    } else {
-      state.bufferedRequest = state.lastBufferedRequest;
-    }
-    state.bufferedRequestCount += 1;
-  } else {
-    doWrite(stream, state, false, len, chunk, encoding, cb);
-  }
-  return ret;
-}
-function doWrite(stream, state, writev, len, chunk, encoding, cb) {
-  state.writelen = len;
-  state.writecb = cb;
-  state.writing = true;
-  state.sync = true;
-  if (state.destroyed) state.onwrite(new ERR_STREAM_DESTROYED('write'));else if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite);
-  state.sync = false;
-}
-function onwriteError(stream, state, sync, er, cb) {
-  --state.pendingcb;
-  if (sync) {
-    // defer the callback if we are being called synchronously
-    // to avoid piling up things on the stack
-    process.nextTick(cb, er);
-    // this can emit finish, and it will always happen
-    // after error
-    process.nextTick(finishMaybe, stream, state);
-    stream._writableState.errorEmitted = true;
-    errorOrDestroy(stream, er);
-  } else {
-    // the caller expect this to happen before if
-    // it is async
-    cb(er);
-    stream._writableState.errorEmitted = true;
-    errorOrDestroy(stream, er);
-    // this can emit finish, but finish must
-    // always follow error
-    finishMaybe(stream, state);
-  }
-}
-function onwriteStateUpdate(state) {
-  state.writing = false;
-  state.writecb = null;
-  state.length -= state.writelen;
-  state.writelen = 0;
-}
-function onwrite(stream, er) {
-  var state = stream._writableState;
-  var sync = state.sync;
-  var cb = state.writecb;
-  if (typeof cb !== 'function') throw new ERR_MULTIPLE_CALLBACK();
-  onwriteStateUpdate(state);
-  if (er) onwriteError(stream, state, sync, er, cb);else {
-    // Check if we're actually ready to finish, but don't emit yet
-    var finished = needFinish(state) || stream.destroyed;
-    if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) {
-      clearBuffer(stream, state);
-    }
-    if (sync) {
-      process.nextTick(afterWrite, stream, state, finished, cb);
-    } else {
-      afterWrite(stream, state, finished, cb);
-    }
-  }
-}
-function afterWrite(stream, state, finished, cb) {
-  if (!finished) onwriteDrain(stream, state);
-  state.pendingcb--;
-  cb();
-  finishMaybe(stream, state);
-}
-
-// Must force callback to be called on nextTick, so that we don't
-// emit 'drain' before the write() consumer gets the 'false' return
-// value, and has a chance to attach a 'drain' listener.
-function onwriteDrain(stream, state) {
-  if (state.length === 0 && state.needDrain) {
-    state.needDrain = false;
-    stream.emit('drain');
-  }
-}
-
-// if there's something in the buffer waiting, then process it
-function clearBuffer(stream, state) {
-  state.bufferProcessing = true;
-  var entry = state.bufferedRequest;
-  if (stream._writev && entry && entry.next) {
-    // Fast case, write everything using _writev()
-    var l = state.bufferedRequestCount;
-    var buffer = new Array(l);
-    var holder = state.corkedRequestsFree;
-    holder.entry = entry;
-    var count = 0;
-    var allBuffers = true;
-    while (entry) {
-      buffer[count] = entry;
-      if (!entry.isBuf) allBuffers = false;
-      entry = entry.next;
-      count += 1;
-    }
-    buffer.allBuffers = allBuffers;
-    doWrite(stream, state, true, state.length, buffer, '', holder.finish);
-
-    // doWrite is almost always async, defer these to save a bit of time
-    // as the hot path ends with doWrite
-    state.pendingcb++;
-    state.lastBufferedRequest = null;
-    if (holder.next) {
-      state.corkedRequestsFree = holder.next;
-      holder.next = null;
-    } else {
-      state.corkedRequestsFree = new CorkedRequest(state);
-    }
-    state.bufferedRequestCount = 0;
-  } else {
-    // Slow case, write chunks one-by-one
-    while (entry) {
-      var chunk = entry.chunk;
-      var encoding = entry.encoding;
-      var cb = entry.callback;
-      var len = state.objectMode ? 1 : chunk.length;
-      doWrite(stream, state, false, len, chunk, encoding, cb);
-      entry = entry.next;
-      state.bufferedRequestCount--;
-      // if we didn't call the onwrite immediately, then
-      // it means that we need to wait until it does.
-      // also, that means that the chunk and cb are currently
-      // being processed, so move the buffer counter past them.
-      if (state.writing) {
-        break;
-      }
-    }
-    if (entry === null) state.lastBufferedRequest = null;
-  }
-  state.bufferedRequest = entry;
-  state.bufferProcessing = false;
-}
-Writable.prototype._write = function (chunk, encoding, cb) {
-  cb(new ERR_METHOD_NOT_IMPLEMENTED('_write()'));
-};
-Writable.prototype._writev = null;
-Writable.prototype.end = function (chunk, encoding, cb) {
-  var state = this._writableState;
-  if (typeof chunk === 'function') {
-    cb = chunk;
-    chunk = null;
-    encoding = null;
-  } else if (typeof encoding === 'function') {
-    cb = encoding;
-    encoding = null;
-  }
-  if (chunk !== null && chunk !== undefined) this.write(chunk, encoding);
-
-  // .end() fully uncorks
-  if (state.corked) {
-    state.corked = 1;
-    this.uncork();
-  }
-
-  // ignore unnecessary end() calls.
-  if (!state.ending) endWritable(this, state, cb);
-  return this;
-};
-Object.defineProperty(Writable.prototype, 'writableLength', {
-  // making it explicit this property is not enumerable
-  // because otherwise some prototype manipulation in
-  // userland will fail
-  enumerable: false,
-  get: function get() {
-    return this._writableState.length;
-  }
-});
-function needFinish(state) {
-  return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing;
-}
-function callFinal(stream, state) {
-  stream._final(function (err) {
-    state.pendingcb--;
-    if (err) {
-      errorOrDestroy(stream, err);
-    }
-    state.prefinished = true;
-    stream.emit('prefinish');
-    finishMaybe(stream, state);
-  });
-}
-function prefinish(stream, state) {
-  if (!state.prefinished && !state.finalCalled) {
-    if (typeof stream._final === 'function' && !state.destroyed) {
-      state.pendingcb++;
-      state.finalCalled = true;
-      process.nextTick(callFinal, stream, state);
-    } else {
-      state.prefinished = true;
-      stream.emit('prefinish');
-    }
-  }
-}
-function finishMaybe(stream, state) {
-  var need = needFinish(state);
-  if (need) {
-    prefinish(stream, state);
-    if (state.pendingcb === 0) {
-      state.finished = true;
-      stream.emit('finish');
-      if (state.autoDestroy) {
-        // In case of duplex streams we need a way to detect
-        // if the readable side is ready for autoDestroy as well
-        var rState = stream._readableState;
-        if (!rState || rState.autoDestroy && rState.endEmitted) {
-          stream.destroy();
-        }
-      }
-    }
-  }
-  return need;
-}
-function endWritable(stream, state, cb) {
-  state.ending = true;
-  finishMaybe(stream, state);
-  if (cb) {
-    if (state.finished) process.nextTick(cb);else stream.once('finish', cb);
-  }
-  state.ended = true;
-  stream.writable = false;
-}
-function onCorkedFinish(corkReq, state, err) {
-  var entry = corkReq.entry;
-  corkReq.entry = null;
-  while (entry) {
-    var cb = entry.callback;
-    state.pendingcb--;
-    cb(err);
-    entry = entry.next;
-  }
-
-  // reuse the free corkReq.
-  state.corkedRequestsFree.next = corkReq;
-}
-Object.defineProperty(Writable.prototype, 'destroyed', {
-  // making it explicit this property is not enumerable
-  // because otherwise some prototype manipulation in
-  // userland will fail
-  enumerable: false,
-  get: function get() {
-    if (this._writableState === undefined) {
-      return false;
-    }
-    return this._writableState.destroyed;
-  },
-  set: function set(value) {
-    // we ignore the value if the stream
-    // has not been initialized yet
-    if (!this._writableState) {
-      return;
-    }
-
-    // backward compatibility, the user is explicitly
-    // managing destroyed
-    this._writableState.destroyed = value;
-  }
-});
-Writable.prototype.destroy = destroyImpl.destroy;
-Writable.prototype._undestroy = destroyImpl.undestroy;
-Writable.prototype._destroy = function (err, cb) {
-  cb(err);
-};
\ No newline at end of file
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/async_iterator.js b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/async_iterator.js
deleted file mode 100644
index 742c5a4674794d..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/async_iterator.js
+++ /dev/null
@@ -1,180 +0,0 @@
-'use strict';
-
-var _Object$setPrototypeO;
-function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
-function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
-function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
-var finished = require('./end-of-stream');
-var kLastResolve = Symbol('lastResolve');
-var kLastReject = Symbol('lastReject');
-var kError = Symbol('error');
-var kEnded = Symbol('ended');
-var kLastPromise = Symbol('lastPromise');
-var kHandlePromise = Symbol('handlePromise');
-var kStream = Symbol('stream');
-function createIterResult(value, done) {
-  return {
-    value: value,
-    done: done
-  };
-}
-function readAndResolve(iter) {
-  var resolve = iter[kLastResolve];
-  if (resolve !== null) {
-    var data = iter[kStream].read();
-    // we defer if data is null
-    // we can be expecting either 'end' or
-    // 'error'
-    if (data !== null) {
-      iter[kLastPromise] = null;
-      iter[kLastResolve] = null;
-      iter[kLastReject] = null;
-      resolve(createIterResult(data, false));
-    }
-  }
-}
-function onReadable(iter) {
-  // we wait for the next tick, because it might
-  // emit an error with process.nextTick
-  process.nextTick(readAndResolve, iter);
-}
-function wrapForNext(lastPromise, iter) {
-  return function (resolve, reject) {
-    lastPromise.then(function () {
-      if (iter[kEnded]) {
-        resolve(createIterResult(undefined, true));
-        return;
-      }
-      iter[kHandlePromise](resolve, reject);
-    }, reject);
-  };
-}
-var AsyncIteratorPrototype = Object.getPrototypeOf(function () {});
-var ReadableStreamAsyncIteratorPrototype = Object.setPrototypeOf((_Object$setPrototypeO = {
-  get stream() {
-    return this[kStream];
-  },
-  next: function next() {
-    var _this = this;
-    // if we have detected an error in the meanwhile
-    // reject straight away
-    var error = this[kError];
-    if (error !== null) {
-      return Promise.reject(error);
-    }
-    if (this[kEnded]) {
-      return Promise.resolve(createIterResult(undefined, true));
-    }
-    if (this[kStream].destroyed) {
-      // We need to defer via nextTick because if .destroy(err) is
-      // called, the error will be emitted via nextTick, and
-      // we cannot guarantee that there is no error lingering around
-      // waiting to be emitted.
-      return new Promise(function (resolve, reject) {
-        process.nextTick(function () {
-          if (_this[kError]) {
-            reject(_this[kError]);
-          } else {
-            resolve(createIterResult(undefined, true));
-          }
-        });
-      });
-    }
-
-    // if we have multiple next() calls
-    // we will wait for the previous Promise to finish
-    // this logic is optimized to support for await loops,
-    // where next() is only called once at a time
-    var lastPromise = this[kLastPromise];
-    var promise;
-    if (lastPromise) {
-      promise = new Promise(wrapForNext(lastPromise, this));
-    } else {
-      // fast path needed to support multiple this.push()
-      // without triggering the next() queue
-      var data = this[kStream].read();
-      if (data !== null) {
-        return Promise.resolve(createIterResult(data, false));
-      }
-      promise = new Promise(this[kHandlePromise]);
-    }
-    this[kLastPromise] = promise;
-    return promise;
-  }
-}, _defineProperty(_Object$setPrototypeO, Symbol.asyncIterator, function () {
-  return this;
-}), _defineProperty(_Object$setPrototypeO, "return", function _return() {
-  var _this2 = this;
-  // destroy(err, cb) is a private API
-  // we can guarantee we have that here, because we control the
-  // Readable class this is attached to
-  return new Promise(function (resolve, reject) {
-    _this2[kStream].destroy(null, function (err) {
-      if (err) {
-        reject(err);
-        return;
-      }
-      resolve(createIterResult(undefined, true));
-    });
-  });
-}), _Object$setPrototypeO), AsyncIteratorPrototype);
-var createReadableStreamAsyncIterator = function createReadableStreamAsyncIterator(stream) {
-  var _Object$create;
-  var iterator = Object.create(ReadableStreamAsyncIteratorPrototype, (_Object$create = {}, _defineProperty(_Object$create, kStream, {
-    value: stream,
-    writable: true
-  }), _defineProperty(_Object$create, kLastResolve, {
-    value: null,
-    writable: true
-  }), _defineProperty(_Object$create, kLastReject, {
-    value: null,
-    writable: true
-  }), _defineProperty(_Object$create, kError, {
-    value: null,
-    writable: true
-  }), _defineProperty(_Object$create, kEnded, {
-    value: stream._readableState.endEmitted,
-    writable: true
-  }), _defineProperty(_Object$create, kHandlePromise, {
-    value: function value(resolve, reject) {
-      var data = iterator[kStream].read();
-      if (data) {
-        iterator[kLastPromise] = null;
-        iterator[kLastResolve] = null;
-        iterator[kLastReject] = null;
-        resolve(createIterResult(data, false));
-      } else {
-        iterator[kLastResolve] = resolve;
-        iterator[kLastReject] = reject;
-      }
-    },
-    writable: true
-  }), _Object$create));
-  iterator[kLastPromise] = null;
-  finished(stream, function (err) {
-    if (err && err.code !== 'ERR_STREAM_PREMATURE_CLOSE') {
-      var reject = iterator[kLastReject];
-      // reject if we are waiting for data in the Promise
-      // returned by next() and store the error
-      if (reject !== null) {
-        iterator[kLastPromise] = null;
-        iterator[kLastResolve] = null;
-        iterator[kLastReject] = null;
-        reject(err);
-      }
-      iterator[kError] = err;
-      return;
-    }
-    var resolve = iterator[kLastResolve];
-    if (resolve !== null) {
-      iterator[kLastPromise] = null;
-      iterator[kLastResolve] = null;
-      iterator[kLastReject] = null;
-      resolve(createIterResult(undefined, true));
-    }
-    iterator[kEnded] = true;
-  });
-  stream.on('readable', onReadable.bind(null, iterator));
-  return iterator;
-};
-module.exports = createReadableStreamAsyncIterator;
\ No newline at end of file
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/buffer_list.js b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/buffer_list.js
deleted file mode 100644
index 69bda497d35f34..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/buffer_list.js
+++ /dev/null
@@ -1,183 +0,0 @@
-'use strict';
-
-function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
-function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
-function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
-function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
-function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
-function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
-function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
-var _require = require('buffer'),
-  Buffer = _require.Buffer;
-var _require2 = require('util'),
-  inspect = _require2.inspect;
-var custom = inspect && inspect.custom || 'inspect';
-function copyBuffer(src, target, offset) {
-  Buffer.prototype.copy.call(src, target, offset);
-}
-module.exports = /*#__PURE__*/function () {
-  function BufferList() {
-    _classCallCheck(this, BufferList);
-    this.head = null;
-    this.tail = null;
-    this.length = 0;
-  }
-  _createClass(BufferList, [{
-    key: "push",
-    value: function push(v) {
-      var entry = {
-        data: v,
-        next: null
-      };
-      if (this.length > 0) this.tail.next = entry;else this.head = entry;
-      this.tail = entry;
-      ++this.length;
-    }
-  }, {
-    key: "unshift",
-    value: function unshift(v) {
-      var entry = {
-        data: v,
-        next: this.head
-      };
-      if (this.length === 0) this.tail = entry;
-      this.head = entry;
-      ++this.length;
-    }
-  }, {
-    key: "shift",
-    value: function shift() {
-      if (this.length === 0) return;
-      var ret = this.head.data;
-      if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next;
-      --this.length;
-      return ret;
-    }
-  }, {
-    key: "clear",
-    value: function clear() {
-      this.head = this.tail = null;
-      this.length = 0;
-    }
-  }, {
-    key: "join",
-    value: function join(s) {
-      if (this.length === 0) return '';
-      var p = this.head;
-      var ret = '' + p.data;
-      while (p = p.next) ret += s + p.data;
-      return ret;
-    }
-  }, {
-    key: "concat",
-    value: function concat(n) {
-      if (this.length === 0) return Buffer.alloc(0);
-      var ret = Buffer.allocUnsafe(n >>> 0);
-      var p = this.head;
-      var i = 0;
-      while (p) {
-        copyBuffer(p.data, ret, i);
-        i += p.data.length;
-        p = p.next;
-      }
-      return ret;
-    }
-
-    // Consumes a specified amount of bytes or characters from the buffered data.
-  }, {
-    key: "consume",
-    value: function consume(n, hasStrings) {
-      var ret;
-      if (n < this.head.data.length) {
-        // `slice` is the same for buffers and strings.
-        ret = this.head.data.slice(0, n);
-        this.head.data = this.head.data.slice(n);
-      } else if (n === this.head.data.length) {
-        // First chunk is a perfect match.
-        ret = this.shift();
-      } else {
-        // Result spans more than one buffer.
-        ret = hasStrings ? this._getString(n) : this._getBuffer(n);
-      }
-      return ret;
-    }
-  }, {
-    key: "first",
-    value: function first() {
-      return this.head.data;
-    }
-
-    // Consumes a specified amount of characters from the buffered data.
-  }, {
-    key: "_getString",
-    value: function _getString(n) {
-      var p = this.head;
-      var c = 1;
-      var ret = p.data;
-      n -= ret.length;
-      while (p = p.next) {
-        var str = p.data;
-        var nb = n > str.length ? str.length : n;
-        if (nb === str.length) ret += str;else ret += str.slice(0, n);
-        n -= nb;
-        if (n === 0) {
-          if (nb === str.length) {
-            ++c;
-            if (p.next) this.head = p.next;else this.head = this.tail = null;
-          } else {
-            this.head = p;
-            p.data = str.slice(nb);
-          }
-          break;
-        }
-        ++c;
-      }
-      this.length -= c;
-      return ret;
-    }
-
-    // Consumes a specified amount of bytes from the buffered data.
-  }, {
-    key: "_getBuffer",
-    value: function _getBuffer(n) {
-      var ret = Buffer.allocUnsafe(n);
-      var p = this.head;
-      var c = 1;
-      p.data.copy(ret);
-      n -= p.data.length;
-      while (p = p.next) {
-        var buf = p.data;
-        var nb = n > buf.length ? buf.length : n;
-        buf.copy(ret, ret.length - n, 0, nb);
-        n -= nb;
-        if (n === 0) {
-          if (nb === buf.length) {
-            ++c;
-            if (p.next) this.head = p.next;else this.head = this.tail = null;
-          } else {
-            this.head = p;
-            p.data = buf.slice(nb);
-          }
-          break;
-        }
-        ++c;
-      }
-      this.length -= c;
-      return ret;
-    }
-
-    // Make sure the linked list only shows the minimal necessary information.
-  }, {
-    key: custom,
-    value: function value(_, options) {
-      return inspect(this, _objectSpread(_objectSpread({}, options), {}, {
-        // Only inspect one level.
-        depth: 0,
-        // It should not recurse.
-        customInspect: false
-      }));
-    }
-  }]);
-  return BufferList;
-}();
\ No newline at end of file
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/destroy.js b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/destroy.js
deleted file mode 100644
index 31a17c4dc46388..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/destroy.js
+++ /dev/null
@@ -1,96 +0,0 @@
-'use strict';
-
-// undocumented cb() API, needed for core, not for public API
-function destroy(err, cb) {
-  var _this = this;
-  var readableDestroyed = this._readableState && this._readableState.destroyed;
-  var writableDestroyed = this._writableState && this._writableState.destroyed;
-  if (readableDestroyed || writableDestroyed) {
-    if (cb) {
-      cb(err);
-    } else if (err) {
-      if (!this._writableState) {
-        process.nextTick(emitErrorNT, this, err);
-      } else if (!this._writableState.errorEmitted) {
-        this._writableState.errorEmitted = true;
-        process.nextTick(emitErrorNT, this, err);
-      }
-    }
-    return this;
-  }
-
-  // we set destroyed to true before firing error callbacks in order
-  // to make it re-entrance safe in case destroy() is called within callbacks
-
-  if (this._readableState) {
-    this._readableState.destroyed = true;
-  }
-
-  // if this is a duplex stream mark the writable part as destroyed as well
-  if (this._writableState) {
-    this._writableState.destroyed = true;
-  }
-  this._destroy(err || null, function (err) {
-    if (!cb && err) {
-      if (!_this._writableState) {
-        process.nextTick(emitErrorAndCloseNT, _this, err);
-      } else if (!_this._writableState.errorEmitted) {
-        _this._writableState.errorEmitted = true;
-        process.nextTick(emitErrorAndCloseNT, _this, err);
-      } else {
-        process.nextTick(emitCloseNT, _this);
-      }
-    } else if (cb) {
-      process.nextTick(emitCloseNT, _this);
-      cb(err);
-    } else {
-      process.nextTick(emitCloseNT, _this);
-    }
-  });
-  return this;
-}
-function emitErrorAndCloseNT(self, err) {
-  emitErrorNT(self, err);
-  emitCloseNT(self);
-}
-function emitCloseNT(self) {
-  if (self._writableState && !self._writableState.emitClose) return;
-  if (self._readableState && !self._readableState.emitClose) return;
-  self.emit('close');
-}
-function undestroy() {
-  if (this._readableState) {
-    this._readableState.destroyed = false;
-    this._readableState.reading = false;
-    this._readableState.ended = false;
-    this._readableState.endEmitted = false;
-  }
-  if (this._writableState) {
-    this._writableState.destroyed = false;
-    this._writableState.ended = false;
-    this._writableState.ending = false;
-    this._writableState.finalCalled = false;
-    this._writableState.prefinished = false;
-    this._writableState.finished = false;
-    this._writableState.errorEmitted = false;
-  }
-}
-function emitErrorNT(self, err) {
-  self.emit('error', err);
-}
-function errorOrDestroy(stream, err) {
-  // We have tests that rely on errors being emitted
-  // in the same tick, so changing this is semver major.
-  // For now when you opt-in to autoDestroy we allow
-  // the error to be emitted nextTick. In a future
-  // semver major update we should change the default to this.
-
-  var rState = stream._readableState;
-  var wState = stream._writableState;
-  if (rState && rState.autoDestroy || wState && wState.autoDestroy) stream.destroy(err);else stream.emit('error', err);
-}
-module.exports = {
-  destroy: destroy,
-  undestroy: undestroy,
-  errorOrDestroy: errorOrDestroy
-};
\ No newline at end of file
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/end-of-stream.js b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/end-of-stream.js
deleted file mode 100644
index 59c671b5af769b..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/end-of-stream.js
+++ /dev/null
@@ -1,86 +0,0 @@
-// Ported from https://github.com/mafintosh/end-of-stream with
-// permission from the author, Mathias Buus (@mafintosh).
-
-'use strict';
-
-var ERR_STREAM_PREMATURE_CLOSE = require('../../../errors').codes.ERR_STREAM_PREMATURE_CLOSE;
-function once(callback) {
-  var called = false;
-  return function () {
-    if (called) return;
-    called = true;
-    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
-      args[_key] = arguments[_key];
-    }
-    callback.apply(this, args);
-  };
-}
-function noop() {}
-function isRequest(stream) {
-  return stream.setHeader && typeof stream.abort === 'function';
-}
-function eos(stream, opts, callback) {
-  if (typeof opts === 'function') return eos(stream, null, opts);
-  if (!opts) opts = {};
-  callback = once(callback || noop);
-  var readable = opts.readable || opts.readable !== false && stream.readable;
-  var writable = opts.writable || opts.writable !== false && stream.writable;
-  var onlegacyfinish = function onlegacyfinish() {
-    if (!stream.writable) onfinish();
-  };
-  var writableEnded = stream._writableState && stream._writableState.finished;
-  var onfinish = function onfinish() {
-    writable = false;
-    writableEnded = true;
-    if (!readable) callback.call(stream);
-  };
-  var readableEnded = stream._readableState && stream._readableState.endEmitted;
-  var onend = function onend() {
-    readable = false;
-    readableEnded = true;
-    if (!writable) callback.call(stream);
-  };
-  var onerror = function onerror(err) {
-    callback.call(stream, err);
-  };
-  var onclose = function onclose() {
-    var err;
-    if (readable && !readableEnded) {
-      if (!stream._readableState || !stream._readableState.ended) err = new ERR_STREAM_PREMATURE_CLOSE();
-      return callback.call(stream, err);
-    }
-    if (writable && !writableEnded) {
-      if (!stream._writableState || !stream._writableState.ended) err = new ERR_STREAM_PREMATURE_CLOSE();
-      return callback.call(stream, err);
-    }
-  };
-  var onrequest = function onrequest() {
-    stream.req.on('finish', onfinish);
-  };
-  if (isRequest(stream)) {
-    stream.on('complete', onfinish);
-    stream.on('abort', onclose);
-    if (stream.req) onrequest();else stream.on('request', onrequest);
-  } else if (writable && !stream._writableState) {
-    // legacy streams
-    stream.on('end', onlegacyfinish);
-    stream.on('close', onlegacyfinish);
-  }
-  stream.on('end', onend);
-  stream.on('finish', onfinish);
-  if (opts.error !== false) stream.on('error', onerror);
-  stream.on('close', onclose);
-  return function () {
-    stream.removeListener('complete', onfinish);
-    stream.removeListener('abort', onclose);
-    stream.removeListener('request', onrequest);
-    if (stream.req) stream.req.removeListener('finish', onfinish);
-    stream.removeListener('end', onlegacyfinish);
-    stream.removeListener('close', onlegacyfinish);
-    stream.removeListener('finish', onfinish);
-    stream.removeListener('end', onend);
-    stream.removeListener('error', onerror);
-    stream.removeListener('close', onclose);
-  };
-}
-module.exports = eos;
\ No newline at end of file
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/from-browser.js b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/from-browser.js
deleted file mode 100644
index a4ce56f3c90f60..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/from-browser.js
+++ /dev/null
@@ -1,3 +0,0 @@
-module.exports = function () {
-  throw new Error('Readable.from is not available in the browser')
-};
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/from.js b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/from.js
deleted file mode 100644
index 0a34ee92e3df85..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/from.js
+++ /dev/null
@@ -1,52 +0,0 @@
-'use strict';
-
-function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
-function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
-function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
-function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
-function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
-function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
-function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
-var ERR_INVALID_ARG_TYPE = require('../../../errors').codes.ERR_INVALID_ARG_TYPE;
-function from(Readable, iterable, opts) {
-  var iterator;
-  if (iterable && typeof iterable.next === 'function') {
-    iterator = iterable;
-  } else if (iterable && iterable[Symbol.asyncIterator]) iterator = iterable[Symbol.asyncIterator]();else if (iterable && iterable[Symbol.iterator]) iterator = iterable[Symbol.iterator]();else throw new ERR_INVALID_ARG_TYPE('iterable', ['Iterable'], iterable);
-  var readable = new Readable(_objectSpread({
-    objectMode: true
-  }, opts));
-  // Reading boolean to protect against _read
-  // being called before last iteration completion.
-  var reading = false;
-  readable._read = function () {
-    if (!reading) {
-      reading = true;
-      next();
-    }
-  };
-  function next() {
-    return _next2.apply(this, arguments);
-  }
-  function _next2() {
-    _next2 = _asyncToGenerator(function* () {
-      try {
-        var _yield$iterator$next = yield iterator.next(),
-          value = _yield$iterator$next.value,
-          done = _yield$iterator$next.done;
-        if (done) {
-          readable.push(null);
-        } else if (readable.push(yield value)) {
-          next();
-        } else {
-          reading = false;
-        }
-      } catch (err) {
-        readable.destroy(err);
-      }
-    });
-    return _next2.apply(this, arguments);
-  }
-  return readable;
-}
-module.exports = from;
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/pipeline.js b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/pipeline.js
deleted file mode 100644
index e6f39241f98dd8..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/pipeline.js
+++ /dev/null
@@ -1,86 +0,0 @@
-// Ported from https://github.com/mafintosh/pump with
-// permission from the author, Mathias Buus (@mafintosh).
-
-'use strict';
-
-var eos;
-function once(callback) {
-  var called = false;
-  return function () {
-    if (called) return;
-    called = true;
-    callback.apply(void 0, arguments);
-  };
-}
-var _require$codes = require('../../../errors').codes,
-  ERR_MISSING_ARGS = _require$codes.ERR_MISSING_ARGS,
-  ERR_STREAM_DESTROYED = _require$codes.ERR_STREAM_DESTROYED;
-function noop(err) {
-  // Rethrow the error if it exists to avoid swallowing it
-  if (err) throw err;
-}
-function isRequest(stream) {
-  return stream.setHeader && typeof stream.abort === 'function';
-}
-function destroyer(stream, reading, writing, callback) {
-  callback = once(callback);
-  var closed = false;
-  stream.on('close', function () {
-    closed = true;
-  });
-  if (eos === undefined) eos = require('./end-of-stream');
-  eos(stream, {
-    readable: reading,
-    writable: writing
-  }, function (err) {
-    if (err) return callback(err);
-    closed = true;
-    callback();
-  });
-  var destroyed = false;
-  return function (err) {
-    if (closed) return;
-    if (destroyed) return;
-    destroyed = true;
-
-    // request.destroy just do .end - .abort is what we want
-    if (isRequest(stream)) return stream.abort();
-    if (typeof stream.destroy === 'function') return stream.destroy();
-    callback(err || new ERR_STREAM_DESTROYED('pipe'));
-  };
-}
-function call(fn) {
-  fn();
-}
-function pipe(from, to) {
-  return from.pipe(to);
-}
-function popCallback(streams) {
-  if (!streams.length) return noop;
-  if (typeof streams[streams.length - 1] !== 'function') return noop;
-  return streams.pop();
-}
-function pipeline() {
-  for (var _len = arguments.length, streams = new Array(_len), _key = 0; _key < _len; _key++) {
-    streams[_key] = arguments[_key];
-  }
-  var callback = popCallback(streams);
-  if (Array.isArray(streams[0])) streams = streams[0];
-  if (streams.length < 2) {
-    throw new ERR_MISSING_ARGS('streams');
-  }
-  var error;
-  var destroys = streams.map(function (stream, i) {
-    var reading = i < streams.length - 1;
-    var writing = i > 0;
-    return destroyer(stream, reading, writing, function (err) {
-      if (!error) error = err;
-      if (err) destroys.forEach(call);
-      if (reading) return;
-      destroys.forEach(call);
-      callback(error);
-    });
-  });
-  return streams.reduce(pipe);
-}
-module.exports = pipeline;
\ No newline at end of file
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/state.js b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/state.js
deleted file mode 100644
index 3fbf8927e00179..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/state.js
+++ /dev/null
@@ -1,22 +0,0 @@
-'use strict';
-
-var ERR_INVALID_OPT_VALUE = require('../../../errors').codes.ERR_INVALID_OPT_VALUE;
-function highWaterMarkFrom(options, isDuplex, duplexKey) {
-  return options.highWaterMark != null ? options.highWaterMark : isDuplex ? options[duplexKey] : null;
-}
-function getHighWaterMark(state, options, duplexKey, isDuplex) {
-  var hwm = highWaterMarkFrom(options, isDuplex, duplexKey);
-  if (hwm != null) {
-    if (!(isFinite(hwm) && Math.floor(hwm) === hwm) || hwm < 0) {
-      var name = isDuplex ? duplexKey : 'highWaterMark';
-      throw new ERR_INVALID_OPT_VALUE(name, hwm);
-    }
-    return Math.floor(hwm);
-  }
-
-  // Default value
-  return state.objectMode ? 16 : 16 * 1024;
-}
-module.exports = {
-  getHighWaterMark: getHighWaterMark
-};
\ No newline at end of file
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/stream-browser.js b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/stream-browser.js
deleted file mode 100644
index 9332a3fdae7060..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/stream-browser.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require('events').EventEmitter;
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/stream.js b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/stream.js
deleted file mode 100644
index ce2ad5b6ee57f4..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/lib/internal/streams/stream.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require('stream');
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/package.json b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/package.json
deleted file mode 100644
index ade59e71aa0f17..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/package.json
+++ /dev/null
@@ -1,68 +0,0 @@
-{
-  "name": "readable-stream",
-  "version": "3.6.2",
-  "description": "Streams3, a user-land copy of the stream library from Node.js",
-  "main": "readable.js",
-  "engines": {
-    "node": ">= 6"
-  },
-  "dependencies": {
-    "inherits": "^2.0.3",
-    "string_decoder": "^1.1.1",
-    "util-deprecate": "^1.0.1"
-  },
-  "devDependencies": {
-    "@babel/cli": "^7.2.0",
-    "@babel/core": "^7.2.0",
-    "@babel/polyfill": "^7.0.0",
-    "@babel/preset-env": "^7.2.0",
-    "airtap": "0.0.9",
-    "assert": "^1.4.0",
-    "bl": "^2.0.0",
-    "deep-strict-equal": "^0.2.0",
-    "events.once": "^2.0.2",
-    "glob": "^7.1.2",
-    "gunzip-maybe": "^1.4.1",
-    "hyperquest": "^2.1.3",
-    "lolex": "^2.6.0",
-    "nyc": "^11.0.0",
-    "pump": "^3.0.0",
-    "rimraf": "^2.6.2",
-    "tap": "^12.0.0",
-    "tape": "^4.9.0",
-    "tar-fs": "^1.16.2",
-    "util-promisify": "^2.1.0"
-  },
-  "scripts": {
-    "test": "tap -J --no-esm test/parallel/*.js test/ours/*.js",
-    "ci": "TAP=1 tap --no-esm test/parallel/*.js test/ours/*.js | tee test.tap",
-    "test-browsers": "airtap --sauce-connect --loopback airtap.local -- test/browser.js",
-    "test-browser-local": "airtap --open --local -- test/browser.js",
-    "cover": "nyc npm test",
-    "report": "nyc report --reporter=lcov",
-    "update-browser-errors": "babel -o errors-browser.js errors.js"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/nodejs/readable-stream"
-  },
-  "keywords": [
-    "readable",
-    "stream",
-    "pipe"
-  ],
-  "browser": {
-    "util": false,
-    "worker_threads": false,
-    "./errors": "./errors-browser.js",
-    "./readable.js": "./readable-browser.js",
-    "./lib/internal/streams/from.js": "./lib/internal/streams/from-browser.js",
-    "./lib/internal/streams/stream.js": "./lib/internal/streams/stream-browser.js"
-  },
-  "nyc": {
-    "include": [
-      "lib/**.js"
-    ]
-  },
-  "license": "MIT"
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/readable-browser.js b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/readable-browser.js
deleted file mode 100644
index adbf60de832f9d..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/readable-browser.js
+++ /dev/null
@@ -1,9 +0,0 @@
-exports = module.exports = require('./lib/_stream_readable.js');
-exports.Stream = exports;
-exports.Readable = exports;
-exports.Writable = require('./lib/_stream_writable.js');
-exports.Duplex = require('./lib/_stream_duplex.js');
-exports.Transform = require('./lib/_stream_transform.js');
-exports.PassThrough = require('./lib/_stream_passthrough.js');
-exports.finished = require('./lib/internal/streams/end-of-stream.js');
-exports.pipeline = require('./lib/internal/streams/pipeline.js');
diff --git a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/readable.js b/deps/npm/node_modules/node-gyp/node_modules/readable-stream/readable.js
deleted file mode 100644
index 9e0ca120ded827..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/readable-stream/readable.js
+++ /dev/null
@@ -1,16 +0,0 @@
-var Stream = require('stream');
-if (process.env.READABLE_STREAM === 'disable' && Stream) {
-  module.exports = Stream.Readable;
-  Object.assign(module.exports, Stream);
-  module.exports.Stream = Stream;
-} else {
-  exports = module.exports = require('./lib/_stream_readable.js');
-  exports.Stream = Stream || exports;
-  exports.Readable = exports;
-  exports.Writable = require('./lib/_stream_writable.js');
-  exports.Duplex = require('./lib/_stream_duplex.js');
-  exports.Transform = require('./lib/_stream_transform.js');
-  exports.PassThrough = require('./lib/_stream_passthrough.js');
-  exports.finished = require('./lib/internal/streams/end-of-stream.js');
-  exports.pipeline = require('./lib/internal/streams/pipeline.js');
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/signal-exit/LICENSE.txt b/deps/npm/node_modules/node-gyp/node_modules/signal-exit/LICENSE.txt
deleted file mode 100644
index eead04a12162dc..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/signal-exit/LICENSE.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-The ISC License
-
-Copyright (c) 2015, Contributors
-
-Permission to use, copy, modify, and/or distribute this software
-for any purpose with or without fee is hereby granted, provided
-that the above copyright notice and this permission notice
-appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
-LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
-OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/deps/npm/node_modules/node-gyp/node_modules/signal-exit/index.js b/deps/npm/node_modules/node-gyp/node_modules/signal-exit/index.js
deleted file mode 100644
index 93703f369265c6..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/signal-exit/index.js
+++ /dev/null
@@ -1,202 +0,0 @@
-// 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'
-}
-
-// some kind of non-node environment, just no-op
-/* istanbul ignore if */
-if (!processOk(process)) {
-  module.exports = function () {
-    return function () {}
-  }
-} else {
-  var assert = require('assert')
-  var signals = require('./signals.js')
-  var isWin = /^win/i.test(process.platform)
-
-  var EE = require('events')
-  /* istanbul ignore if */
-  if (typeof EE !== 'function') {
-    EE = EE.EventEmitter
-  }
-
-  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 = {}
-  }
-
-  // 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
-  }
-
-  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')
-
-    if (loaded === false) {
-      load()
-    }
-
-    var ev = 'exit'
-    if (opts && opts.alwaysLast) {
-      ev = 'afterexit'
-    }
-
-    var remove = function () {
-      emitter.removeListener(ev, cb)
-      if (emitter.listeners('exit').length === 0 &&
-          emitter.listeners('afterexit').length === 0) {
-        unload()
-      }
-    }
-    emitter.on(ev, cb)
-
-    return remove
-  }
-
-  var unload = function unload () {
-    if (!loaded || !processOk(global.process)) {
-      return
-    }
-    loaded = false
-
-    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
-
-  var emit = function emit (event, code, signal) {
-    /* istanbul ignore if */
-    if (emitter.emitted[event]) {
-      return
-    }
-    emitter.emitted[event] = true
-    emitter.emit(event, code, signal)
-  }
-
-  // { : , ... }
-  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)
-      }
-    }
-  })
-
-  module.exports.signals = function () {
-    return signals
-  }
-
-  var loaded = false
-
-  var load = function load () {
-    if (loaded || !processOk(global.process)) {
-      return
-    }
-    loaded = true
-
-    // 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
-
-    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)
-    }
-  }
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/signal-exit/package.json b/deps/npm/node_modules/node-gyp/node_modules/signal-exit/package.json
deleted file mode 100644
index e1a00311f9fbe5..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/signal-exit/package.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
-  "name": "signal-exit",
-  "version": "3.0.7",
-  "description": "when you want to fire an event no matter how a process exits.",
-  "main": "index.js",
-  "scripts": {
-    "test": "tap",
-    "snap": "tap",
-    "preversion": "npm test",
-    "postversion": "npm publish",
-    "prepublishOnly": "git push origin --follow-tags"
-  },
-  "files": [
-    "index.js",
-    "signals.js"
-  ],
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/tapjs/signal-exit.git"
-  },
-  "keywords": [
-    "signal",
-    "exit"
-  ],
-  "author": "Ben Coe ",
-  "license": "ISC",
-  "bugs": {
-    "url": "https://github.com/tapjs/signal-exit/issues"
-  },
-  "homepage": "https://github.com/tapjs/signal-exit",
-  "devDependencies": {
-    "chai": "^3.5.0",
-    "coveralls": "^3.1.1",
-    "nyc": "^15.1.0",
-    "standard-version": "^9.3.1",
-    "tap": "^15.1.1"
-  }
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/signal-exit/signals.js b/deps/npm/node_modules/node-gyp/node_modules/signal-exit/signals.js
deleted file mode 100644
index 3bd67a8a554e30..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/signal-exit/signals.js
+++ /dev/null
@@ -1,53 +0,0 @@
-// 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'
-  )
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/which/LICENSE b/deps/npm/node_modules/node-gyp/node_modules/which/LICENSE
deleted file mode 100644
index 19129e315fe593..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/which/LICENSE
+++ /dev/null
@@ -1,15 +0,0 @@
-The ISC License
-
-Copyright (c) Isaac Z. Schlueter and Contributors
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/deps/npm/node_modules/node-gyp/node_modules/which/README.md b/deps/npm/node_modules/node-gyp/node_modules/which/README.md
deleted file mode 100644
index cd833509f3bcc9..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/which/README.md
+++ /dev/null
@@ -1,54 +0,0 @@
-# which
-
-Like the unix `which` utility.
-
-Finds the first instance of a specified executable in the PATH
-environment variable.  Does not cache the results, so `hash -r` is not
-needed when the PATH changes.
-
-## USAGE
-
-```javascript
-var which = require('which')
-
-// async usage
-which('node', function (er, resolvedPath) {
-  // er is returned if no "node" is found on the PATH
-  // if it is found, then the absolute path to the exec is returned
-})
-
-// or promise
-which('node').then(resolvedPath => { ... }).catch(er => { ... not found ... })
-
-// sync usage
-// throws if not found
-var resolved = which.sync('node')
-
-// if nothrow option is used, returns null if not found
-resolved = which.sync('node', {nothrow: true})
-
-// Pass options to override the PATH and PATHEXT environment vars.
-which('node', { path: someOtherPath }, function (er, resolved) {
-  if (er)
-    throw er
-  console.log('found at %j', resolved)
-})
-```
-
-## CLI USAGE
-
-Same as the BSD `which(1)` binary.
-
-```
-usage: which [-as] program ...
-```
-
-## OPTIONS
-
-You may pass an options object as the second argument.
-
-- `path`: Use instead of the `PATH` environment variable.
-- `pathExt`: Use instead of the `PATHEXT` environment variable.
-- `all`: Return all matches, instead of just the first one.  Note that
-  this means the function returns an array of strings instead of a
-  single string.
diff --git a/deps/npm/node_modules/node-gyp/node_modules/which/bin/node-which b/deps/npm/node_modules/node-gyp/node_modules/which/bin/node-which
deleted file mode 100755
index 7cee3729eebdd0..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/which/bin/node-which
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/usr/bin/env node
-var which = require("../")
-if (process.argv.length < 3)
-  usage()
-
-function usage () {
-  console.error('usage: which [-as] program ...')
-  process.exit(1)
-}
-
-var all = false
-var silent = false
-var dashdash = false
-var args = process.argv.slice(2).filter(function (arg) {
-  if (dashdash || !/^-/.test(arg))
-    return true
-
-  if (arg === '--') {
-    dashdash = true
-    return false
-  }
-
-  var flags = arg.substr(1).split('')
-  for (var f = 0; f < flags.length; f++) {
-    var flag = flags[f]
-    switch (flag) {
-      case 's':
-        silent = true
-        break
-      case 'a':
-        all = true
-        break
-      default:
-        console.error('which: illegal option -- ' + flag)
-        usage()
-    }
-  }
-  return false
-})
-
-process.exit(args.reduce(function (pv, current) {
-  try {
-    var f = which.sync(current, { all: all })
-    if (all)
-      f = f.join('\n')
-    if (!silent)
-      console.log(f)
-    return pv;
-  } catch (e) {
-    return 1;
-  }
-}, 0))
diff --git a/deps/npm/node_modules/node-gyp/node_modules/which/package.json b/deps/npm/node_modules/node-gyp/node_modules/which/package.json
deleted file mode 100644
index 97ad7fbabc52b5..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/which/package.json
+++ /dev/null
@@ -1,43 +0,0 @@
-{
-  "author": "Isaac Z. Schlueter  (http://blog.izs.me)",
-  "name": "which",
-  "description": "Like which(1) unix command. Find the first instance of an executable in the PATH.",
-  "version": "2.0.2",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/node-which.git"
-  },
-  "main": "which.js",
-  "bin": {
-    "node-which": "./bin/node-which"
-  },
-  "license": "ISC",
-  "dependencies": {
-    "isexe": "^2.0.0"
-  },
-  "devDependencies": {
-    "mkdirp": "^0.5.0",
-    "rimraf": "^2.6.2",
-    "tap": "^14.6.9"
-  },
-  "scripts": {
-    "test": "tap",
-    "preversion": "npm test",
-    "postversion": "npm publish",
-    "prepublish": "npm run changelog",
-    "prechangelog": "bash gen-changelog.sh",
-    "changelog": "git add CHANGELOG.md",
-    "postchangelog": "git commit -m 'update changelog - '${npm_package_version}",
-    "postpublish": "git push origin --follow-tags"
-  },
-  "files": [
-    "which.js",
-    "bin/node-which"
-  ],
-  "tap": {
-    "check-coverage": true
-  },
-  "engines": {
-    "node": ">= 8"
-  }
-}
diff --git a/deps/npm/node_modules/node-gyp/node_modules/which/which.js b/deps/npm/node_modules/node-gyp/node_modules/which/which.js
deleted file mode 100644
index 82afffd2143749..00000000000000
--- a/deps/npm/node_modules/node-gyp/node_modules/which/which.js
+++ /dev/null
@@ -1,125 +0,0 @@
-const isWindows = process.platform === 'win32' ||
-    process.env.OSTYPE === 'cygwin' ||
-    process.env.OSTYPE === 'msys'
-
-const path = require('path')
-const COLON = isWindows ? ';' : ':'
-const isexe = require('isexe')
-
-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
diff --git a/deps/npm/node_modules/node-gyp/package.json b/deps/npm/node_modules/node-gyp/package.json
index 7e9fb648ab0825..80c63f2e72c3d9 100644
--- a/deps/npm/node_modules/node-gyp/package.json
+++ b/deps/npm/node_modules/node-gyp/package.json
@@ -11,7 +11,7 @@
     "bindings",
     "gyp"
   ],
-  "version": "9.4.0",
+  "version": "10.0.1",
   "installVersion": 11,
   "author": "Nathan Rajlich  (http://tootallnate.net)",
   "repository": {
@@ -24,28 +24,28 @@
   "dependencies": {
     "env-paths": "^2.2.0",
     "exponential-backoff": "^3.1.1",
-    "glob": "^7.1.4",
+    "glob": "^10.3.10",
     "graceful-fs": "^4.2.6",
-    "make-fetch-happen": "^11.0.3",
-    "nopt": "^6.0.0",
-    "npmlog": "^6.0.0",
-    "rimraf": "^3.0.2",
+    "make-fetch-happen": "^13.0.0",
+    "nopt": "^7.0.0",
+    "proc-log": "^3.0.0",
     "semver": "^7.3.5",
     "tar": "^6.1.2",
-    "which": "^2.0.2"
+    "which": "^4.0.0"
   },
   "engines": {
-    "node": "^12.13 || ^14.13 || >=16"
+    "node": "^16.14.0 || >=18.0.0"
   },
   "devDependencies": {
     "bindings": "^1.5.0",
+    "cross-env": "^7.0.3",
     "mocha": "^10.2.0",
     "nan": "^2.14.2",
     "require-inject": "^1.4.4",
-    "standard": "^14.3.4"
+    "standard": "^17.0.0"
   },
   "scripts": {
-    "lint": "standard */*.js test/**/*.js",
-    "test": "npm run lint && mocha --reporter=test/reporter.js test/test-download.js test/test-*"
+    "lint": "standard \"*/*.js\" \"test/**/*.js\" \".github/**/*.js\"",
+    "test": "cross-env NODE_GYP_NULL_LOGGER=true mocha --timeout 15000 test/test-download.js test/test-*"
   }
 }
diff --git a/deps/npm/node_modules/node-gyp/test/common.js b/deps/npm/node_modules/node-gyp/test/common.js
deleted file mode 100644
index b714ee29029d36..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/common.js
+++ /dev/null
@@ -1,3 +0,0 @@
-const envPaths = require('env-paths')
-
-module.exports.devDir = () => envPaths('node-gyp', { suffix: '' }).cache
diff --git a/deps/npm/node_modules/node-gyp/test/fixtures/VS_2017_BuildTools_minimal.txt b/deps/npm/node_modules/node-gyp/test/fixtures/VS_2017_BuildTools_minimal.txt
deleted file mode 100644
index 244f6b07982409..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/fixtures/VS_2017_BuildTools_minimal.txt
+++ /dev/null
@@ -1 +0,0 @@
-[{"path":"C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools","version":"15.9.28307.665","packages":["Microsoft.VisualStudio.Product.BuildTools","Microsoft.VisualStudio.Component.VC.CoreIde","Microsoft.VisualStudio.VC.Ide.Pro","Microsoft.VisualStudio.VC.Ide.Pro.Resources","Microsoft.VisualStudio.VC.Templates.Pro","Microsoft.VisualStudio.VC.Templates.Pro.Resources","Microsoft.VisualStudio.VC.Items.Pro","Microsoft.VisualStudio.PackageGroup.VC.CoreIDE.Reduced","Microsoft.VisualStudio.VC.Ide.MDD","Microsoft.VisualStudio.VC.Ide.x64","Microsoft.VisualStudio.PackageGroup.VC.CoreIDE.Express","Microsoft.VisualStudio.PackageGroup.Debugger.Script","Microsoft.VisualStudio.JavaScript.LanguageService","Microsoft.VisualStudio.JavaScript.LanguageService.Resources","Microsoft.VisualStudio.Debugger.Script.Msi","Microsoft.VisualStudio.Debugger.Script","Microsoft.VisualStudio.Debugger.Script","Microsoft.VisualStudio.Debugger.Script.Resources","Microsoft.VisualStudio.Debugger.Script.Resources","Microsoft.VisualStudio.VC.Ide.WinXPlus","Microsoft.VisualStudio.VC.Ide.Dskx","Microsoft.VisualStudio.VC.Ide.Dskx.Resources","Microsoft.VisualStudio.VC.Ide.Core","Microsoft.VisualStudio.VC.Ide.Core.Resources","Microsoft.VisualStudio.VC.Ide.Base","Microsoft.VisualStudio.VC.Ide.LanguageService","Microsoft.VisualStudio.VC.Ide.ResourceEditor","Microsoft.VisualStudio.VC.Ide.ResourceEditor.Resources","Microsoft.VisualStudio.VC.Ide.ProjectSystem","Microsoft.VisualStudio.VC.Ide.ProjectSystem.Resources","Microsoft.VisualStudio.VC.Ide.Core.VCProjectEngine","Microsoft.VisualStudio.VC.Ide.Core.VCProjectEngine.Resources","Microsoft.VisualStudio.VC.Ide.LanguageService.Resources","Microsoft.VisualStudio.VC.Ide.Base.Resources","Microsoft.VisualStudio.PackageGroup.Core","Microsoft.VisualStudio.TestTools.TeamFoundationClient","Microsoft.VisualStudio.PackageGroup.Debugger.Core","Microsoft.VisualStudio.Debugger.VSCodeDebuggerHost","Microsoft.VisualStudio.VC.Ide.Debugger","Microsoft.VisualStudio.VC.Ide.Debugger.Resources","Microsoft.VisualStudio.VC.Ide.Common","Microsoft.VisualStudio.VC.Ide.Common.Resources","Microsoft.VisualStudio.Debugger.Parallel","Microsoft.VisualStudio.Debugger.Parallel.Resources","Microsoft.VisualStudio.Debugger.CollectionAgents","Microsoft.VisualStudio.Debugger.Managed","Microsoft.CodeAnalysis.VisualStudio.Setup.Resources","Microsoft.CodeAnalysis.VisualStudio.Setup","Microsoft.CodeAnalysis.ExpressionEvaluator.Resources","Microsoft.CodeAnalysis.ExpressionEvaluator","Microsoft.VisualStudio.Debugger.Managed.Resources","Microsoft.VisualStudio.Debugger.Remote","Microsoft.VisualStudio.Debugger.Remote","Microsoft.VisualStudio.Debugger.Remote.Resources","Microsoft.VisualStudio.Debugger.Remote.Resources","Microsoft.VisualStudio.Debugger","Microsoft.VisualStudio.VC.MSVCDis","Microsoft.VisualStudio.ScriptedHost","Microsoft.VisualStudio.ScriptedHost.Targeted","Microsoft.VisualStudio.ScriptedHost.Resources","Microsoft.IntelliTrace.DiagnosticsHub","Microsoft.VisualStudio.Debugger.Resources","Microsoft.PackageGroup.ClientDiagnostics","Microsoft.VisualStudio.AppResponsiveness","Microsoft.VisualStudio.AppResponsiveness.Targeted","Microsoft.VisualStudio.AppResponsiveness.Resources","Microsoft.VisualStudio.ClientDiagnostics","Microsoft.VisualStudio.ClientDiagnostics.Targeted","Microsoft.VisualStudio.ClientDiagnostics.Resources","Microsoft.VisualStudio.PackageGroup.CommunityCore","Microsoft.VisualStudio.ProjectSystem.Full","Microsoft.VisualStudio.ProjectSystem","Microsoft.VisualStudio.Community.x86","Microsoft.VisualStudio.Community.x64","Microsoft.VisualStudio.Community","Microsoft.IntelliTrace.CollectorCab","Microsoft.VisualStudio.Community.Resources","Microsoft.VisualStudio.WebSiteProject.DTE","Microsoft.MSHtml","Microsoft.VisualStudio.Community.Msi.Resources","Microsoft.VisualStudio.Community.Msi","Microsoft.VisualStudio.MinShell.Interop.Msi","Microsoft.VisualStudio.PackageGroup.CoreEditor","PortableFacades","Microsoft.VisualStudio.VirtualTree","Microsoft.VisualStudio.PackageGroup.Progression","Microsoft.VisualStudio.PerformanceProvider","Microsoft.VisualStudio.GraphModel","Microsoft.VisualStudio.GraphProvider","Microsoft.DiaSymReader","Microsoft.VisualStudio.TextMateGrammars","Microsoft.VisualStudio.PackageGroup.TeamExplorer","Microsoft.TeamFoundation.OfficeIntegration","Microsoft.TeamFoundation.OfficeIntegration.Resources","Microsoft.VisualStudio.TeamExplorer","Microsoft.ServiceHub","Microsoft.VisualStudio.ProjectServices","Microsoft.VisualStudio.SLNX.VSIX","Microsoft.VisualStudio.FileHandler.Msi","Microsoft.VisualStudio.FileHandler.Msi","Microsoft.VisualStudio.PackageGroup.MinShell","Microsoft.VisualStudio.MinShell.Msi","Microsoft.VisualStudio.MinShell.Msi.Resources","Microsoft.VisualStudio.MinShell.Interop","Microsoft.VisualStudio.Log","Microsoft.VisualStudio.Log.Targeted","Microsoft.VisualStudio.Log.Resources","Microsoft.VisualStudio.Finalizer","Microsoft.VisualStudio.CoreEditor","Microsoft.VisualStudio.Connected","Microsoft.VisualStudio.Connected.Resources","Microsoft.VisualStudio.MinShell","Microsoft.VisualStudio.MinShell.Platform","Microsoft.VisualStudio.MinShell.Platform.Resources","Microsoft.VisualStudio.MefHosting","Microsoft.VisualStudio.MefHosting.Resources","Microsoft.VisualStudio.Initializer","Microsoft.VisualStudio.ExtensionManager","Microsoft.VisualStudio.Editors","Microsoft.Net.4.TargetingPack","Microsoft.VisualStudio.Component.Windows10SDK.17134","Win10SDK_10.0.17134","Microsoft.VisualStudio.Component.VC.Tools.x86.x64","Microsoft.VisualCpp.CodeAnalysis.Extensions","Microsoft.VisualCpp.CodeAnalysis.Extensions.X86","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X86","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X86.Resources","Microsoft.VisualCpp.CodeAnalysis.Extensions.X64","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X64","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X64.Resources","Microsoft.VisualStudio.Component.Static.Analysis.Tools","Microsoft.VisualStudio.StaticAnalysis","Microsoft.VisualStudio.StaticAnalysis.Resources","Microsoft.VisualCpp.Tools.HostX64.TargetX86","Microsoft.VisualCpp.VCTip.HostX64.TargetX86","Microsoft.VisualCpp.Tools.HostX64.TargetX86.Resources","Microsoft.VisualCpp.Tools.HostX64.TargetX64","Microsoft.VisualCpp.VCTip.HostX64.TargetX64","Microsoft.VisualCpp.Tools.HostX64.TargetX64.Resources","Microsoft.VisualCpp.Premium.Tools.HostX86.TargetX64","Microsoft.VisualCpp.Premium.Tools.Hostx86.Targetx64.Resources","Microsoft.VisualCpp.Premium.Tools.HostX86.TargetX86","Microsoft.VisualCpp.Premium.Tools.HostX86.TargetX86.Resources","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX86","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX86.Resources","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX64","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX64.Resources","Microsoft.VisualCpp.PGO.X86","Microsoft.VisualCpp.PGO.X64","Microsoft.VisualCpp.PGO.Headers","Microsoft.VisualCpp.CRT.x86.Store","Microsoft.VisualCpp.CRT.x86.OneCore.Desktop","Microsoft.VisualCpp.CRT.x64.Store","Microsoft.VisualCpp.CRT.x64.OneCore.Desktop","Microsoft.VisualCpp.CRT.Redist.x86.OneCore.Desktop","Microsoft.VisualCpp.CRT.Redist.x64.OneCore.Desktop","Microsoft.VisualCpp.CRT.ClickOnce.Msi","Microsoft.VisualStudio.PackageGroup.VC.Tools.x86","Microsoft.VisualCpp.Tools.HostX86.TargetX64","Microsoft.VisualCpp.VCTip.hostX86.targetX64","Microsoft.VisualCpp.Tools.Hostx86.Targetx64.Resources","Microsoft.VisualCpp.Tools.HostX86.TargetX86","Microsoft.VisualCpp.VCTip.hostX86.targetX86","Microsoft.VisualCpp.Tools.HostX86.TargetX86.Resources","Microsoft.VisualCpp.Tools.Core.Resources","Microsoft.VisualCpp.Tools.Core.x86","Microsoft.VisualCpp.Tools.Common.Utils","Microsoft.VisualCpp.Tools.Common.Utils.Resources","Microsoft.VisualCpp.DIA.SDK","Microsoft.VisualCpp.CRT.x86.Desktop","Microsoft.VisualCpp.CRT.x64.Desktop","Microsoft.VisualCpp.CRT.Source","Microsoft.VisualCpp.CRT.Redist.X86","Microsoft.VisualCpp.CRT.Redist.X64","Microsoft.VisualCpp.CRT.Redist.Resources","Microsoft.VisualCpp.RuntimeDebug.14","Microsoft.VisualCpp.RuntimeDebug.14","Microsoft.VisualCpp.Redist.14","Microsoft.VisualCpp.Redist.14","Microsoft.VisualCpp.CRT.Headers","Microsoft.VisualStudio.VC.MSBuild.X86","Microsoft.VisualStudio.VC.MSBuild.X64","Microsoft.VS.VC.MSBuild.X64.Resources","Microsoft.VisualStudio.VC.MSBuild.Base","Microsoft.VisualStudio.VC.MSBuild.Base.Resources","Microsoft.VisualStudio.VC.MSBuild.ARM","Microsoft.VisualStudio.Workload.MSBuildTools","Microsoft.VisualStudio.Component.CoreBuildTools","Microsoft.VisualStudio.Setup.Configuration","Microsoft.VisualStudio.PackageGroup.VsDevCmd","Microsoft.VisualStudio.VsDevCmd.Ext.NetFxSdk","Microsoft.VisualStudio.VsDevCmd.Core.WinSdk","Microsoft.VisualStudio.VsDevCmd.Core.DotNet","Microsoft.VisualStudio.VC.DevCmd","Microsoft.VisualStudio.VC.DevCmd.Resources","Microsoft.VisualStudio.BuildTools.Resources","Microsoft.VisualStudio.Net.Eula.Resources","Microsoft.Build.Dependencies","Microsoft.Build.FileTracker.Msi","Microsoft.Component.MSBuild","Microsoft.PythonTools.BuildCore.Vsix","Microsoft.NuGet.Build.Tasks","Microsoft.VisualStudio.Component.Roslyn.Compiler","Microsoft.CodeAnalysis.Compilers.Resources","Microsoft.CodeAnalysis.Compilers","Microsoft.Net.PackageGroup.4.6.1.Redist","Microsoft.VisualStudio.NativeImageSupport","Microsoft.Build"]}]
diff --git a/deps/npm/node_modules/node-gyp/test/fixtures/VS_2017_Community_workload.txt b/deps/npm/node_modules/node-gyp/test/fixtures/VS_2017_Community_workload.txt
deleted file mode 100644
index dd5e77dafb9dfe..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/fixtures/VS_2017_Community_workload.txt
+++ /dev/null
@@ -1 +0,0 @@
-[{"path":"C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community","version":"15.9.28307.665","packages":["Microsoft.VisualStudio.Component.Windows10SDK.IpOverUsb","Win10SDK_IpOverUsb","Microsoft.VisualStudio.Component.VC.ATL.ARM64","Microsoft.VisualCpp.ATL.ARM64","Microsoft.VisualStudio.Component.VC.ATL.ARM","Microsoft.VisualCpp.ATL.ARM","Microsoft.VisualStudio.Component.VC.Tools.ARM","Microsoft.VisualCpp.Tools.HostX64.TargetX86.Resources","Microsoft.VisualStudio.Graphics.Analyzer.Resources","Microsoft.Icecap.Analysis","Microsoft.VisualCpp.CRT.Redist.arm.OneCore.Desktop","Microsoft.VisualCpp.CRT.arm.Store","Microsoft.VisualCpp.CRT.arm.Desktop","Microsoft.VisualStudio.PackageGroup.VC.Tools.x64.ARM","Microsoft.VisualCpp.Premium.Tools.Hostx86.Targetarm","Microsoft.VisualCpp.Premium.Tools.HostX86.TargetARM.Resources","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetARM","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetARM.Resources","Microsoft.VisualCpp.Premium.Tools.ARM.Base","Microsoft.VisualCpp.Premium.Tools.ARM.Base.Resources","Microsoft.VisualCpp.PGO.ARM","Microsoft.VisualCpp.Tools.HostX64.TargetX64","Microsoft.VisualStudio.Product.Community","Microsoft.VisualCpp.Tools.Hostx86.Targetarm","Microsoft.VisualStudio.Component.VC.Tools.ARM64","Microsoft.VisualStudio.VC.MSBuild.Arm64","Microsoft.VisualCpp.CRT.Redist.ARM64.OneCore.Desktop","Microsoft.VisualCpp.VCTip.HostX64.TargetX64","Microsoft.VisualCpp.CRT.ARM64.OneCore.Desktop","Microsoft.VisualCpp.CRT.ARM64.Store","Microsoft.VisualCpp.CRT.ARM64.Desktop","Microsoft.VisualCpp.Tools.HostX64.TargetX64.Resources","Microsoft.Icecap.Analysis.Resources","Microsoft.VisualCpp.VCTip.hostX86.targetARM","Microsoft.VisualStudio.PackageGroup.VC.Tools.x64.ARM64","Microsoft.VisualCpp.Tools.Core","Microsoft.VisualCpp.PGO.ARM64","Microsoft.VisualCpp.Premium.Tools.Hostx86.Targetarm64","Microsoft.VisualCpp.Premium.Tools.HostX86.TargetARM64.Resources","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetARM64","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetARM64.Resources","Microsoft.VisualCpp.Premium.Tools.ARM64.Base","Microsoft.VisualCpp.Tools.HostX86.TargetX64","Microsoft.VisualCpp.Tools.HostX86.TargetARM.Resources","Microsoft.VisualCpp.CRT.Redist.ARM64","Microsoft.VisualCpp.CRT.arm.OneCore.Desktop","Microsoft.VisualCpp.CodeAnalysis.Extensions.X86","Microsoft.VisualCpp.CodeAnalysis.Extensions.X64","Microsoft.VisualCpp.VCTip.HostX64.TargetX86","Component.WixToolset.VisualStudioExtension.Dev15","WixToolset.VisualStudioExtension.Dev15","Microsoft.VisualCpp.MFC.X64","Microsoft.VisualCpp.ATL.Headers","Microsoft.VisualStudio.Component.VC.CMake.Project","Microsoft.VisualStudio.VC.CMake","Microsoft.VisualStudio.VC.CMake.Project","Microsoft.VisualStudio.Component.Windows10SDK.17763","Microsoft.VisualStudio.VC.MSBuild.Base.Resources","MLGen","Microsoft.VisualStudio.Graphics.Analyzer","Microsoft.VisualStudio.Component.TestTools.Core","Microsoft.VisualCpp.Tools.Core.x86","Microsoft.VisualCpp.CRT.x86.OneCore.Desktop","Microsoft.VisualCpp.DIA.SDK","Microsoft.VisualCpp.CRT.x64.OneCore.Desktop","Microsoft.VisualCpp.CRT.ClickOnce.Msi","Microsoft.VisualStudio.NuGet.Licenses","SQLCommon","Microsoft.VisualStudio.VC.MSBuild.X86","Microsoft.VisualCpp.Tools.HostX64.TargetARM","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X64","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X64.Resources","Microsoft.VisualCpp.HTMLHelpWorkshop.Msi","Microsoft.Icecap.Collection.Msi.Resources","Microsoft.VisualCpp.Tools.Hostx86.Targetx64.Resources","Microsoft.VisualCpp.VCTip.hostX64.targetARM","Microsoft.VisualStudio.VC.Ide.Dskx.Resources","Microsoft.VisualStudio.VC.Templates.UnitTest","Microsoft.VisualStudio.TestTools.TestPlatform.V1.CPP","Microsoft.VisualStudio.VC.Ide.Core","Microsoft.VisualStudio.Graphics.Appid","Microsoft.VisualCpp.ATL.Source","Microsoft.VisualStudio.VC.Ide.Core.Resources","Microsoft.VisualStudio.Debugger.ImmersiveActivateHelper.Msi","Microsoft.VisualStudio.Debugger.JustInTime","Microsoft.DiagnosticsHub.CpuSampling","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Common","Microsoft.VisualStudio.TestTools.TP.Legacy.Common.Res","Microsoft.VisualStudio.ProTools.Resources","Microsoft.VisualStudio.Community.Msi","Microsoft.VisualCpp.Tools.HostX64.TargetARM.Resources","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Agent","Microsoft.Component.MSBuild","Microsoft.VisualStudio.Graphics.Msi","Microsoft.VisualStudio.WebToolsExtensions","Microsoft.VisualCpp.Tools.Hostx86.Targetarm64","Microsoft.VisualStudio.TextTemplating.MSBuild","Microsoft.VisualCpp.VCTip.hostX86.targetARM64","Microsoft.VisualStudio.VC.Ide.Core.VCProjectEngine","Microsoft.VisualCpp.Tools.HostX86.TargetARM64.Resources","Microsoft.VisualStudio.RazorExtension","Microsoft.VisualCpp.CRT.x86.Store","Microsoft.VisualCpp.Tools.Core.Resources","Microsoft.VisualStudio.Debugger.Script","Microsoft.VisualStudio.Debugger.Script","Microsoft.VisualCpp.MFC.Source","Microsoft.VisualCpp.CRT.x86.Desktop","Microsoft.VisualStudio.VC.MSBuild.X64","Microsoft.VisualStudio.VC.Items.Pro","Microsoft.VisualStudio.Graphics.Viewers","Microsoft.VisualCpp.CRT.x64.Desktop","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X86.Resources","Microsoft.VisualCpp.MFC.Redist.X86","Microsoft.VisualStudio.WebToolsExtensions.Chip","Microsoft.DiagnosticsHub.Runtime.Resources","Microsoft.DiagnosticsHub.CpuSampling.Targeted","Microsoft.VisualStudio.VC.Ide.LanguageService.Resources","Microsoft.VisualStudio.Component.VC.DiagnosticTools","Microsoft.VisualCpp.MFC.Redist.X64","Microsoft.VisualStudio.PackageGroup.TestTools.Native","Microsoft.VisualStudio.Graphics.Viewers.Resources","Microsoft.VisualCpp.MFC.MBCS","Microsoft.VisualStudio.Debugger.Remote.Resources","Microsoft.VisualStudio.Component.TextTemplating","Win10SDK_10.0.17763","Microsoft.VisualStudio.VC.Ide.Base.Resources","Microsoft.VisualCpp.MFC.MBCS.X64","Microsoft.VisualStudio.PackageGroup.TestTools.CodeCoverage","Microsoft.VisualStudio.Graphics.EnableTools","Microsoft.VisualStudio.Graphics.Appid.Resources","Microsoft.VisualStudio.VC.MSBuild.Base","Microsoft.VisualStudio.VC.MSBuild.ARM","Microsoft.VisualCpp.MFC.Headers","Microsoft.VisualCpp.CRT.Redist.x86.OneCore.Desktop","Microsoft.VisualCpp.Tools.HostX86.TargetX86","Microsoft.VisualStudio.VC.Ide.Base","Microsoft.VisualStudio.Graphics.Analyzer.Targeted","Microsoft.VisualCpp.CRT.Headers","Microsoft.DiagnosticsHub.Runtime.Targeted","Microsoft.VisualCpp.Premium.Tools.HostX86.TargetX86","Microsoft.VisualCpp.Tools.HostX64.TargetARM64","Microsoft.VisualCpp.VCTip.hostX64.targetARM64","Microsoft.VisualCpp.Premium.Tools.HostX86.TargetX86.Resources","Microsoft.Icecap.Collection.Msi","Microsoft.VisualCpp.ATL.X86","Microsoft.VisualCpp.Tools.HostX64.TargetARM64.Resources","Microsoft.VisualStudio.Component.VC.ATLMFC","Microsoft.VisualCpp.VCTip.hostX86.targetX86","Microsoft.Icecap.Collection.Msi.Resources.Targeted","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX86","Microsoft.VisualStudio.Component.Graphics.Tools","Microsoft.VisualStudio.WebTools.Resources","Microsoft.VisualCpp.ATL.X64","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX86.Resources","Microsoft.VisualStudio.Component.Graphics.Win81","Microsoft.VisualStudio.VC.Ide.MDD","Microsoft.VisualStudio.VC.Ide.ResourceEditor","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX64","Microsoft.Icecap.Analysis.Resources.Targeted","Microsoft.VisualStudio.Debugger.Script.Msi","Microsoft.VisualStudio.Component.VC.CoreIde","Microsoft.VisualStudio.VC.Ide.MFC.Resources","Microsoft.VisualStudio.Debugger.Script.Resources","Microsoft.VisualStudio.PackageGroup.VC.Tools.x86","Microsoft.VisualStudio.TextTemplating.Core","Microsoft.VisualStudio.JavaScript.LanguageService","Microsoft.VisualStudio.VC.Ide.ResourceEditor.Resources","Microsoft.VisualStudio.VC.Ide.ProjectSystem.Resources","Microsoft.VisualStudio.Component.VC.TestAdapterForBoostTest","Microsoft.VisualStudio.VC.Ide.ProjectSystem","Microsoft.VisualStudio.VC.Ide.Dskx","Microsoft.VisualCpp.Tools.HostX86.TargetX86.Resources","Microsoft.CredentialProvider","Microsoft.VisualStudio.VC.Templates.Desktop","Microsoft.VisualStudio.VC.Ide.Pro.Resources","Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Core","Microsoft.VisualStudio.TextTemplating.Integration","Microsoft.VisualStudio.Component.NuGet","Microsoft.VisualStudio.PackageGroup.VC.CoreIDE.Reduced","Microsoft.VisualCpp.PGO.Headers","Microsoft.DiagnosticsHub.Collection","Microsoft.Icecap.Collection.Msi.Targeted","Microsoft.VisualStudio.VC.Ide.LanguageService","Microsoft.VisualStudio.WebTools.WSP.FSA","Microsoft.VisualStudio.Graphics.Msi","Microsoft.VisualCpp.CRT.Redist.X86","Microsoft.VisualStudio.Branding.Community","Microsoft.VisualStudio.VC.Ide.x64","Microsoft.VisualStudio.WebToolsExtensions.Common","Microsoft.VisualStudio.WebTools.MSBuild","Microsoft.VisualStudio.NuGet.Core","Microsoft.DiagnosticsHub.Collection.Service","Microsoft.VisualStudio.VC.Ide.Core.VCProjectEngine.Resources","Microsoft.CodeAnalysis.ExpressionEvaluator","Microsoft.VisualCpp.CRT.Redist.X64","Microsoft.VisualCpp.RuntimeDebug.14","Microsoft.VS.VC.MSBuild.X64.Resources","Microsoft.VisualCpp.CRT.Source","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Tips.Resources","Microsoft.VisualStudio.VC.Ide.WinXPlus","Microsoft.VisualCpp.RuntimeDebug.14","Microsoft.VisualCpp.Redist.14.Latest","Microsoft.VisualCpp.Premium.Tools.HostX86.TargetX64","Microsoft.VisualCpp.CRT.Redist.Resources","Microsoft.VisualCpp.Redist.14.Latest","Microsoft.Net.4.TargetingPack","Microsoft.VisualStudio.Debugger.Script.Resources","Microsoft.VisualCpp.CRT.x64.Store","Microsoft.VisualStudio.VC.Ide.Debugger.Resources","Microsoft.DiaSymReader.Native","Microsoft.VisualCpp.Redist.14","Microsoft.VisualCpp.Redist.14","Microsoft.VisualStudio.StaticAnalysis","Microsoft.VisualStudio.TestTools.TeamFoundationClient","Microsoft.VisualStudio.TestTools.TestPlatform.V1.CLI","Microsoft.VisualStudio.VC.Ide.Common","Microsoft.VisualStudio.Community.Extra.Resources","Microsoft.VisualStudio.Component.Roslyn.LanguageServices","Microsoft.DiagnosticsHub.Collection.StopService.Install","Microsoft.VisualStudio.InteractiveWindow","Microsoft.PackageGroup.DiagnosticsHub.Platform","Microsoft.VisualStudio.StaticAnalysis.Resources","Microsoft.VisualStudio.Debugger.Remote","Microsoft.VisualStudio.VC.Ide.Common.Resources","Microsoft.VisualCpp.Tools.HostX64.TargetX86","Microsoft.VisualStudio.VC.DevCmd","Microsoft.VisualStudio.Community.Extra","Microsoft.VisualStudio.TestTools.TP.Legacy.Tips.Msi","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.TestTools","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Core.Resources","Microsoft.VisualStudio.PackageGroup.TestTools.Core","Microsoft.VisualStudio.PackageGroup.TestTools.TestPlatform.V2.CLI","Microsoft.VisualStudio.Debugger.Remote","Microsoft.VisualStudio.PackageGroup.TestTools.TestPlatform.V1.CLI","Microsoft.VisualStudio.Component.VC.Tools.x86.x64","Microsoft.VisualStudio.TestTools.Pex.Common","Microsoft.VisualStudio.PackageGroup.TestTools.TestPlatform.Legacy","Microsoft.VisualStudio.PackageGroup.MinShell.Interop","Microsoft.CodeAnalysis.ExpressionEvaluator.Resources","Microsoft.VisualCpp.CodeAnalysis.Extensions","Microsoft.VisualStudio.PackageGroup.CoreEditor","Microsoft.VisualStudio.Component.Roslyn.Compiler","Microsoft.VisualStudio.ScriptedHost.Targeted","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Professional","Microsoft.VisualStudio.Debugger.Resources","Microsoft.VisualStudio.Debugger.Parallel","Microsoft.VisualStudio.Debugger.Parallel.Resources","Microsoft.VisualCpp.PGO.X64","Microsoft.VisualStudio.PackageGroup.TestTools.TestPlatform.IDE","Microsoft.VisualStudio.GraphModel","Microsoft.VisualStudio.PackageGroup.TestTools.DataCollectors","sqlsysclrtypes","Microsoft.VisualStudio.ProTools","Component.Microsoft.VisualStudio.RazorExtension","Microsoft.VisualStudio.TestTools.TestPlatform.V2.CLI","Microsoft.Build.Dependencies","Microsoft.VisualStudio.WebTools.WSP.FSA.Resources","Microsoft.VisualStudio.Component.Static.Analysis.Tools","Microsoft.VisualStudio.VC.Ide.ATL.Resources","Microsoft.VisualStudio.VC.Templates.UnitTest.Resources","Microsoft.VisualStudio.Debugger.Managed","Microsoft.VisualStudio.Workload.NativeDesktop","Microsoft.VisualStudio.Component.VC.TestAdapterForGoogleTest","Microsoft.VisualStudio.Debugger.JustInTime.Msi","Microsoft.Net.PackageGroup.4.6.1.Redist","Microsoft.VisualStudio.Debugger.VSCodeDebuggerHost","sqlsysclrtypes","Microsoft.VisualStudio.Debugger.Managed.Resources","Microsoft.VisualStudio.TestTools.TP.Legacy.Tips.Common","Microsoft.VisualStudio.VC.Ide.Debugger","Microsoft.VisualStudio.AppResponsiveness","Microsoft.VisualStudio.Debugger.Remote.Resources","Microsoft.VisualStudio.TestTools.TestWIExtension","Microsoft.VisualStudio.VC.Ide.Pro","Microsoft.VisualStudio.PackageGroup.Debugger.Core","Microsoft.VisualStudio.PackageGroup.VC.CoreIDE.Express","Microsoft.VisualStudio.WebTools","Microsoft.VisualStudio.Component.VC.Redist.14.Latest","Microsoft.VisualStudio.VsDevCmd.Core.WinSdk","Microsoft.VisualStudio.TestTools.TestPlatform.IDE","Microsoft.VisualStudio.TextTemplating.Integration.Resources","Microsoft.VisualStudio.Debugger.CollectionAgents","Microsoft.VisualStudio.Debugger","Microsoft.VisualStudio.PackageGroup.Debugger.Script","Microsoft.VisualStudio.VC.MSVCDis","Microsoft.VisualStudio.ScriptedHost","Microsoft.VisualStudio.ClientDiagnostics.Targeted","Microsoft.VisualStudio.ScriptedHost.Resources","Microsoft.TeamFoundation.OfficeIntegration.Resources","Microsoft.IntelliTrace.DiagnosticsHub","Microsoft.VisualStudio.JavaScript.LanguageService.Resources","Microsoft.VisualStudio.VC.Ide.TestAdapterForGoogleTest","Microsoft.VisualStudio.PackageGroup.Community","Microsoft.VisualStudio.ClientDiagnostics","Microsoft.VisualStudio.Component.Windows10SDK.17134","Microsoft.VisualStudio.PackageGroup.Core","PortableFacades","Microsoft.DiaSymReader","Microsoft.DiagnosticsHub.Runtime","Microsoft.VisualStudio.Component.CoreEditor","Microsoft.VisualStudio.AppResponsiveness.Targeted","Microsoft.VisualStudio.AppResponsiveness.Resources","Microsoft.VisualStudio.Community","Microsoft.TeamFoundation.OfficeIntegration","Microsoft.VisualStudio.WebSiteProject.DTE","Microsoft.VisualStudio.ClientDiagnostics.Resources","Microsoft.VisualStudio.ProjectSystem.Full","Microsoft.VisualStudio.ProjectSystem","Microsoft.VisualCpp.Tools.Common.UtilsPrereq","Microsoft.IntelliTrace.CollectorCab","Microsoft.VisualStudio.Community.Resources","Microsoft.VisualCpp.Tools.Common.Utils","Microsoft.ServiceHub","Microsoft.VisualStudio.Editors","Microsoft.VisualStudio.TeamExplorer","Microsoft.CodeAnalysis.VisualStudio.InteractiveComponents.Resources","Microsoft.VisualStudio.MinShell.Interop.Msi","Microsoft.VisualStudio.GraphProvider","Microsoft.CodeAnalysis.VisualStudio.InteractiveComponents","Microsoft.CodeAnalysis.VisualStudio.Setup.Interactive.Resources","Microsoft.CodeAnalysis.VisualStudio.Setup.Resources","Microsoft.VisualStudio.Community.x86","Microsoft.VisualStudio.Community.x64","Microsoft.CodeAnalysis.VisualStudio.Setup","Microsoft.NuGet.Build.Tasks","Microsoft.PackageGroup.ClientDiagnostics","Microsoft.CodeAnalysis.Compilers.Resources","Microsoft.CodeAnalysis.Compilers","Microsoft.VisualCpp.Tools.Common.Utils.Resources","Microsoft.VisualStudio.Net.Eula.Resources","Microsoft.VisualStudio.PackageGroup.CommunityCore","Microsoft.Build","Microsoft.VisualStudio.VC.Ide.TestAdapterForBoostTest","Microsoft.VisualStudio.VC.Ide.ATL","Microsoft.VisualStudio.TextMateGrammars","Microsoft.VisualStudio.Workload.CoreEditor","Microsoft.VisualStudio.MinShell.Interop","Microsoft.Build.FileTracker.Msi","Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core","Microsoft.MSHtml","Microsoft.VisualStudio.Community.Msi.Resources","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Tips","Microsoft.VisualStudio.Devenv.Msi","Microsoft.VisualStudio.Component.VC.ATL","Microsoft.VisualStudio.VC.Templates.Pro","Microsoft.VisualCpp.CRT.Redist.x64.OneCore.Desktop","Microsoft.VisualStudio.SLNX.VSIX","Microsoft.VisualStudio.CoreEditor","Win10SDK_10.0.17134","Microsoft.VisualStudio.VsDevCmd.Ext.NetFxSdk","Microsoft.VisualStudio.Component.Debugger.JustInTime","Microsoft.VisualStudio.VC.Ide.MFC","Microsoft.VisualStudio.VsDevCmd.Core.DotNet","Microsoft.VisualStudio.PackageGroup.VsDevCmd","Microsoft.VisualStudio.Finalizer","Microsoft.VisualStudio.VirtualTree","Microsoft.VisualStudio.FileHandler.Msi","Microsoft.VisualStudio.ProjectServices","Microsoft.VisualStudio.VC.DevCmd.Resources","Microsoft.VisualStudio.MinShell","Microsoft.VisualStudio.PackageGroup.Progression","Microsoft.VisualStudio.PerformanceProvider","Microsoft.VisualStudio.Connected.Resources","Microsoft.VisualStudio.Log","Microsoft.VisualStudio.PackageGroup.TeamExplorer","Microsoft.VisualStudio.Log.Targeted","Microsoft.VisualStudio.MinShell.Platform","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X86","Microsoft.VisualStudio.FileHandler.Msi","Microsoft.VisualStudio.VC.Templates.Pro.Resources","Microsoft.VisualStudio.Devenv","Microsoft.VisualCpp.VCTip.hostX86.targetX64","Microsoft.VisualStudio.Devenv.Resources","Microsoft.VisualStudio.MinShell.Platform.Resources","Microsoft.VisualStudio.Connected","Microsoft.VisualStudio.MefHosting","Microsoft.DiagnosticsHub.Collection.StopService.Uninstall","Microsoft.VisualStudio.PackageGroup.MinShell","Microsoft.VisualStudio.MefHosting.Resources","Microsoft.VisualCpp.MFC.X86","Microsoft.VisualStudio.Log.Resources","Microsoft.Icecap.Analysis.Targeted","Microsoft.VisualCpp.Premium.Tools.Hostx86.Targetx64.Resources","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX64.Resources","Microsoft.VisualCpp.PGO.X86","Microsoft.VisualStudio.ExtensionManager","Microsoft.VisualStudio.MinShell.x86","Microsoft.VisualStudio.MinShell.Msi","Microsoft.VisualStudio.Setup.Configuration","Microsoft.VisualStudio.LanguageServer","Microsoft.VisualStudio.NativeImageSupport","Microsoft.VisualStudio.MinShell.Msi.Resources","Microsoft.VisualStudio.Devenv.Config","Microsoft.VisualStudio.MinShell.Resources","Microsoft.VisualStudio.Initializer","Microsoft.Net.PackageGroup.4.6.Redist"]}]
diff --git a/deps/npm/node_modules/node-gyp/test/fixtures/VS_2017_Express.txt b/deps/npm/node_modules/node-gyp/test/fixtures/VS_2017_Express.txt
deleted file mode 100644
index c4b3b5f2b01635..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/fixtures/VS_2017_Express.txt
+++ /dev/null
@@ -1 +0,0 @@
-[{"path":"C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\WDExpress","version":"15.9.28307.858","packages":["Microsoft.VisualStudio.Product.WDExpress","Microsoft.VisualStudio.Workload.WDExpress","Microsoft.VisualStudio.Component.Windows10SDK.17763","MLGen","Win10SDK_10.0.17763","Microsoft.VisualStudio.Component.Windows10SDK.14393","Win10SDK_10.0.14393.795","Microsoft.VisualStudio.VC.Items.Pro","Microsoft.VisualStudio.VC.Ide.Pro","Microsoft.VisualStudio.VC.Ide.Pro.Resources","Microsoft.VisualStudio.Component.VC.Tools.ARM64","Microsoft.VisualStudio.VC.MSBuild.Arm64","Microsoft.VisualCpp.CRT.Redist.ARM64.OneCore.Desktop","Microsoft.VisualCpp.CRT.Redist.ARM64","Microsoft.VisualCpp.CRT.ARM64.OneCore.Desktop","Microsoft.VisualCpp.CRT.ARM64.Store","Microsoft.VisualCpp.CRT.ARM64.Desktop","Microsoft.VisualCpp.Tools.Hostx86.Targetarm64","Microsoft.VisualCpp.VCTip.hostX86.targetARM64","Microsoft.VisualCpp.Tools.HostX86.TargetARM64.Resources","Microsoft.VisualStudio.Component.VC.Tools.ARM","Microsoft.VisualCpp.Tools.Hostx86.Targetarm","Microsoft.VisualCpp.VCTip.hostX86.targetARM","Microsoft.VisualCpp.Tools.HostX86.TargetARM.Resources","Microsoft.VisualCpp.CRT.x86.Store","Microsoft.VisualCpp.CRT.x86.OneCore.Desktop","Microsoft.VisualCpp.CRT.x64.Store","Microsoft.VisualCpp.CRT.x64.OneCore.Desktop","Microsoft.VisualCpp.CRT.Redist.arm.OneCore.Desktop","Microsoft.VisualCpp.CRT.arm.OneCore.Desktop","Microsoft.VisualCpp.CRT.arm.Store","Microsoft.VisualCpp.CRT.arm.Desktop","Microsoft.VisualStudio.VC.Templates.UnitTest","Microsoft.VisualStudio.TestTools.TestPlatform.V1.CPP","Microsoft.VisualStudio.VC.Templates.UnitTest.Resources","Microsoft.VisualStudio.VC.Templates.Desktop","Microsoft.VisualStudio.VC.Templates.Pro","Microsoft.VisualStudio.VC.Templates.Pro.Resources","Microsoft.VisualStudio.PackageGroup.VC.CoreIDE.Express","Microsoft.VisualStudio.PackageGroup.Debugger.Script","Microsoft.VisualStudio.JavaScript.LanguageService","Microsoft.VisualStudio.JavaScript.LanguageService.Resources","Microsoft.VisualStudio.Debugger.Script.Msi","Microsoft.VisualStudio.Debugger.Script","Microsoft.VisualStudio.Debugger.Script","Microsoft.VisualStudio.Debugger.Script.Resources","Microsoft.VisualStudio.Debugger.Script.Resources","Microsoft.VisualStudio.VC.MSBuild.X64","Microsoft.VS.VC.MSBuild.X64.Resources","Microsoft.VisualStudio.VC.MSBuild.ARM","Microsoft.VisualStudio.VC.MSBuild.X86","Microsoft.VisualStudio.VC.MSBuild.Base","Microsoft.VisualStudio.VC.MSBuild.Base.Resources","Microsoft.VisualStudio.VC.Ide.WinXPlus","Microsoft.VisualStudio.VC.Ide.Dskx","Microsoft.VisualStudio.VC.Ide.Dskx.Resources","Microsoft.VisualStudio.VC.Ide.Core","Microsoft.VisualStudio.VC.Ide.Core.Resources","Microsoft.VisualStudio.VC.Ide.Base","Microsoft.VisualStudio.VC.Ide.Base.Resources","Microsoft.VisualStudio.Component.VC.CLI.Support","Microsoft.VisualCpp.CLI.X86","Microsoft.VisualCpp.CLI.X64","Microsoft.VisualCpp.CLI.Source","Microsoft.VisualCpp.CLI.ARM64","Microsoft.VisualCpp.CLI.ARM","Microsoft.VisualStudio.VC.Templates.CLR","Microsoft.VisualStudio.VC.Ide.LanguageService","Microsoft.VisualStudio.VC.Ide.ResourceEditor","Microsoft.VisualStudio.VC.Ide.ResourceEditor.Resources","Microsoft.VisualStudio.VC.Ide.ProjectSystem","Microsoft.VisualStudio.VC.Ide.ProjectSystem.Resources","Microsoft.VisualStudio.VC.Ide.Core.VCProjectEngine","Microsoft.VisualStudio.VC.Ide.Core.VCProjectEngine.Resources","Microsoft.VisualStudio.VC.Ide.LanguageService.Resources","Microsoft.VisualStudio.VC.Templates.CLR.Resources","Microsoft.Component.VC.Runtime.OSSupport","Microsoft.Windows.UniversalCRT.Tools.Msi","Microsoft.Windows.UniversalCRT.Tools.Msi","Microsoft.Windows.UniversalCRT.ExtensionSDK.Msi","Microsoft.Windows.UniversalCRT.HeadersLibsSources.Msi","Microsoft.VisualStudio.PackageGroup.VC.Tools.x86","Microsoft.VisualCpp.Tools.HostX86.TargetX64","Microsoft.VisualCpp.VCTip.hostX86.targetX64","Microsoft.VisualCpp.Tools.Hostx86.Targetx64.Resources","Microsoft.VisualCpp.Tools.HostX86.TargetX86","Microsoft.VisualCpp.VCTip.hostX86.targetX86","Microsoft.VisualCpp.Tools.HostX86.TargetX86.Resources","Microsoft.VisualCpp.Tools.Core.Resources","Microsoft.VisualCpp.Tools.Core.x86","Microsoft.VisualCpp.Tools.Common.Utils","Microsoft.VisualCpp.Tools.Common.Utils.Resources","Microsoft.VisualCpp.DIA.SDK","Microsoft.VisualCpp.CRT.x86.Desktop","Microsoft.VisualCpp.CRT.x64.Desktop","Microsoft.VisualCpp.CRT.Source","Microsoft.VisualCpp.CRT.Redist.X86","Microsoft.VisualCpp.CRT.Redist.X64","Microsoft.VisualCpp.CRT.Redist.Resources","Microsoft.VisualCpp.RuntimeDebug.14","Microsoft.VisualCpp.RuntimeDebug.14","Microsoft.VisualCpp.CRT.Headers","Microsoft.Component.HelpViewer","Microsoft.HelpViewer","Microsoft.VisualStudio.Help.Configuration.Msi","Microsoft.VisualStudio.Component.SQL.DataSources","Microsoft.VisualStudio.Component.SQL.SSDT","Microsoft.VisualStudio.Component.SQL.CMDUtils","sqlcmdlnutils","Microsoft.VisualStudio.Component.Common.Azure.Tools","Microsoft.VisualStudio.Azure.CommonAzureTools","SSDT","Microsoft.VisualStudio.Component.SQL.ADAL","sql_adalsql","Microsoft.VisualStudio.Component.NuGet","Microsoft.CredentialProvider","Microsoft.VisualStudio.NuGet.Licenses","Microsoft.VisualStudio.Component.SQL.LocalDB.Runtime","Microsoft.VisualStudio.Component.SQL.NCLI","sqllocaldb","sqlncli","Microsoft.VisualStudio.Component.EntityFramework","Microsoft.VisualStudio.PackageGroup.DslRuntime","Microsoft.VisualStudio.Dsl.Core","Microsoft.VisualStudio.Dsl.GraphObject","Microsoft.VisualStudio.Dsl.Core.Resources","Microsoft.VisualStudio.EntityFrameworkTools","Microsoft.VisualStudio.EntityFrameworkTools.Msi","Microsoft.VisualStudio.Component.Roslyn.LanguageServices","Microsoft.VisualStudio.InteractiveWindow","Microsoft.DiaSymReader.Native","Microsoft.VisualStudio.Component.Static.Analysis.Tools","Microsoft.VisualCpp.Redist.14","Microsoft.VisualCpp.Redist.14","Microsoft.VisualStudio.StaticAnalysis","Microsoft.VisualStudio.StaticAnalysis.Resources","Microsoft.CodeAnalysis.VisualStudio.InteractiveComponents.Resources","Microsoft.CodeAnalysis.VisualStudio.InteractiveComponents","Microsoft.CodeAnalysis.VisualStudio.Setup.Interactive.Resources","Microsoft.Net.ComponentGroup.TargetingPacks.Common","Microsoft.Net.Component.4.6.TargetingPack","Microsoft.Net.4.6.TargetingPack","Microsoft.Net.Component.4.5.2.TargetingPack","Microsoft.Net.4.5.2.TargetingPack","Microsoft.Net.Component.4.5.1.TargetingPack","Microsoft.Net.4.5.1.TargetingPack","Microsoft.Net.Component.4.5.TargetingPack","Microsoft.Net.4.5.TargetingPack","Microsoft.Net.Component.4.TargetingPack","Microsoft.Net.4.TargetingPack","Microsoft.Net.ComponentGroup.DevelopmentPrerequisites","Microsoft.Net.Component.4.6.1.TargetingPack","Microsoft.Net.4.6.1.TargetingPack","Microsoft.Net.Cumulative.TargetingPack.Resources","Microsoft.Net.Component.4.6.1.SDK","Microsoft.Net.4.6.1.SDK","Microsoft.VisualStudio.Component.TextTemplating","Microsoft.VisualStudio.TextTemplating.MSBuild","Microsoft.VisualStudio.TextTemplating.Integration","Microsoft.VisualStudio.TextTemplating.Core","Microsoft.VisualStudio.TextTemplating.Integration.Resources","Microsoft.VisualStudio.Component.VisualStudioData","Microsoft.VisualStudio.Component.SQL.CLR","Microsoft.VisualStudio.ProTools","sqlsysclrtypes","sqlsysclrtypes","SQLCommon","Microsoft.VisualStudio.ProTools.Resources","Microsoft.VisualStudio.XamlDiagnostics","Microsoft.VisualStudio.XamlDiagnostics.Resources","Microsoft.VisualStudio.XamlDesigner","Microsoft.VisualStudio.XamlDesigner.Resources","Microsoft.VisualStudio.XamlDesigner.Executables","Microsoft.VisualStudio.XamlShared","Microsoft.VisualStudio.XamlShared.Resources","Microsoft.VisualStudio.PackageGroup.TestTools.Managed","Microsoft.VisualStudio.PackageGroup.IntelliTrace.Core","Microsoft.IntelliTrace.Core","Microsoft.IntelliTrace.Core.Targeted","Microsoft.IntelliTrace.ProfilerProxy.Msi.x64","Microsoft.IntelliTrace.ProfilerProxy.Msi","Microsoft.VisualStudio.NuGet.Core","Microsoft.VisualStudio.TestWindow.SourceBasedTestDiscovery","Microsoft.VisualStudio.TestWindow.Dotnet","Microsoft.VisualStudio.TestTools.TestGeneration","Microsoft.VisualStudio.PackageGroup.TestTools.CodeCoverage","Microsoft.VisualStudio.PackageGroup.TestTools.Enterprise","Microsoft.VisualStudio.PackageGroup.TestTools.MSTestV2.Managed","Microsoft.VisualStudio.TestTools.MSTestV2.WizardExtension.UnitTest","Microsoft.VisualStudio.PackageGroup.TestTools.Core","Microsoft.VisualStudio.PackageGroup.TestTools.TestPlatform.V2.CLI","Microsoft.VisualStudio.TestTools.TestPlatform.V2.CLI","Microsoft.VisualStudio.PackageGroup.TestTools.TestPlatform.V1.CLI","Microsoft.VisualStudio.TestTools.TestPlatform.V1.CLI","Microsoft.VisualStudio.TestTools.Pex.Common","Microsoft.VisualStudio.PackageGroup.TestTools.TestPlatform.Legacy","Microsoft.VisualStudio.PackageGroup.MinShell.Interop","Microsoft.VisualStudio.TestTools.TP.Legacy.Tips.Msi","Microsoft.VisualStudio.TestTools.TP.Legacy.Tips.Common","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Tips","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Tips.Resources","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.TestTools","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Professional","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Common","Microsoft.VisualStudio.TestTools.TP.Legacy.Common.Res","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Core","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Core.Resources","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Agent","Microsoft.VisualStudio.PackageGroup.TestTools.TestPlatform.IDE","Microsoft.VisualStudio.TestTools.TestWIExtension","Microsoft.VisualStudio.TestTools.TestPlatform.IDE","Microsoft.VisualStudio.PackageGroup.TestTools.DataCollectors","Microsoft.Component.ClickOnce","Microsoft.VisualStudio.PackageGroup.ClickOnce.MSBuild","Microsoft.VisualCpp.CRT.ClickOnce.Msi","Microsoft.ClickOnce.SignTool.Msi","Microsoft.SQL.ClickOnceBootstrapper.Msi","Microsoft.Net.ClickOnceBootstrapper","Microsoft.ClickOnce.BootStrapper.Msi.Resources","Microsoft.ClickOnce.BootStrapper.Msi","Microsoft.VisualStudio.WebTools.WSP.FSA","Microsoft.VisualStudio.WebTools.WSP.FSA.Resources","Microsoft.VisualStudio.PackageGroup.Community","Microsoft.VisualStudio.Community.Extra.Resources","Microsoft.VisualStudio.Community.Extra","Microsoft.VisualStudio.PackageGroup.Core","Microsoft.VisualStudio.TestTools.TeamFoundationClient","Microsoft.VisualStudio.PackageGroup.Debugger.Core","Microsoft.VisualStudio.Debugger.VSCodeDebuggerHost","Microsoft.VisualStudio.VC.Ide.Debugger","Microsoft.VisualStudio.VC.Ide.Debugger.Resources","Microsoft.VisualStudio.VC.Ide.Common","Microsoft.VisualStudio.VC.Ide.Common.Resources","Microsoft.VisualStudio.Debugger.Parallel","Microsoft.VisualStudio.Debugger.Parallel.Resources","Microsoft.VisualStudio.Debugger.CollectionAgents","Microsoft.VisualStudio.Debugger.Managed","Microsoft.CodeAnalysis.VisualStudio.Setup.Resources","Microsoft.CodeAnalysis.VisualStudio.Setup","Microsoft.CodeAnalysis.ExpressionEvaluator.Resources","Microsoft.CodeAnalysis.ExpressionEvaluator","Microsoft.VisualStudio.Debugger.Managed.Resources","Microsoft.VisualStudio.Debugger.Remote","Microsoft.VisualStudio.Debugger.Remote","Microsoft.VisualStudio.Debugger.Remote.Resources","Microsoft.VisualStudio.Debugger.Remote.Resources","Microsoft.VisualStudio.Debugger","Microsoft.VisualStudio.VC.MSVCDis","Microsoft.VisualStudio.ScriptedHost","Microsoft.VisualStudio.ScriptedHost.Targeted","Microsoft.VisualStudio.ScriptedHost.Resources","Microsoft.IntelliTrace.DiagnosticsHub","Microsoft.VisualStudio.Debugger.Resources","Microsoft.PackageGroup.ClientDiagnostics","Microsoft.VisualStudio.AppResponsiveness","Microsoft.VisualStudio.AppResponsiveness.Targeted","Microsoft.VisualStudio.AppResponsiveness.Resources","Microsoft.VisualStudio.ClientDiagnostics","Microsoft.VisualStudio.ClientDiagnostics.Targeted","Microsoft.VisualStudio.ClientDiagnostics.Resources","Microsoft.VisualStudio.PackageGroup.CommunityCore","Microsoft.VisualStudio.ProjectSystem.Full","Microsoft.VisualStudio.ProjectSystem","Microsoft.VisualStudio.Community.x86","Microsoft.VisualStudio.Community.x64","Microsoft.VisualStudio.Community","Microsoft.IntelliTrace.CollectorCab","Microsoft.VisualStudio.Community.Resources","Microsoft.VisualStudio.Net.Eula.Resources","Microsoft.VisualStudio.WebSiteProject.DTE","Microsoft.MSHtml","Microsoft.VisualStudio.Community.Msi.Resources","Microsoft.VisualStudio.Community.Msi","Microsoft.VisualStudio.MinShell.Interop.Msi","Microsoft.VisualStudio.Editors","Microsoft.VisualStudio.ClickOnce.Resources","Microsoft.VisualStudio.ClickOnce","Microsoft.Component.MSBuild","Microsoft.NuGet.Build.Tasks","Microsoft.VisualStudio.Component.Roslyn.Compiler","Microsoft.CodeAnalysis.Compilers.Resources","Microsoft.CodeAnalysis.Compilers","Microsoft.Net.PackageGroup.4.6.1.Redist","Microsoft.VisualStudio.TemplateEngine","Microsoft.VisualStudio.WebToolsExtensions.Common","Microsoft.NET.Sdk","Microsoft.VisualStudio.PackageGroup.TestTools.Templates.Managed","Microsoft.VisualStudio.TestTools.Templates.Managed","Microsoft.VisualStudio.TestTools.Templates.Managed.Resources","Microsoft.VisualStudio.Templates.VB.MSTestv2.Desktop.UnitTest","Microsoft.VisualStudio.Templates.CS.MSTestv2.Desktop.UnitTest","Microsoft.VisualStudio.Templates.VB.Wpf","Microsoft.VisualStudio.Templates.VB.Wpf.Resources","Microsoft.VisualStudio.Templates.VB.Winforms","Microsoft.VisualStudio.Templates.VB.ManagedCore","Microsoft.VisualStudio.Templates.VB.Shared","Microsoft.VisualStudio.Templates.VB.Shared.Resources","Microsoft.VisualStudio.Templates.VB.ManagedCore.Resources","Microsoft.VisualStudio.Templates.CS.GettingStarted.Desktop.Package","Microsoft.VisualStudio.Templates.GetStarted.Desktop.Setup","Microsoft.VisualStudio.Templates.CS.GettingStarted.Console.Package","Microsoft.VisualStudio.Templates.GetStarted.Resources","Microsoft.VisualStudio.Templates.GetStarted.Common.Setup","Microsoft.VisualStudio.Templates.GetStarted.Console.Setup","Microsoft.VisualStudio.Templates.CS.Wpf","Microsoft.VisualStudio.Templates.CS.Wpf.Resources","Microsoft.VisualStudio.Templates.CS.Winforms","Microsoft.VisualStudio.Templates.CS.ManagedCore","Microsoft.VisualStudio.Templates.CS.Shared","Microsoft.VisualStudio.Templates.Editorconfig.Wizard.Setup","Templates.Editorconfig.SolutionFile.Setup","Microsoft.VisualStudio.Templates.CS.Shared.Resources","Microsoft.VisualStudio.Templates.CS.ManagedCore.Resources","Microsoft.VisualStudio.Component.CoreEditor","Microsoft.VisualStudio.PackageGroup.CoreEditor","PortableFacades","Microsoft.VisualStudio.PackageGroup.VsDevCmd","Microsoft.VisualStudio.VsDevCmd.Ext.NetFxSdk","Microsoft.VisualStudio.VsDevCmd.Core.WinSdk","Microsoft.VisualStudio.VsDevCmd.Core.DotNet","Microsoft.VisualStudio.VC.DevCmd","Microsoft.VisualStudio.VC.DevCmd.Resources","Microsoft.VisualStudio.VirtualTree","Microsoft.VisualStudio.PackageGroup.Progression","Microsoft.VisualStudio.PerformanceProvider","Microsoft.VisualStudio.GraphModel","Microsoft.VisualStudio.GraphProvider","Microsoft.DiaSymReader","Microsoft.Build.Dependencies","Microsoft.Build.FileTracker.Msi","Microsoft.Build","Microsoft.VisualStudio.TextMateGrammars","Microsoft.VisualStudio.PackageGroup.TeamExplorer","Microsoft.TeamFoundation.OfficeIntegration","Microsoft.TeamFoundation.OfficeIntegration.Resources","Microsoft.VisualStudio.TeamExplorer","Microsoft.ServiceHub","Microsoft.VisualStudio.ProjectServices","Microsoft.VisualStudio.SLNX.VSIX","Microsoft.VisualStudio.FileHandler.Msi","Microsoft.VisualStudio.FileHandler.Msi","Microsoft.VisualStudio.PackageGroup.MinShell","Microsoft.VisualStudio.MinShell.Interop","Microsoft.VisualStudio.Log","Microsoft.VisualStudio.Log.Targeted","Microsoft.VisualStudio.Log.Resources","Microsoft.VisualStudio.Finalizer","Microsoft.VisualStudio.WDExpress","Microsoft.VisualStudio.WDExpress.Resources","Microsoft.VisualStudio.CoreEditor","Microsoft.VisualStudio.Connected","Microsoft.VisualStudio.Connected.Resources","Microsoft.VisualStudio.MinShell","Microsoft.VisualStudio.Setup.Configuration","Microsoft.VisualStudio.MinShell.Platform","Microsoft.VisualStudio.MinShell.Platform.Resources","Microsoft.VisualStudio.MefHosting","Microsoft.VisualStudio.MefHosting.Resources","Microsoft.VisualStudio.Initializer","Microsoft.VisualStudio.ExtensionManager","Microsoft.VisualStudio.MinShell.x86","Microsoft.VisualStudio.NativeImageSupport","Microsoft.VisualStudio.MinShell.Msi","Microsoft.VisualStudio.MinShell.Msi.Resources","Microsoft.VisualStudio.LanguageServer","Microsoft.VisualStudio.MinShell.Resources","Microsoft.Net.PackageGroup.4.6.Redist","Microsoft.VisualStudio.Branding.WDExpress"]}]
diff --git a/deps/npm/node_modules/node-gyp/test/fixtures/VS_2017_Unusable.txt b/deps/npm/node_modules/node-gyp/test/fixtures/VS_2017_Unusable.txt
deleted file mode 100644
index fc0a257f447830..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/fixtures/VS_2017_Unusable.txt
+++ /dev/null
@@ -1 +0,0 @@
-[{"path":"C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildToolsUnusable","version":"15.9.28307.665","packages":["Microsoft.VisualStudio.Product.BuildTools","Microsoft.VisualStudio.Component.Windows10SDK.17134","Win10SDK_10.0.17134","Microsoft.VisualStudio.Component.VC.Tools.x86.x64","Microsoft.VisualCpp.CodeAnalysis.Extensions","Microsoft.VisualCpp.CodeAnalysis.Extensions.X86","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X86","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X86.Resources","Microsoft.VisualCpp.CodeAnalysis.Extensions.X64","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X64","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X64.Resources","Microsoft.VisualStudio.Component.Static.Analysis.Tools","Microsoft.VisualStudio.StaticAnalysis","Microsoft.VisualStudio.StaticAnalysis.Resources","Microsoft.VisualCpp.Tools.HostX64.TargetX86","Microsoft.VisualCpp.VCTip.HostX64.TargetX86","Microsoft.VisualCpp.Tools.HostX64.TargetX86.Resources","Microsoft.VisualCpp.Tools.HostX64.TargetX64","Microsoft.VisualCpp.VCTip.HostX64.TargetX64","Microsoft.VisualCpp.Tools.HostX64.TargetX64.Resources","Microsoft.VisualCpp.Premium.Tools.HostX86.TargetX64","Microsoft.VisualCpp.Premium.Tools.Hostx86.Targetx64.Resources","Microsoft.VisualCpp.Premium.Tools.HostX86.TargetX86","Microsoft.VisualCpp.Premium.Tools.HostX86.TargetX86.Resources","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX86","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX86.Resources","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX64","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX64.Resources","Microsoft.VisualCpp.PGO.X86","Microsoft.VisualCpp.PGO.X64","Microsoft.VisualCpp.PGO.Headers","Microsoft.VisualCpp.CRT.x86.Store","Microsoft.VisualCpp.CRT.x86.OneCore.Desktop","Microsoft.VisualCpp.CRT.x64.Store","Microsoft.VisualCpp.CRT.x64.OneCore.Desktop","Microsoft.VisualCpp.CRT.Redist.x86.OneCore.Desktop","Microsoft.VisualCpp.CRT.Redist.x64.OneCore.Desktop","Microsoft.VisualCpp.CRT.ClickOnce.Msi","Microsoft.VisualStudio.PackageGroup.VC.Tools.x86","Microsoft.VisualCpp.Tools.HostX86.TargetX64","Microsoft.VisualCpp.VCTip.hostX86.targetX64","Microsoft.VisualCpp.Tools.Hostx86.Targetx64.Resources","Microsoft.VisualCpp.Tools.HostX86.TargetX86","Microsoft.VisualCpp.VCTip.hostX86.targetX86","Microsoft.VisualCpp.Tools.HostX86.TargetX86.Resources","Microsoft.VisualCpp.Tools.Core.Resources","Microsoft.VisualCpp.Tools.Core.x86","Microsoft.VisualCpp.Tools.Common.Utils","Microsoft.VisualCpp.Tools.Common.Utils.Resources","Microsoft.VisualCpp.DIA.SDK","Microsoft.VisualCpp.CRT.x86.Desktop","Microsoft.VisualCpp.CRT.x64.Desktop","Microsoft.VisualCpp.CRT.Source","Microsoft.VisualCpp.CRT.Redist.X86","Microsoft.VisualCpp.CRT.Redist.X64","Microsoft.VisualCpp.CRT.Redist.Resources","Microsoft.VisualCpp.RuntimeDebug.14","Microsoft.VisualCpp.RuntimeDebug.14","Microsoft.VisualCpp.Redist.14","Microsoft.VisualCpp.Redist.14","Microsoft.VisualCpp.CRT.Headers","Microsoft.VisualStudio.Workload.MSBuildTools","Microsoft.VisualStudio.Component.CoreBuildTools","Microsoft.VisualStudio.Setup.Configuration","Microsoft.VisualStudio.PackageGroup.VsDevCmd","Microsoft.VisualStudio.VsDevCmd.Ext.NetFxSdk","Microsoft.VisualStudio.VsDevCmd.Core.WinSdk","Microsoft.VisualStudio.VsDevCmd.Core.DotNet","Microsoft.VisualStudio.VC.DevCmd","Microsoft.VisualStudio.VC.DevCmd.Resources","Microsoft.VisualStudio.BuildTools.Resources","Microsoft.VisualStudio.Net.Eula.Resources","Microsoft.Build.Dependencies","Microsoft.Build.FileTracker.Msi","Microsoft.Component.MSBuild","Microsoft.PythonTools.BuildCore.Vsix","Microsoft.NuGet.Build.Tasks","Microsoft.VisualStudio.Component.Roslyn.Compiler","Microsoft.CodeAnalysis.Compilers.Resources","Microsoft.CodeAnalysis.Compilers","Microsoft.Net.PackageGroup.4.6.1.Redist","Microsoft.Net.4.6.1.FullRedist.NonThreshold","Microsoft.Windows.UniversalCRT.Msu.81","Microsoft.VisualStudio.NativeImageSupport","Microsoft.Build"]}]
diff --git a/deps/npm/node_modules/node-gyp/test/fixtures/VS_2019_BuildTools_minimal.txt b/deps/npm/node_modules/node-gyp/test/fixtures/VS_2019_BuildTools_minimal.txt
deleted file mode 100644
index f07d2541648829..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/fixtures/VS_2019_BuildTools_minimal.txt
+++ /dev/null
@@ -1 +0,0 @@
-[{"path":"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools","version":"16.1.28922.388","packages":["Microsoft.VisualStudio.Product.BuildTools","Microsoft.VisualStudio.Component.VC.CoreIde","Microsoft.VisualStudio.VC.Ide.Pro","Microsoft.VisualStudio.VC.Ide.Pro.Resources","Microsoft.VisualStudio.VC.Templates.Pro","Microsoft.VisualStudio.VC.Templates.Pro.Resources","Microsoft.VisualStudio.VC.Items.Pro","Microsoft.VisualStudio.PackageGroup.VC.CoreIDE.Reduced","Microsoft.VisualStudio.VC.Ide.MDD","Microsoft.VisualStudio.PackageGroup.Core","Microsoft.VisualStudio.CodeSense.Community","Microsoft.VisualStudio.TestTools.TeamFoundationClient","Microsoft.PackageGroup.ClientDiagnostics","Microsoft.VisualStudio.AppResponsiveness","Microsoft.VisualStudio.AppResponsiveness.Targeted","Microsoft.VisualStudio.AppResponsiveness.Resources","Microsoft.VisualStudio.ClientDiagnostics","Microsoft.VisualStudio.ClientDiagnostics.Targeted","Microsoft.VisualStudio.ClientDiagnostics.Resources","Microsoft.VisualStudio.PackageGroup.CommunityCore","Microsoft.VisualStudio.ProjectSystem.Full","Microsoft.VisualStudio.ProjectSystem","Microsoft.VisualStudio.Community.x86","Microsoft.VisualStudio.Community.x64","Microsoft.VisualStudio.Community","Microsoft.IntelliTrace.CollectorCab","Microsoft.VisualStudio.Community.Resources","Microsoft.VisualStudio.WebSiteProject.DTE","Microsoft.MSHtml","Microsoft.VisualStudio.Platform.CallHierarchy","Microsoft.VisualStudio.Community.Msi.Resources","Microsoft.VisualStudio.Community.Msi","Microsoft.VisualStudio.MinShell.Interop.Msi","Microsoft.VisualStudio.PackageGroup.CoreEditor","Microsoft.VisualStudio.VirtualTree","Microsoft.VisualStudio.PackageGroup.Progression","Microsoft.VisualStudio.PerformanceProvider","Microsoft.VisualStudio.GraphModel","Microsoft.VisualStudio.GraphProvider","Microsoft.VisualStudio.TextMateGrammars","Microsoft.VisualStudio.PackageGroup.TeamExplorer.Common","Microsoft.VisualStudio.TeamExplorer","Microsoft.ServiceHub","Microsoft.VisualStudio.ProjectServices","Microsoft.VisualStudio.OpenFolder.VSIX","Microsoft.VisualStudio.FileHandler.Msi","Microsoft.VisualStudio.FileHandler.Msi","Microsoft.VisualStudio.PackageGroup.MinShell","Microsoft.VisualStudio.MinShell.Msi","Microsoft.VisualStudio.MinShell.Msi.Resources","Microsoft.VisualStudio.MinShell.Interop","Microsoft.VisualStudio.Log","Microsoft.VisualStudio.Log.Targeted","Microsoft.VisualStudio.Log.Resources","Microsoft.VisualStudio.Finalizer","Microsoft.VisualStudio.CoreEditor","Microsoft.VisualStudio.Platform.NavigateTo","Microsoft.VisualStudio.Connected","Microsoft.VisualStudio.Connected.Resources","Microsoft.VisualStudio.VC.Ide.x64","Microsoft.VisualStudio.PackageGroup.VC.CoreIDE.Express","Microsoft.VisualStudio.PackageGroup.Debugger.Script","Microsoft.VisualStudio.Debugger.Script.Msi","Microsoft.VisualStudio.Debugger.Script","Microsoft.VisualStudio.Debugger.Script","Microsoft.VisualStudio.Debugger.Script.Resources","Microsoft.VisualStudio.Debugger.Script.Resources","Microsoft.VisualStudio.VC.Ide.WinXPlus","Microsoft.VisualStudio.VC.Ide.Dskx","Microsoft.VisualStudio.VC.Ide.Dskx.Resources","Microsoft.VisualStudio.VC.Ide.Base","Microsoft.VisualStudio.VC.Ide.LanguageService","Microsoft.VisualStudio.VC.Ide.Core","Microsoft.VisualStudio.VisualC.Logging","Microsoft.VisualStudio.VC.Ide.Core.Resources","Microsoft.VisualStudio.VC.Ide.VCPkgDatabase","Microsoft.VisualStudio.VC.Ide.ResourceEditor","Microsoft.VisualStudio.VC.Ide.ResourceEditor.Resources","Microsoft.VisualStudio.VC.Ide.ProjectSystem","Microsoft.VisualStudio.VC.Ide.ProjectSystem.Resources","Microsoft.VisualStudio.VC.Ide.Core.VCProjectEngine","Microsoft.VisualStudio.VC.Ide.Core.VCProjectEngine.Resources","Microsoft.VisualStudio.VC.Ide.LanguageService.Resources","Microsoft.VisualStudio.VC.Ide.Base.Resources","Microsoft.Net.4.TargetingPack","Microsoft.VisualStudio.PackageGroup.Debugger.Core","Microsoft.VisualStudio.PackageGroup.Debugger.TimeTravel.Record","Microsoft.VisualStudio.Debugger.TimeTravel.Runtime","Microsoft.VisualStudio.Debugger.TimeTravel.Runtime","Microsoft.VisualStudio.Debugger.TimeTravel.Agent","Microsoft.VisualStudio.Debugger.TimeTravel.Record","Microsoft.VisualStudio.Debugger.VSCodeDebuggerHost","Microsoft.VisualStudio.VC.Ide.Debugger","Microsoft.VisualStudio.VC.Ide.Debugger.Concord","Microsoft.VisualStudio.VC.Ide.Debugger.Concord.Resources","Microsoft.VisualStudio.VC.Ide.Debugger.Resources","Microsoft.VisualStudio.VC.Ide.Common","Microsoft.VisualStudio.VC.Ide.Common.Resources","Microsoft.VisualStudio.Debugger.Parallel","Microsoft.VisualStudio.Debugger.Parallel.Resources","Microsoft.VisualStudio.Debugger.CollectionAgents","Microsoft.VisualStudio.Debugger.Managed","Microsoft.DiaSymReader","Microsoft.CodeAnalysis.ExpressionEvaluator","Microsoft.VisualStudio.Debugger.Concord.Managed","Microsoft.VisualStudio.Debugger.Concord.Managed.Resources","Microsoft.VisualStudio.Debugger.Managed.Resources","Microsoft.VisualStudio.Debugger.Remote","Microsoft.VisualStudio.Debugger.Concord.Remote","Microsoft.VisualStudio.Debugger.Concord.Remote.Resources","Microsoft.VisualStudio.Debugger.Remote","Microsoft.VisualStudio.Debugger.Concord.Remote","Microsoft.VisualStudio.Debugger.Concord.Remote.Resources","Microsoft.VisualStudio.Debugger.Remote.Resources","Microsoft.VisualStudio.Debugger.Remote.Resources","Microsoft.VisualStudio.Debugger","Microsoft.VisualStudio.PerfLib","Microsoft.VisualStudio.Debugger.Package.DiagHub.Client.VSx86","Microsoft.VisualStudio.Debugger.Remote.DiagHub.Client","Microsoft.VisualStudio.Debugger.Remote.DiagHub.Client","Microsoft.VisualStudio.VC.MSVCDis","Microsoft.VisualStudio.ScriptedHost","Microsoft.VisualStudio.ScriptedHost.Targeted","Microsoft.VisualStudio.ScriptedHost.Resources","Microsoft.VisualStudio.Editors","Microsoft.IntelliTrace.DiagnosticsHub","Microsoft.VisualStudio.MinShell","Microsoft.VisualStudio.MinShell.Platform","Microsoft.VisualStudio.MinShell.Platform.Resources","Microsoft.VisualStudio.MefHosting","Microsoft.VisualStudio.MefHosting.Resources","Microsoft.VisualStudio.Initializer","Microsoft.VisualStudio.ExtensionManager","Microsoft.VisualStudio.Platform.Editor","Microsoft.VisualStudio.Debugger.Concord","Microsoft.VisualStudio.Debugger.Concord.Resources","Microsoft.VisualStudio.Debugger.Resources","Microsoft.CodeAnalysis.VisualStudio.Setup","Microsoft.VisualStudio.Component.Windows10SDK.17134","Win10SDK_10.0.17134","Microsoft.VisualStudio.Component.VC.Tools.x86.x64","Microsoft.VisualCpp.CodeAnalysis.Extensions","Microsoft.VisualCpp.CodeAnalysis.Extensions.X86","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X86","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X86.Resources","Microsoft.VisualCpp.CodeAnalysis.Extensions.X64","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X64","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X64.Resources","Microsoft.VisualStudio.StaticAnalysis","Microsoft.VisualStudio.StaticAnalysis.Resources","Microsoft.VisualCpp.Tools.HostX64.TargetX86","Microsoft.VisualCpp.VCTip.HostX64.TargetX86","Microsoft.VisualCpp.Tools.HostX64.TargetX86.Resources","Microsoft.VisualCpp.Tools.HostX64.TargetX64","Microsoft.VisualCpp.VCTip.HostX64.TargetX64","Microsoft.VisualCpp.Tools.HostX64.TargetX64.Resources","Microsoft.VisualCpp.Premium.Tools.HostX86.TargetX64","Microsoft.VisualCpp.Premium.Tools.Hostx86.Targetx64.Resources","Microsoft.VisualCpp.Premium.Tools.HostX86.TargetX86","Microsoft.VisualCpp.Premium.Tools.HostX86.TargetX86.Resources","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX86","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX86.Resources","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX64","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX64.Resources","Microsoft.VisualCpp.PGO.X86","Microsoft.VisualCpp.PGO.X64","Microsoft.VisualCpp.PGO.Headers","Microsoft.VisualCpp.CRT.x86.Store","Microsoft.VisualCpp.CRT.x86.OneCore.Desktop","Microsoft.VisualCpp.CRT.x64.Store","Microsoft.VisualCpp.CRT.x64.OneCore.Desktop","Microsoft.VisualCpp.CRT.Redist.x86.OneCore.Desktop","Microsoft.VisualCpp.CRT.Redist.x64.OneCore.Desktop","Microsoft.VisualCpp.CRT.ClickOnce.Msi","Microsoft.VisualStudio.PackageGroup.VC.Tools.x86","Microsoft.VisualCpp.Tools.HostX86.TargetX64","Microsoft.VisualCpp.VCTip.hostX86.targetX64","Microsoft.VisualCpp.Tools.Hostx86.Targetx64.Resources","Microsoft.VisualCpp.Tools.HostX86.TargetX86","Microsoft.VisualCpp.VCTip.hostX86.targetX86","Microsoft.VisualCpp.Tools.HostX86.TargetX86.Resources","Microsoft.VisualCpp.Tools.Core.Resources","Microsoft.VisualCpp.Tools.Core.x86","Microsoft.VisualCpp.Tools.Common.Utils","Microsoft.VisualCpp.Tools.Common.Utils.Resources","Microsoft.VisualCpp.DIA.SDK","Microsoft.VisualCpp.CRT.x86.Desktop","Microsoft.VisualCpp.CRT.x64.Desktop","Microsoft.VisualCpp.CRT.Source","Microsoft.VisualCpp.CRT.Redist.X86","Microsoft.VisualCpp.CRT.Redist.X64","Microsoft.VisualCpp.CRT.Redist.Resources","Microsoft.VisualCpp.RuntimeDebug.14","Microsoft.VisualCpp.RuntimeDebug.14","Microsoft.VisualCpp.Redist.14.Latest","Microsoft.VisualCpp.Redist.14.Latest","Microsoft.VisualCpp.Redist.14","Microsoft.VisualCpp.Redist.14","Microsoft.VisualCpp.CRT.Headers","Microsoft.VisualStudio.VC.MSBuild.x86.v142","Microsoft.VisualStudio.VC.MSBuild.X86","Microsoft.VisualStudio.VC.MSBuild.X64.v142","Microsoft.VisualStudio.VC.MSBuild.X64","Microsoft.VS.VC.MSBuild.X64.Resources","Microsoft.VisualStudio.VC.MSBuild.ARM.v142","Microsoft.VisualStudio.VC.MSBuild.ARM","Microsoft.VisualStudio.VC.MSBuild.Base","Microsoft.VisualStudio.VC.MSBuild.Base.Resources","Microsoft.VisualStudio.Workload.MSBuildTools","Microsoft.VisualStudio.Component.CoreBuildTools","Microsoft.VisualStudio.Setup.Configuration","Microsoft.VisualStudio.PackageGroup.VsDevCmd","Microsoft.VisualStudio.VsDevCmd.Ext.NetFxSdk","Microsoft.VisualStudio.VsDevCmd.Core.WinSdk","Microsoft.VisualStudio.VsDevCmd.Core.DotNet","Microsoft.VisualStudio.VC.DevCmd","Microsoft.VisualStudio.VC.DevCmd.Resources","Microsoft.VisualStudio.BuildTools.Resources","Microsoft.VisualStudio.Net.Eula.Resources","Microsoft.Build.Dependencies","Microsoft.Build.FileTracker.Msi","Microsoft.Component.MSBuild","Microsoft.PythonTools.BuildCore.Vsix","Microsoft.NuGet.Build.Tasks","Microsoft.VisualStudio.Component.Roslyn.Compiler","Microsoft.CodeAnalysis.Compilers","Microsoft.Net.PackageGroup.4.7.2.Redist","Microsoft.VisualStudio.NativeImageSupport","Microsoft.Build","Microsoft.VisualStudio.PackageGroup.NuGet","Microsoft.VisualStudio.NuGet.BuildTools"]}]
diff --git a/deps/npm/node_modules/node-gyp/test/fixtures/VS_2019_Community_workload.txt b/deps/npm/node_modules/node-gyp/test/fixtures/VS_2019_Community_workload.txt
deleted file mode 100644
index 50071c25f189e5..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/fixtures/VS_2019_Community_workload.txt
+++ /dev/null
@@ -1 +0,0 @@
-[{"path":"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community","version":"16.1.28922.388","packages":["Microsoft.VisualStudio.Workload.NativeDesktop","Microsoft.VisualStudio.Component.VC.TestAdapterForGoogleTest","Microsoft.VisualStudio.VC.Ide.TestAdapterForGoogleTest","Microsoft.VisualStudio.Component.VC.TestAdapterForBoostTest","Microsoft.VisualStudio.VC.Ide.TestAdapterForBoostTest","Microsoft.VisualStudio.Component.VC.ATL","Microsoft.VisualStudio.VC.Ide.ATL","Microsoft.VisualStudio.VC.Ide.ATL.Resources","Microsoft.VisualCpp.ATL.X86","Microsoft.VisualCpp.ATL.X64","Microsoft.VisualCpp.ATL.Source","Microsoft.VisualCpp.ATL.Headers","Microsoft.VisualStudio.Component.VC.CMake.Project","Microsoft.VisualStudio.VC.CMake","Microsoft.VisualStudio.VC.CMake.Project","Microsoft.VisualStudio.VC.ExternalBuildFramework","Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core","Microsoft.VisualStudio.PackageGroup.TestTools.Native","Microsoft.VisualStudio.Component.VC.Redist.14.Latest","Microsoft.VisualStudio.VC.Templates.UnitTest","Microsoft.VisualStudio.VC.UnitTest.Desktop.Build.Core","Microsoft.VisualStudio.TestTools.TestPlatform.V1.CPP","Microsoft.VisualStudio.VC.Templates.UnitTest.Resources","Microsoft.VisualStudio.VC.Templates.Desktop","Microsoft.VisualStudio.Component.Debugger.JustInTime","Microsoft.VisualStudio.Debugger.ImmersiveActivateHelper.Msi","Microsoft.VisualStudio.Debugger.JustInTime","Microsoft.VisualStudio.Debugger.JustInTime.Msi","Microsoft.VisualStudio.Component.Windows10SDK.17763","Win10SDK_10.0.17763","Microsoft.VisualStudio.Component.VC.DiagnosticTools","Microsoft.VisualStudio.Component.Graphics.Tools","Microsoft.VisualStudio.Component.VC.Tools.x86.x64","Microsoft.VisualCpp.CodeAnalysis.Extensions","Microsoft.VisualCpp.CodeAnalysis.Extensions.X86","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X86","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X86.Resources","Microsoft.VisualCpp.CodeAnalysis.Extensions.X64","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X64","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X64.Resources","Microsoft.VisualCpp.Tools.HostX64.TargetX86","Microsoft.VisualCpp.VCTip.HostX64.TargetX86","Microsoft.VisualCpp.Tools.HostX64.TargetX86.Resources","Microsoft.VisualCpp.Tools.HostX64.TargetX64","Microsoft.VisualCpp.VCTip.HostX64.TargetX64","Microsoft.VisualCpp.Tools.HostX64.TargetX64.Resources","Microsoft.VisualCpp.Premium.Tools.HostX86.TargetX64","Microsoft.VisualCpp.Premium.Tools.Hostx86.Targetx64.Resources","Microsoft.VisualCpp.Premium.Tools.HostX86.TargetX86","Microsoft.VisualCpp.Premium.Tools.HostX86.TargetX86.Resources","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX86","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX86.Resources","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX64","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX64.Resources","Microsoft.VisualCpp.PGO.X86","Microsoft.VisualCpp.PGO.X64","Microsoft.VisualCpp.PGO.Headers","Microsoft.VisualCpp.CRT.x86.Store","Microsoft.VisualCpp.CRT.x86.OneCore.Desktop","Microsoft.VisualCpp.CRT.x64.Store","Microsoft.VisualCpp.CRT.x64.OneCore.Desktop","Microsoft.VisualCpp.CRT.Redist.x86.OneCore.Desktop","Microsoft.VisualCpp.CRT.Redist.x64.OneCore.Desktop","Microsoft.VisualStudio.PackageGroup.VC.Tools.x86","Microsoft.VisualCpp.Tools.HostX86.TargetX64","Microsoft.VisualCpp.VCTip.hostX86.targetX64","Microsoft.VisualCpp.Tools.Hostx86.Targetx64.Resources","Microsoft.VisualCpp.Tools.HostX86.TargetX86","Microsoft.VisualCpp.VCTip.hostX86.targetX86","Microsoft.VisualCpp.Tools.HostX86.TargetX86.Resources","Microsoft.VisualCpp.Tools.Core.Resources","Microsoft.VisualCpp.Tools.Core.x86","Microsoft.VisualCpp.DIA.SDK","Microsoft.VisualCpp.CRT.x86.Desktop","Microsoft.VisualCpp.CRT.x64.Desktop","Microsoft.VisualCpp.CRT.Source","Microsoft.VisualCpp.CRT.Redist.X86","Microsoft.VisualCpp.CRT.Redist.X64","Microsoft.VisualCpp.CRT.Redist.Resources","Microsoft.VisualCpp.RuntimeDebug.14","Microsoft.VisualCpp.RuntimeDebug.14","Microsoft.VisualCpp.Redist.14.Latest","Microsoft.VisualCpp.Redist.14.Latest","Microsoft.VisualCpp.CRT.Headers","Microsoft.VisualStudio.Graphics.Viewers","Microsoft.VisualStudio.Graphics.Viewers.Resources","Microsoft.VisualStudio.Graphics.Msi","Microsoft.VisualStudio.Graphics.Msi","Microsoft.VisualStudio.Graphics.Analyzer","Microsoft.VisualStudio.Graphics.Analyzer.Targeted","Microsoft.VisualStudio.Graphics.Analyzer.Resources","Microsoft.VisualStudio.Graphics.Appid","Microsoft.VisualStudio.Graphics.Appid.Resources","Microsoft.VisualStudio.Component.VC.CoreIde","Microsoft.VisualStudio.VC.Ide.Pro","Microsoft.VisualStudio.VC.Ide.Pro.Resources","Microsoft.VisualStudio.VC.Templates.Pro","Microsoft.VisualStudio.VC.Templates.Pro.Resources","Microsoft.VisualStudio.VC.Items.Pro","Microsoft.VisualStudio.PackageGroup.VC.CoreIDE.Reduced","Microsoft.VisualStudio.VC.Ide.x64","Microsoft.VisualStudio.PackageGroup.VC.CoreIDE.Express","Microsoft.VisualStudio.VC.MSBuild.X64.v142","Microsoft.VisualStudio.VC.MSBuild.X64","Microsoft.VS.VC.MSBuild.X64.Resources","Microsoft.VisualStudio.VC.MSBuild.ARM.v142","Microsoft.VisualStudio.VC.MSBuild.ARM","Microsoft.VisualStudio.VC.MSBuild.x86.v142","Microsoft.VisualStudio.VC.MSBuild.X86","Microsoft.VisualStudio.VC.MSBuild.Base","Microsoft.VisualStudio.VC.MSBuild.Base.Resources","Microsoft.VisualStudio.VC.Ide.WinXPlus","Microsoft.VisualStudio.VC.Ide.Dskx","Microsoft.VisualStudio.VC.Ide.Dskx.Resources","Microsoft.VisualStudio.VC.Ide.Base","Microsoft.VisualStudio.VC.Ide.LanguageService","Microsoft.VisualStudio.VC.Ide.Core","Microsoft.VisualStudio.VC.Ide.Core.Resources","Microsoft.VisualStudio.VC.Ide.VCPkgDatabase","Microsoft.VisualStudio.VC.Ide.ProjectSystem","Microsoft.VisualStudio.VC.Ide.ProjectSystem.Resources","Microsoft.VisualStudio.VC.Ide.Core.VCProjectEngine","Microsoft.VisualStudio.VC.Ide.Core.VCProjectEngine.Resources","Microsoft.VisualStudio.VC.Ide.LanguageService.Resources","Microsoft.VisualStudio.VC.Ide.Base.Resources","Component.Microsoft.VisualStudio.LiveShare","Microsoft.VisualStudio.LiveShare","Microsoft.Icecap.Analysis","Microsoft.Icecap.Analysis.Targeted","Microsoft.Icecap.Analysis.Resources","Microsoft.Icecap.Analysis.Resources.Targeted","Microsoft.Icecap.Collection.Msi","Microsoft.Icecap.Collection.Msi.Targeted","Microsoft.Icecap.Collection.Msi.Resources","Microsoft.Icecap.Collection.Msi.Resources.Targeted","Microsoft.DiagnosticsHub.Instrumentation","Microsoft.DiagnosticsHub.CpuSampling.ExternalDependencies","Microsoft.DiagnosticsHub.CpuSampling","Microsoft.DiagnosticsHub.CpuSampling.Targeted","Microsoft.PackageGroup.DiagnosticsHub.Platform","Microsoft.DiagnosticsHub.Runtime.ExternalDependencies","Microsoft.DiagnosticsHub.Runtime.ExternalDependencies.Targeted","Microsoft.DiagnosticsHub.Collection.ExternalDependencies.x64","Microsoft.DiagnosticsHub.Collection.StopService.Uninstall","Microsoft.DiagnosticsHub.Runtime","Microsoft.DiagnosticsHub.Runtime.Targeted","Microsoft.DiagnosticsHub.Collection","Microsoft.DiagnosticsHub.Collection.Service","Microsoft.DiagnosticsHub.Collection.StopService.Install","Microsoft.VisualStudio.Component.IntelliCode","Microsoft.VisualStudio.IntelliCode","Microsoft.Net.4.TargetingPack","Microsoft.VisualStudio.VC.Ide.ResourceEditor","Microsoft.VisualStudio.VC.Ide.ResourceEditor.Resources","Microsoft.VisualStudio.PackageGroup.TestTools.CodeCoverage","Microsoft.VisualStudio.PackageGroup.TestTools.Core","Microsoft.VisualStudio.PackageGroup.TestTools.TestPlatform.V2.CLI","Microsoft.VisualStudio.TestTools.TestPlatform.V2.CLI","Microsoft.VisualStudio.PackageGroup.TestTools.TestPlatform.V1.CLI","Microsoft.VisualStudio.TestTools.TestPlatform.V1.CLI","Microsoft.VisualStudio.TestTools.Pex.Common","Microsoft.VisualStudio.PackageGroup.TestTools.TestPlatform.Legacy","Microsoft.VisualStudio.PackageGroup.MinShell.Interop","Microsoft.VisualStudio.TestTools.TP.Legacy.Tips.Msi","Microsoft.VisualStudio.TestTools.TP.Legacy.Tips.Common","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Tips","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Tips.Resources","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.TestTools","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Professional","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Common","Microsoft.VisualStudio.TestTools.TP.Legacy.Common.Res","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Core","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Core.Resources","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Agent","Microsoft.VisualStudio.PackageGroup.TestTools.TestPlatform.IDE","Microsoft.VisualStudio.TestTools.TestWIExtension","Microsoft.VisualStudio.TestTools.TestPlatform.IDE","Microsoft.VisualStudio.PackageGroup.TestTools.DataCollectors","Microsoft.VisualStudio.LiveShareApi","Microsoft.VisualStudio.Component.TextTemplating","Microsoft.VisualStudio.TextTemplating.MSBuild","Microsoft.VisualStudio.TextTemplating.Integration","Microsoft.VisualStudio.TextTemplating.Core","Microsoft.VisualStudio.TextTemplating.Integration.Resources","Microsoft.VisualCpp.CRT.ClickOnce.Msi","Microsoft.Component.MSBuild","Microsoft.NuGet.Build.Tasks","Microsoft.DiagnosticsHub.KB2882822.Win7","Microsoft.VisualStudio.PackageGroup.Debugger.Script","Microsoft.VisualStudio.Debugger.Script.Msi","Microsoft.VisualStudio.Debugger.Script","Microsoft.VisualStudio.Debugger.Script","Microsoft.VisualStudio.Debugger.Script.Resources","Microsoft.VisualStudio.Debugger.Script.Resources","Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions","Microsoft.VisualStudio.ProTools","sqlsysclrtypes","sqlsysclrtypes","SQLCommon","Microsoft.VisualStudio.ProTools.Resources","Microsoft.VisualStudio.WebToolsExtensions","Microsoft.VisualStudio.WebTools","Microsoft.VisualStudio.WebTools.Resources","Microsoft.VisualStudio.WebTools.MSBuild","Microsoft.VisualStudio.WebTools.WSP.FSA","Microsoft.VisualStudio.WebTools.WSP.FSA.Resources","Microsoft.VisualStudio.VC.Ide.MDD","Microsoft.VisualStudio.VisualC.Logging","Microsoft.WebTools.Shared","Microsoft.WebTools.DotNet.Core.ItemTemplates","Microsoft.VisualCpp.Redist.14","Microsoft.VisualCpp.Redist.14","Microsoft.Windows.UniversalCRT.Msu.7","Microsoft.VisualStudio.StaticAnalysis","Microsoft.VisualStudio.StaticAnalysis.Resources","Microsoft.VisualStudio.Component.Roslyn.Compiler","Microsoft.CodeAnalysis.Compilers","Microsoft.VisualStudio.Component.NuGet","Microsoft.CredentialProvider","Microsoft.VisualStudio.NuGet.PowershellBindingRedirect","Microsoft.VisualStudio.NuGet.Licenses","Microsoft.VisualStudio.PackageGroup.Community","Microsoft.VisualStudio.Community.Extra.Resources","Microsoft.VisualStudio.Community.Extra","Microsoft.VisualStudio.PackageGroup.Core","Microsoft.VisualStudio.CodeSense.Community","Microsoft.VisualStudio.TestTools.TeamFoundationClient","Microsoft.VisualStudio.PackageGroup.Debugger.Core","Microsoft.VisualStudio.PackageGroup.Debugger.TimeTravel.Record","Microsoft.VisualStudio.Debugger.TimeTravel.Runtime","Microsoft.VisualStudio.Debugger.TimeTravel.Runtime","Microsoft.VisualStudio.Debugger.TimeTravel.Agent","Microsoft.VisualStudio.Debugger.TimeTravel.Record","Microsoft.VisualStudio.Debugger.VSCodeDebuggerHost","Microsoft.VisualStudio.VC.Ide.Debugger","Microsoft.VisualStudio.VC.Ide.Debugger.Concord","Microsoft.VisualStudio.VC.Ide.Debugger.Concord.Resources","Microsoft.VisualStudio.VC.Ide.Debugger.Resources","Microsoft.VisualStudio.VC.Ide.Common","Microsoft.VisualStudio.VC.Ide.Common.Resources","Microsoft.VisualStudio.Debugger.Parallel","Microsoft.VisualStudio.Debugger.Parallel.Resources","Microsoft.VisualStudio.Debugger.CollectionAgents","Microsoft.VisualStudio.Debugger.Managed","Microsoft.CodeAnalysis.VisualStudio.Setup","Microsoft.CodeAnalysis.ExpressionEvaluator","Microsoft.VisualStudio.Debugger.Concord.Managed","Microsoft.VisualStudio.Debugger.Concord.Managed.Resources","Microsoft.VisualStudio.Debugger.Managed.Resources","Microsoft.VisualStudio.Debugger.Remote","Microsoft.VisualStudio.Debugger.Remote.DbgHelp.Win8","Microsoft.VisualStudio.Debugger.Concord.Remote","Microsoft.VisualStudio.Debugger.Concord.Remote.Resources","Microsoft.VisualStudio.Debugger.Remote","Microsoft.VisualStudio.Debugger.Remote.DbgHelp.Win8","Microsoft.VisualStudio.Debugger.Concord.Remote","Microsoft.VisualStudio.Debugger.Concord.Remote.Resources","Microsoft.VisualStudio.Debugger.Remote.Resources","Microsoft.VisualStudio.Debugger.Remote.Resources","Microsoft.VisualStudio.Debugger","Microsoft.VisualStudio.Debugger.Package.DiagHub.Client.VSx86","Microsoft.VisualStudio.Debugger.Remote.DiagHub.Client","Microsoft.VisualStudio.Debugger.Remote.DiagHub.Client","Microsoft.VisualStudio.Debugger.DbgHelp.Win8","Microsoft.VisualStudio.VC.MSVCDis","Microsoft.VisualStudio.ScriptedHost","Microsoft.VisualStudio.ScriptedHost.Targeted","Microsoft.VisualStudio.ScriptedHost.Resources","Microsoft.IntelliTrace.DiagnosticsHub","Microsoft.VisualStudio.Debugger.Concord","Microsoft.VisualStudio.Debugger.Concord.Resources","Microsoft.VisualStudio.Debugger.Resources","Microsoft.PackageGroup.ClientDiagnostics","Microsoft.VisualStudio.AppResponsiveness","Microsoft.VisualStudio.AppResponsiveness.Targeted","Microsoft.VisualStudio.AppResponsiveness.Resources","Microsoft.VisualStudio.ClientDiagnostics","Microsoft.VisualStudio.ClientDiagnostics.Targeted","Microsoft.VisualStudio.ClientDiagnostics.Resources","Microsoft.VisualStudio.PackageGroup.CommunityCore","Microsoft.VisualStudio.ProjectSystem.Full","Microsoft.VisualStudio.ProjectSystem","Microsoft.VisualStudio.Community.x86","Microsoft.VisualStudio.Community.x64","Microsoft.VisualStudio.Community","Microsoft.IntelliTrace.CollectorCab","Microsoft.VisualStudio.Community.Resources","Microsoft.VisualStudio.Net.Eula.Resources","Microsoft.VisualStudio.WebSiteProject.DTE","Microsoft.MSHtml","Microsoft.VisualStudio.Platform.CallHierarchy","Microsoft.VisualStudio.Community.Msi.Resources","Microsoft.VisualStudio.Community.Msi","Microsoft.VisualStudio.Devenv.Msi","Microsoft.VisualStudio.MinShell.Interop.Msi","Microsoft.VisualStudio.Editors","Microsoft.VisualStudio.Product.Community","Microsoft.VisualStudio.Workload.CoreEditor","Microsoft.VisualStudio.Component.CoreEditor","Microsoft.VisualStudio.PackageGroup.CoreEditor","Microsoft.VisualCpp.Tools.Common.UtilsPrereq","Microsoft.VisualCpp.Tools.Common.Utils","Microsoft.VisualCpp.Tools.Common.Utils.Resources","Microsoft.VisualStudio.PackageGroup.VsDevCmd","Microsoft.VisualStudio.VsDevCmd.Ext.NetFxSdk","Microsoft.VisualStudio.VsDevCmd.Core.WinSdk","Microsoft.VisualStudio.VsDevCmd.Core.DotNet","Microsoft.VisualStudio.VC.DevCmd","Microsoft.VisualStudio.VC.DevCmd.Resources","Microsoft.VisualStudio.VirtualTree","Microsoft.VisualStudio.PackageGroup.Progression","Microsoft.VisualStudio.PerformanceProvider","Microsoft.VisualStudio.GraphModel","Microsoft.VisualStudio.GraphProvider","Microsoft.DiaSymReader","Microsoft.Build.Dependencies","Microsoft.Build.FileTracker.Msi","Microsoft.Build","Microsoft.VisualStudio.PackageGroup.NuGet","Microsoft.VisualStudio.NuGet.Core","Microsoft.VisualStudio.TextMateGrammars","Microsoft.VisualStudio.PackageGroup.TeamExplorer.Common","Microsoft.VisualStudio.TeamExplorer","Microsoft.ServiceHub","Microsoft.VisualStudio.ProjectServices","Microsoft.VisualStudio.OpenFolder.VSIX","Microsoft.VisualStudio.FileHandler.Msi","Microsoft.VisualStudio.FileHandler.Msi","Microsoft.VisualStudio.PackageGroup.MinShell","Microsoft.VisualStudio.MinShell.Interop","Microsoft.VisualStudio.Log","Microsoft.VisualStudio.Log.Targeted","Microsoft.VisualStudio.Log.Resources","Microsoft.VisualStudio.Finalizer","Microsoft.VisualStudio.Devenv","Microsoft.VisualStudio.Devenv.Resources","Microsoft.VisualStudio.CoreEditor","Microsoft.VisualStudio.Platform.NavigateTo","Microsoft.VisualStudio.Connected","Microsoft.VisualStudio.PerfLib","Microsoft.VisualStudio.Connected.Resources","Microsoft.VisualStudio.MinShell","Microsoft.VisualStudio.Setup.Configuration","Microsoft.VisualStudio.MinShell.Platform","Microsoft.VisualStudio.MinShell.Platform.Resources","Microsoft.VisualStudio.MefHosting","Microsoft.VisualStudio.MefHosting.Resources","Microsoft.VisualStudio.Initializer","Microsoft.VisualStudio.ExtensionManager","Microsoft.VisualStudio.Platform.Editor","Microsoft.VisualStudio.MinShell.x86","Microsoft.VisualStudio.NativeImageSupport","Microsoft.VisualStudio.MinShell.Msi","Microsoft.VisualStudio.MinShell.Msi.Resources","Microsoft.VisualStudio.LanguageServer","Microsoft.VisualStudio.Devenv.Config","Microsoft.VisualStudio.MinShell.Resources","Microsoft.Net.PackageGroup.4.7.2.Redist","Microsoft.Net.4.7.2.FullRedist","Microsoft.VisualStudio.Branding.Community"]}]
diff --git a/deps/npm/node_modules/node-gyp/test/fixtures/VS_2019_Preview.txt b/deps/npm/node_modules/node-gyp/test/fixtures/VS_2019_Preview.txt
deleted file mode 100644
index 806509e7ce8652..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/fixtures/VS_2019_Preview.txt
+++ /dev/null
@@ -1 +0,0 @@
-[{"path":"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Preview","version":"16.0.28608.199","packages":["Microsoft.VisualStudio.Product.Enterprise","Microsoft.VisualStudio.Workload.NativeDesktop","Microsoft.VisualStudio.Component.VC.TestAdapterForGoogleTest","Microsoft.VisualStudio.VC.Ide.TestAdapterForGoogleTest","Microsoft.VisualStudio.Component.VC.TestAdapterForBoostTest","Microsoft.VisualStudio.VC.Ide.TestAdapterForBoostTest","Microsoft.VisualStudio.Component.VC.ATL","Microsoft.VisualStudio.VC.Ide.ATL","Microsoft.VisualStudio.VC.Ide.ATL.Resources","Microsoft.VisualCpp.ATL.X86","Microsoft.VisualCpp.ATL.X64","Microsoft.VisualCpp.ATL.Source","Microsoft.VisualCpp.ATL.Headers","Microsoft.VisualStudio.Component.VC.CMake.Project","Microsoft.VisualStudio.VC.CMake","Microsoft.VisualStudio.VC.CMake.Project","Microsoft.VisualStudio.VC.ExternalBuildFramework","Microsoft.VisualStudio.Component.VC.DiagnosticTools","Microsoft.VisualStudio.Component.Graphics.Tools","Microsoft.VisualStudio.Graphics.Viewers","Microsoft.VisualStudio.Graphics.Viewers.Resources","Microsoft.VisualStudio.Graphics.EnableTools","Microsoft.VisualStudio.Graphics.Msi","Microsoft.VisualStudio.Graphics.Msi","Microsoft.VisualStudio.Graphics.Analyzer","Microsoft.VisualStudio.Graphics.Analyzer.Targeted","Microsoft.VisualStudio.Graphics.Analyzer.Resources","Microsoft.VisualStudio.Graphics.Appid","Microsoft.VisualStudio.Graphics.Appid.Resources","Microsoft.VisualStudio.Component.Windows10SDK.17763","Win10SDK_10.0.17763","Microsoft.VisualStudio.Component.VC.Tools.x86.x64","Microsoft.VisualCpp.CodeAnalysis.Extensions","Microsoft.VisualCpp.CodeAnalysis.Extensions.X86","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X86","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X86.Resources","Microsoft.VisualCpp.CodeAnalysis.Extensions.X64","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X64","Microsoft.VisualCpp.CodeAnalysis.ConcurrencyCheck.X64.Resources","Microsoft.VisualCpp.Tools.HostX64.TargetX86","Microsoft.VisualCpp.VCTip.HostX64.TargetX86","Microsoft.VisualCpp.Tools.HostX64.TargetX86.Resources","Microsoft.VisualCpp.Tools.HostX64.TargetX64","Microsoft.VisualCpp.VCTip.HostX64.TargetX64","Microsoft.VisualCpp.Tools.HostX64.TargetX64.Resources","Microsoft.VisualCpp.Premium.Tools.HostX86.TargetX64","Microsoft.VisualCpp.Premium.Tools.Hostx86.Targetx64.Resources","Microsoft.VisualCpp.Premium.Tools.HostX86.TargetX86","Microsoft.VisualCpp.Premium.Tools.HostX86.TargetX86.Resources","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX86","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX86.Resources","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX64","Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX64.Resources","Microsoft.VisualCpp.PGO.X86","Microsoft.VisualCpp.PGO.X64","Microsoft.VisualCpp.PGO.Headers","Microsoft.VisualCpp.CRT.x86.Store","Microsoft.VisualCpp.CRT.x86.OneCore.Desktop","Microsoft.VisualCpp.CRT.x64.Store","Microsoft.VisualCpp.CRT.x64.OneCore.Desktop","Microsoft.VisualCpp.CRT.Redist.x86.OneCore.Desktop","Microsoft.VisualCpp.CRT.Redist.x64.OneCore.Desktop","Microsoft.VisualStudio.PackageGroup.VC.Tools.x86","Microsoft.VisualCpp.Tools.HostX86.TargetX64","Microsoft.VisualCpp.VCTip.hostX86.targetX64","Microsoft.VisualCpp.Tools.Hostx86.Targetx64.Resources","Microsoft.VisualCpp.Tools.HostX86.TargetX86","Microsoft.VisualCpp.VCTip.hostX86.targetX86","Microsoft.VisualCpp.Tools.HostX86.TargetX86.Resources","Microsoft.VisualCpp.Tools.Core.Resources","Microsoft.VisualCpp.Tools.Core.x86","Microsoft.VisualCpp.DIA.SDK","Microsoft.VisualCpp.CRT.x86.Desktop","Microsoft.VisualCpp.CRT.x64.Desktop","Microsoft.VisualCpp.CRT.Source","Microsoft.VisualCpp.CRT.Redist.X86","Microsoft.VisualCpp.CRT.Redist.X64","Microsoft.VisualCpp.CRT.Redist.Resources","Microsoft.VisualCpp.RuntimeDebug.14","Microsoft.VisualCpp.RuntimeDebug.14","Microsoft.VisualCpp.CRT.Headers","Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core","Microsoft.VisualStudio.PackageGroup.TestTools.Native","Microsoft.VisualStudio.ComponentGroup.ArchitectureTools.Native","Microsoft.VisualStudio.Component.ClassDesigner","Microsoft.VisualStudio.ClassDesigner","Microsoft.VisualStudio.ClassDesigner.Resources","Microsoft.VisualStudio.Component.VC.Redist.14.Latest","Microsoft.VisualCpp.Redist.14.Latest","Microsoft.VisualCpp.Redist.14.Latest","Microsoft.VisualStudio.VC.Templates.UnitTest","Microsoft.VisualStudio.VC.UnitTest.Desktop.Build.Core","Microsoft.VisualStudio.TestTools.TestPlatform.V1.CPP","Microsoft.VisualStudio.VC.Templates.UnitTest.Resources","Microsoft.VisualStudio.VC.Templates.Desktop","Microsoft.VisualStudio.Component.VC.CoreIde","Microsoft.VisualStudio.VC.Ide.Pro","Microsoft.VisualStudio.VC.Ide.Pro.Resources","Microsoft.VisualStudio.VC.Templates.Pro","Microsoft.VisualStudio.VC.Templates.Pro.Resources","Microsoft.VisualStudio.VC.Items.Pro","Microsoft.VisualStudio.PackageGroup.VC.CoreIDE.Reduced","Microsoft.VisualStudio.VC.Ide.x64","Microsoft.VisualStudio.PackageGroup.VC.CoreIDE.Express","Microsoft.VisualStudio.VC.MSBuild.X64.v142","Microsoft.VisualStudio.VC.MSBuild.X64","Microsoft.VS.VC.MSBuild.X64.Resources","Microsoft.VisualStudio.VC.MSBuild.ARM.v142","Microsoft.VisualStudio.VC.MSBuild.ARM","Microsoft.VisualStudio.VC.MSBuild.x86.v142","Microsoft.VisualStudio.VC.MSBuild.X86","Microsoft.VisualStudio.VC.MSBuild.Base","Microsoft.VisualStudio.VC.MSBuild.Base.Resources","Microsoft.VisualStudio.VC.Ide.WinXPlus","Microsoft.VisualStudio.VC.Ide.Dskx","Microsoft.VisualStudio.VC.Ide.Dskx.Resources","Microsoft.VisualStudio.VC.Ide.Base","Microsoft.VisualStudio.VC.Ide.LanguageService","Microsoft.VisualStudio.VC.Ide.Core","Microsoft.VisualStudio.VC.Ide.Core.Resources","Microsoft.VisualStudio.VC.Ide.VCPkgDatabase","Microsoft.VisualStudio.VC.Ide.Progression.Enterprise","Microsoft.VisualStudio.VC.Ide.ProjectSystem","Microsoft.VisualStudio.VC.Ide.ProjectSystem.Resources","Microsoft.VisualStudio.VC.Ide.Core.VCProjectEngine","Microsoft.VisualStudio.VC.Ide.Core.VCProjectEngine.Resources","Microsoft.VisualStudio.VC.Ide.LanguageService.Resources","Microsoft.VisualStudio.VC.Ide.Base.Resources","Microsoft.VisualStudio.Component.CodeMap","Microsoft.VisualStudio.Component.GraphDocument","Microsoft.VisualStudio.Vmp","Microsoft.VisualStudio.GraphDocument","Microsoft.VisualStudio.GraphDocument.Resources","Microsoft.VisualStudio.CodeMap","Microsoft.VisualStudio.Component.SQL.LocalDB.Runtime","Microsoft.VisualStudio.Component.SQL.NCLI","sqllocaldb","sqlncli","Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions","Microsoft.VisualStudio.WebToolsExtensions","Microsoft.VisualStudio.WebTools","Microsoft.VisualStudio.WebTools.Resources","Microsoft.VisualStudio.WebTools.MSBuild","Microsoft.VisualStudio.PackageGroup.Debugger.Script","Microsoft.VisualStudio.Debugger.Script.Msi","Microsoft.VisualStudio.Debugger.Script","Microsoft.VisualStudio.Debugger.Script","Microsoft.VisualStudio.Debugger.Script.Resources","Microsoft.VisualStudio.Debugger.Script.Resources","Microsoft.VisualStudio.VC.Ide.MDD","Microsoft.VisualStudio.Component.NuGet","Microsoft.CredentialProvider","Component.Microsoft.VisualStudio.LiveShare","Microsoft.VisualStudio.LiveShare","Microsoft.VisualStudio.Component.Debugger.JustInTime","Microsoft.VisualStudio.Debugger.ImmersiveActivateHelper.Msi","Microsoft.VisualStudio.Debugger.JustInTime","Microsoft.VisualStudio.Debugger.JustInTime.Msi","Microsoft.VisualStudio.Component.IntelliTrace.FrontEnd","Microsoft.IntelliTrace.DiagnosticsHubAgent.Targeted","Microsoft.IntelliTrace.Debugger","Microsoft.IntelliTrace.Debugger.Targeted","Microsoft.IntelliTrace.FrontEnd","Microsoft.DiagnosticsHub.Instrumentation","Microsoft.DiagnosticsHub.CpuSampling","Microsoft.DiagnosticsHub.CpuSampling.Targeted","Microsoft.PackageGroup.DiagnosticsHub.Platform","Microsoft.DiagnosticsHub.Collection.StopService.Uninstall","Microsoft.DiagnosticsHub.Runtime","Microsoft.DiagnosticsHub.Runtime.Targeted","Microsoft.DiagnosticsHub.Runtime.Resources","Microsoft.DiagnosticsHub.Collection","Microsoft.DiagnosticsHub.Collection.Service","Microsoft.DiagnosticsHub.Collection.StopService.Install","Microsoft.VisualStudio.Dsl.GraphObject","Microsoft.Net.4.TargetingPack","Microsoft.VisualStudio.VC.Ide.ResourceEditor","Microsoft.VisualStudio.VC.Ide.ResourceEditor.Resources","Microsoft.VisualStudio.NuGet.Licenses","Microsoft.WebTools.Shared","Microsoft.VisualStudio.WebToolsExtensions.DotNet.Core.ItemTemplates","Microsoft.VisualStudio.Component.TextTemplating","Microsoft.VisualStudio.TextTemplating.MSBuild","Microsoft.VisualStudio.TextTemplating.Integration","Microsoft.VisualStudio.TextTemplating.Core","Microsoft.VisualStudio.TextTemplating.Integration.Resources","Microsoft.VisualStudio.ProTools","sqlsysclrtypes","sqlsysclrtypes","SQLCommon","Microsoft.VisualStudio.ProTools.Resources","Microsoft.VisualStudio.NuGet.Core","Microsoft.VisualStudio.PackageGroup.TestTools.CodeCoverage","Microsoft.VisualStudio.PackageGroup.IntelliTrace.Core","Microsoft.IntelliTrace.Core","Microsoft.IntelliTrace.Core.Concord","Microsoft.IntelliTrace.Core.Targeted","Microsoft.IntelliTrace.ProfilerProxy.Msi.x64","Microsoft.IntelliTrace.ProfilerProxy.Msi","Microsoft.VisualStudio.TestTools.DynamicCodeCoverage","Microsoft.VisualStudio.TestTools.CodeCoverage.Msi","Microsoft.VisualStudio.TestTools.CodeCoverage","Microsoft.Icecap.Analysis","Microsoft.Icecap.Analysis.Targeted","Microsoft.Icecap.Analysis.Resources","Microsoft.Icecap.Analysis.Resources.Targeted","Microsoft.Icecap.Collection.Msi","Microsoft.Icecap.Collection.Msi.Targeted","Microsoft.Icecap.Collection.Msi.Resources","Microsoft.Icecap.Collection.Msi.Resources.Targeted","Microsoft.VisualStudio.PackageGroup.TestTools.Core","Microsoft.VisualStudio.PackageGroup.TestTools.TestPlatform.V2.CLI","Microsoft.VisualStudio.TestTools.TestPlatform.V2.CLI","Microsoft.VisualStudio.PackageGroup.TestTools.TestPlatform.V1.CLI","Microsoft.VisualStudio.TestTools.TestPlatform.V1.CLI","Microsoft.VisualStudio.TestTools.Pex.Common","Microsoft.VisualStudio.PackageGroup.TestTools.TestPlatform.Legacy","Microsoft.VisualStudio.PackageGroup.MinShell.Interop","Microsoft.VisualStudio.TestTools.TP.Legacy.Tips.Msi","Microsoft.VisualStudio.TestTools.TP.Legacy.Tips.Common","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Tips","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Tips.Resources","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.TestTools","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Remote","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Professional","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Core.Premium","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Common","Microsoft.VisualStudio.TestTools.TP.Legacy.Common.Res","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Core","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Core.Resources","Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Agent","Microsoft.VisualStudio.PackageGroup.TestTools.TestPlatform.IDE","Microsoft.VisualStudio.TestTools.TestWIExtension","Microsoft.VisualStudio.TestTools.TestPlatform.IDE","Microsoft.VisualStudio.PackageGroup.TestTools.DataCollectors","Microsoft.VisualStudio.TestTools.NE.Msi.Targeted","Microsoft.VisualStudio.TestTools.NetworkEmulation","Microsoft.VisualStudio.TestTools.DataCollectors","Microsoft.VisualCpp.CRT.ClickOnce.Msi","Microsoft.VisualStudio.WebTools.WSP.FSA","Microsoft.VisualStudio.WebTools.WSP.FSA.Resources","Microsoft.VisualStudio.Component.Static.Analysis.Tools","Microsoft.VisualCpp.Redist.14","Microsoft.VisualCpp.Redist.14","Microsoft.VisualStudio.StaticAnalysis","Microsoft.VisualStudio.StaticAnalysis.Resources","Microsoft.VisualStudio.PackageGroup.Community","Microsoft.VisualStudio.Community.Extra.Resources","Microsoft.VisualStudio.Community.Extra","Microsoft.VisualStudio.PackageGroup.Core","Microsoft.VisualStudio.CodeSense","Microsoft.VisualStudio.CodeSense.Community","Microsoft.VisualStudio.TestTools.TeamFoundationClient","Microsoft.VisualStudio.PackageGroup.Debugger.Core","Microsoft.VisualStudio.PackageGroup.Debugger.TimeTravel.Record","Microsoft.VisualStudio.Debugger.TimeTravel.Runtime","Microsoft.VisualStudio.Debugger.TimeTravel.Runtime","Microsoft.VisualStudio.Debugger.TimeTravel.Agent","Microsoft.VisualStudio.Debugger.TimeTravel.Record","Microsoft.VisualStudio.Debugger.VSCodeDebuggerHost","Microsoft.VisualStudio.VC.Ide.Debugger","Microsoft.VisualStudio.VC.Ide.Debugger.Concord","Microsoft.VisualStudio.VC.Ide.Debugger.Concord.Resources","Microsoft.VisualStudio.VC.Ide.Debugger.Resources","Microsoft.VisualStudio.VC.Ide.Common","Microsoft.VisualStudio.VC.Ide.Common.Resources","Microsoft.VisualStudio.Debugger.Parallel","Microsoft.VisualStudio.Debugger.Parallel.Resources","Microsoft.VisualStudio.Debugger.CollectionAgents","Microsoft.VisualStudio.Debugger.Managed","Microsoft.VisualStudio.Debugger.Concord.Managed","Microsoft.VisualStudio.Debugger.Concord.Managed.Resources","Microsoft.VisualStudio.Debugger.Managed.Resources","Microsoft.VisualStudio.Debugger.Remote","Microsoft.VisualStudio.Debugger.Concord.Remote","Microsoft.VisualStudio.Debugger.Concord.Remote.Resources","Microsoft.VisualStudio.Debugger.Remote","Microsoft.VisualStudio.Debugger.Concord.Remote","Microsoft.VisualStudio.Debugger.Concord.Remote.Resources","Microsoft.VisualStudio.Debugger.Remote.Resources","Microsoft.VisualStudio.Debugger.Remote.Resources","Microsoft.VisualStudio.Debugger","Microsoft.VisualStudio.Debugger.Package.DiagHub.Client.VSx86","Microsoft.VisualStudio.Debugger.Remote.DiagHub.Client","Microsoft.VisualStudio.Debugger.Remote.DiagHub.Client","Microsoft.VisualStudio.VC.MSVCDis","Microsoft.VisualStudio.ScriptedHost","Microsoft.VisualStudio.ScriptedHost.Targeted","Microsoft.VisualStudio.ScriptedHost.Resources","Microsoft.IntelliTrace.DiagnosticsHub","Microsoft.VisualStudio.Debugger.Concord","Microsoft.VisualStudio.Debugger.Concord.Resources","Microsoft.VisualStudio.Debugger.Resources","Microsoft.PackageGroup.ClientDiagnostics","Microsoft.VisualStudio.AppResponsiveness","Microsoft.VisualStudio.AppResponsiveness.Targeted","Microsoft.VisualStudio.AppResponsiveness.Resources","Microsoft.VisualStudio.ClientDiagnostics","Microsoft.VisualStudio.ClientDiagnostics.Targeted","Microsoft.VisualStudio.ClientDiagnostics.Resources","Microsoft.VisualStudio.PackageGroup.ProfessionalCore","Microsoft.VisualStudio.Professional","Microsoft.VisualStudio.Professional.Msi","Microsoft.VisualStudio.PackageGroup.EnterpriseCore","Microsoft.VisualStudio.Enterprise.Msi","Microsoft.VisualStudio.Enterprise","Microsoft.ShDocVw","Microsoft.VisualStudio.PackageGroup.CommunityCore","Microsoft.VisualStudio.ProjectSystem.Full","Microsoft.VisualStudio.ProjectSystem","Microsoft.VisualStudio.Community.x86","Microsoft.VisualStudio.Community.x64","Microsoft.VisualStudio.Community","Microsoft.IntelliTrace.CollectorCab","Microsoft.VisualStudio.Community.Resources","Microsoft.VisualStudio.WebSiteProject.DTE","Microsoft.MSHtml","Microsoft.VisualStudio.Platform.CallHierarchy","Microsoft.VisualStudio.Community.Msi.Resources","Microsoft.VisualStudio.Community.Msi","Microsoft.VisualStudio.Devenv.Msi","Microsoft.VisualStudio.MinShell.Interop.Msi","Microsoft.VisualStudio.Editors","Microsoft.VisualStudio.Net.Eula.Resources","Microsoft.CodeAnalysis.ExpressionEvaluator","Microsoft.CodeAnalysis.VisualStudio.Setup","Microsoft.Component.MSBuild","Microsoft.NuGet.Build.Tasks","Microsoft.VisualStudio.Component.Roslyn.Compiler","Microsoft.CodeAnalysis.Compilers","Microsoft.VisualStudio.Workload.CoreEditor","Microsoft.VisualStudio.Component.CoreEditor","Microsoft.VisualStudio.PackageGroup.CoreEditor","Microsoft.VisualCpp.Tools.Common.UtilsPrereq","Microsoft.VisualCpp.Tools.Common.Utils","Microsoft.VisualCpp.Tools.Common.Utils.Resources","Microsoft.VisualStudio.PackageGroup.VsDevCmd","Microsoft.VisualStudio.VsDevCmd.Ext.NetFxSdk","Microsoft.VisualStudio.VsDevCmd.Core.WinSdk","Microsoft.VisualStudio.VsDevCmd.Core.DotNet","Microsoft.VisualStudio.VC.DevCmd","Microsoft.VisualStudio.VC.DevCmd.Resources","Microsoft.VisualStudio.VirtualTree","Microsoft.VisualStudio.PackageGroup.Progression","Microsoft.VisualStudio.PerformanceProvider","Microsoft.VisualStudio.GraphModel","Microsoft.VisualStudio.GraphProvider","Microsoft.DiaSymReader","Microsoft.Build.Dependencies","Microsoft.Build.FileTracker.Msi","Microsoft.Build","Microsoft.VisualStudio.TextMateGrammars","Microsoft.VisualStudio.PackageGroup.TeamExplorer.Common","Microsoft.VisualStudio.TeamExplorer","Microsoft.ServiceHub","Microsoft.VisualStudio.ProjectServices","Microsoft.VisualStudio.SLNX.VSIX","Microsoft.VisualStudio.FileHandler.Msi","Microsoft.VisualStudio.FileHandler.Msi","Microsoft.VisualStudio.PackageGroup.MinShell","Microsoft.VisualStudio.MinShell.Interop","Microsoft.VisualStudio.Log","Microsoft.VisualStudio.Log.Targeted","Microsoft.VisualStudio.Log.Resources","Microsoft.VisualStudio.Finalizer","Microsoft.VisualStudio.Devenv","Microsoft.VisualStudio.Devenv.Resources","Microsoft.VisualStudio.CoreEditor","Microsoft.VisualStudio.Platform.NavigateTo","Microsoft.VisualStudio.Connected","Microsoft.VisualStudio.Connected.Resources","Microsoft.VisualStudio.MinShell","Microsoft.VisualStudio.Setup.Configuration","Microsoft.VisualStudio.Platform.Search","Microsoft.VisualStudio.MinShell.Platform","Microsoft.VisualStudio.MinShell.Platform.Resources","Microsoft.VisualStudio.MefHosting","Microsoft.VisualStudio.MefHosting.Resources","Microsoft.VisualStudio.Initializer","Microsoft.VisualStudio.ExtensionManager","Microsoft.VisualStudio.Platform.Editor","Microsoft.VisualStudio.MinShell.x86","Microsoft.VisualStudio.NativeImageSupport","Microsoft.VisualStudio.MinShell.Msi","Microsoft.VisualStudio.MinShell.Msi.Resources","Microsoft.VisualStudio.LanguageServer","Microsoft.VisualStudio.Devenv.Config","Microsoft.VisualStudio.MinShell.Resources","Microsoft.Net.PackageGroup.4.7.2.Redist","Microsoft.VisualStudio.Branding.Enterprise"]}]
diff --git a/deps/npm/node_modules/node-gyp/test/fixtures/VS_2022_Community_workload.txt b/deps/npm/node_modules/node-gyp/test/fixtures/VS_2022_Community_workload.txt
deleted file mode 100644
index 7cd20f85989261..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/fixtures/VS_2022_Community_workload.txt
+++ /dev/null
@@ -1,569 +0,0 @@
-[
-    {
-        "path": "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community",
-        "version": "17.4.33213.308",
-        "packages": [
-            "Microsoft.VisualStudio.Product.Community",
-            "Microsoft.VisualStudio.PackageGroup.LiveShare.VSCore",
-            "Microsoft.VisualStudio.LiveShare.VSCore",
-            "Microsoft.VisualStudio.Workload.NativeDesktop",
-            "Microsoft.VisualStudio.Component.VC.ASAN",
-            "Microsoft.VisualCpp.ASAN.X86",
-            "Microsoft.VC.14.34.17.4.ASAN.X86.base",
-            "Microsoft.VC.14.34.17.4.ASAN.X64.base",
-            "Microsoft.VC.14.34.17.4.ASAN.Headers.base",
-            "Microsoft.VisualStudio.VC.IDE.Project.Factories",
-            "Microsoft.VisualStudio.Component.VC.TestAdapterForGoogleTest",
-            "Microsoft.VisualStudio.VC.Ide.TestAdapterForGoogleTest",
-            "Microsoft.VisualStudio.Component.VC.TestAdapterForBoostTest",
-            "Microsoft.VisualStudio.VC.Ide.TestAdapterForBoostTest",
-            "Microsoft.VisualStudio.Component.VC.CMake.Project",
-            "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions.CMake",
-            "Microsoft.VisualStudio.VC.CMake",
-            "Microsoft.VisualStudio.VC.CMake.Project",
-            "Microsoft.VisualStudio.VC.CMake.Client",
-            "Microsoft.VisualStudio.VC.ExternalBuildFramework",
-            "Microsoft.VisualStudio.Component.VC.DiagnosticTools",
-            "Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core",
-            "Microsoft.VisualStudio.PackageGroup.TestTools.Native",
-            "Microsoft.VisualStudio.Component.VC.Redist.14.Latest",
-            "Microsoft.VisualStudio.VC.Templates.UnitTest",
-            "Microsoft.VisualStudio.VC.UnitTest.Desktop.Build.Core",
-            "Microsoft.VisualStudio.TestTools.TestPlatform.V1.CPP",
-            "Microsoft.VisualStudio.VC.Templates.UnitTest.Resources",
-            "Microsoft.VisualStudio.VC.Templates.Desktop",
-            "Microsoft.VisualStudio.Component.Graphics",
-            "Microsoft.VisualStudio.Graphics.Viewers",
-            "Microsoft.VisualStudio.Graphics.Viewers.Resources",
-            "Microsoft.VisualStudio.Component.VC.ATL.ARM64",
-            "Microsoft.VisualCpp.ATL.ARM64",
-            "Microsoft.VC.14.34.17.4.ATL.ARM64.base",
-            "Microsoft.VisualStudio.Component.VC.ATL",
-            "Microsoft.VisualStudio.VC.Ide.ATL",
-            "Microsoft.VisualStudio.VC.Ide.ATL.Resources",
-            "Microsoft.VisualCpp.ATL.X86",
-            "Microsoft.VC.14.34.17.4.ATL.X86.base",
-            "Microsoft.VisualCpp.ATL.X64",
-            "Microsoft.VC.14.34.17.4.ATL.X64.base",
-            "Microsoft.VC.14.34.17.4.Props.ATLMFC",
-            "Microsoft.VisualCpp.ATL.Source",
-            "Microsoft.VC.14.34.17.4.ATL.Source.base",
-            "Microsoft.VisualCpp.ATL.Headers",
-            "Microsoft.VC.14.34.17.4.ATL.Headers.base",
-            "Microsoft.VC.14.34.17.4.Servicing.ATL",
-            "Microsoft.VisualStudio.Component.VC.Tools.ARM64",
-            "Microsoft.VisualStudio.VC.MSBuild.v170.ARM64.v143",
-            "Microsoft.VisualStudio.VC.MSBuild.v170.ARM64",
-            "Microsoft.VS.VC.vcvars.arm64.Shortcuts",
-            "Microsoft.VisualCpp.CA.Ext.Hostx64.TargetARM64",
-            "Microsoft.VC.14.34.17.4.CA.Ext.Hostx64.TargetARM64.base",
-            "Microsoft.VC.14.34.17.4.CA.Ext.Hostx64.TargetARM64.Res.base",
-            "Microsoft.VisualCpp.CA.Ext.Hostx86.TargetARM64",
-            "Microsoft.VC.14.34.17.4.CA.Ext.Hostx86.TargetARM64.base",
-            "Microsoft.VC.14.34.17.4.CA.Ext.Hostx86.TargetARM64.Res.base",
-            "Microsoft.VisualCpp.CA.Ext.HostARM64.TargetARM64",
-            "Microsoft.VC.14.34.17.4.CA.Ext.HostARM64.TargetARM64.base",
-            "Microsoft.VC.14.34.17.4.CA.Ext.HostARM64.TargetARM64.Res.base",
-            "Microsoft.VisualCpp.Tools.Hostx86.Targetarm64",
-            "Microsoft.VC.14.34.17.4.Tools.Hostx86.Targetarm64.base",
-            "Microsoft.VC.14.34.17.4.Tools.HostX86.TargetARM64.Res.base",
-            "Microsoft.VisualCpp.Tools.HostARM64.TargetARM64",
-            "Microsoft.VC.14.34.17.4.Tools.HostARM64.TargetARM64.base",
-            "Microsoft.VC.14.34.17.4.Tools.HostARM64.TargetARM64.Res.base",
-            "Microsoft.VisualCpp.CRT.Redist.ARM64.OneCore.Desktop",
-            "Microsoft.VC.14.34.17.4.CRT.Redist.ARM64.OneCore.Desktop.base",
-            "Microsoft.VisualCpp.CRT.Redist.ARM64",
-            "Microsoft.VC.14.34.17.4.CRT.Redist.ARM64.base",
-            "Microsoft.VisualCpp.CRT.ARM64.OneCore.Desktop",
-            "Microsoft.VC.14.34.17.4.CRT.ARM64.OneCore.Desktop.base",
-            "Microsoft.VC.14.34.17.4.CRT.ARM64.OneCore.Desktop.debug.base",
-            "Microsoft.VisualCpp.CRT.ARM64.Store",
-            "Microsoft.VC.14.34.17.4.CRT.ARM64.Store.base",
-            "Microsoft.VisualCpp.CRT.ARM64.Desktop",
-            "Microsoft.VC.14.34.17.4.CRT.ARM64.Desktop.base",
-            "Microsoft.VC.14.34.17.4.CRT.ARM64.Desktop.debug.base",
-            "Microsoft.VisualStudio.PackageGroup.VC.Tools.x64.ARM64",
-            "Microsoft.VisualCpp.Tools.Core",
-            "Microsoft.VisualCpp.PGO.ARM64",
-            "Microsoft.VC.14.34.17.4.PGO.ARM64.base",
-            "Microsoft.VisualCpp.Premium.Tools.Hostx86.Targetarm64",
-            "Microsoft.VC.14.34.17.4.Premium.Tools.Hostx86.Targetarm64.base",
-            "Microsoft.VC.14.34.17.4.Prem.HostX86.TargetARM64.Res.base",
-            "Microsoft.VisualCpp.Premium.Tools.HostX64.TargetARM64",
-            "Microsoft.VC.14.34.17.4.Premium.Tools.HostX64.TargetARM64.base",
-            "Microsoft.VC.14.34.17.4.Prem.HostX64.TargetARM64.Res.base",
-            "Microsoft.VisualCpp.Premium.Tools.ARM64.Base",
-            "Microsoft.VC.14.34.17.4.Premium.Tools.ARM64.Base.base",
-            "Microsoft.VisualCpp.Tools.HostX64.TargetARM64",
-            "Microsoft.VC.14.34.17.4.Tools.HostX64.TargetARM64.base",
-            "Microsoft.VC.14.34.17.4.Props.ARM64",
-            "Microsoft.VC.14.34.17.4.Tools.HostX64.TargetARM64.Res.base",
-            "Microsoft.VisualStudio.Component.VC.Tools.ARM64EC",
-            "Microsoft.VisualStudio.Component.Windows11SDK.22621",
-            "Win11SDK_10.0.22621",
-            "Microsoft.VisualStudio.VC.MSBuild.v170.ARM64EC.v143",
-            "Microsoft.VisualStudio.VC.MSBuild.v170.ARM64EC",
-            "Microsoft.VisualCpp.CRT.ARM64EC.Store",
-            "Microsoft.VC.14.34.17.4.CRT.ARM64EC.Store.base",
-            "Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
-            "Microsoft.VisualCpp.CodeAnalysis.Extensions",
-            "Microsoft.VisualCpp.CA.Ext.HostARM64.Targetx64",
-            "Microsoft.VC.14.34.17.4.CA.Ext.HostARM64.Targetx64.base",
-            "Microsoft.VC.14.34.17.4.CA.Ext.HostARM64.Targetx64.Res.base",
-            "Microsoft.VisualCpp.CA.Ext.HostARM64.Targetx86",
-            "Microsoft.VC.14.34.17.4.CA.Ext.HostARM64.Targetx86.base",
-            "Microsoft.VC.14.34.17.4.CA.Ext.HostARM64.Targetx86.Res.base",
-            "Microsoft.VisualCpp.CA.Ext.Hostx86.Targetx64",
-            "Microsoft.VC.14.34.17.4.CA.Ext.Hostx86.Targetx64.base",
-            "Microsoft.VC.14.34.17.4.CA.Ext.Hostx86.Targetx64.Res.base",
-            "Microsoft.VisualCpp.CA.Ext.Hostx86.Targetx86",
-            "Microsoft.VC.14.34.17.4.CA.Ext.Hostx86.Targetx86.base",
-            "Microsoft.VC.14.34.17.4.CA.Ext.Hostx86.Targetx86.Res.base",
-            "Microsoft.VisualCpp.CA.Ext.Hostx64.Targetx64",
-            "Microsoft.VC.14.34.17.4.CA.Ext.Hostx64.Targetx64.base",
-            "Microsoft.VC.14.34.17.4.CA.Ext.Hostx64.Targetx64.Res.base",
-            "Microsoft.VisualCpp.CA.Ext.Hostx64.Targetx86",
-            "Microsoft.VC.14.34.17.4.CA.Ext.Hostx64.Targetx86.base",
-            "Microsoft.VC.14.34.17.4.Servicing.CAExtensions",
-            "Microsoft.VC.14.34.17.4.CA.Ext.Hostx64.Targetx86.Res.base",
-            "Microsoft.VisualCpp.Tools.HostX64.TargetX86",
-            "Microsoft.VC.14.34.17.4.Tools.HostX64.TargetX86.base",
-            "Microsoft.VC.14.34.17.4.Tools.HostX64.TargetX86.Res.base",
-            "Microsoft.VisualCpp.Tools.HostX64.TargetX64",
-            "Microsoft.VC.14.34.17.4.Tools.HostX64.TargetX64.base",
-            "Microsoft.VC.14.34.17.4.Tools.HostX64.TargetX64.Res.base",
-            "Microsoft.VisualCpp.Tools.HostARM64.TargetX86",
-            "Microsoft.VC.14.34.17.4.Tools.HostARM64.TargetX86.base",
-            "Microsoft.VisualCpp.RuntimeDebug.14",
-            "Microsoft.VC.14.34.17.4.Tools.HostARM64.TargetX86.Res.base",
-            "Microsoft.VisualCpp.Tools.HostARM64.TargetX64",
-            "Microsoft.VC.14.34.17.4.Tools.HostARM64.TargetX64.base",
-            "Microsoft.VisualCpp.RuntimeDebug.14.ARM64",
-            "Microsoft.VisualCpp.Redist.14.Latest",
-            "Microsoft.VisualCpp.Redist.14.Latest",
-            "Microsoft.VC.14.34.17.4.Tools.HostARM64.Targetx64.Res.base",
-            "Microsoft.VisualCpp.Premium.Tools.HostX86.TargetX64",
-            "Microsoft.VC.14.34.17.4.Premium.Tools.HostX86.TargetX64.base",
-            "Microsoft.VC.14.34.17.4.Prem.Hostx86.Targetx64.Res.base",
-            "Microsoft.VisualCpp.Premium.Tools.HostX86.TargetX86",
-            "Microsoft.VC.14.34.17.4.Premium.Tools.HostX86.TargetX86.base",
-            "Microsoft.VC.14.34.17.4.Prem.HostX86.TargetX86.Res.base",
-            "Microsoft.VisualCpp.Premium.Tools.HostARM64.TargetX86",
-            "Microsoft.VC.14.34.17.4.Premium.Tools.HostARM64.TargetX86.base",
-            "Microsoft.VC.14.34.17.4.Prem.HostARM64.TargetX86.Res.base",
-            "Microsoft.VisualCpp.Premium.Tools.HostARM64.TargetX64",
-            "Microsoft.VC.14.34.17.4.Premium.Tools.HostARM64.TargetX64.base",
-            "Microsoft.VC.14.34.17.4.Prem.HostARM64.Targetx64.Res.base",
-            "Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX86",
-            "Microsoft.VC.14.34.17.4.Premium.Tools.HostX64.TargetX86.base",
-            "Microsoft.VC.14.34.17.4.Prem.HostX64.TargetX86.Res.base",
-            "Microsoft.VisualCpp.Premium.Tools.HostX64.TargetX64",
-            "Microsoft.VC.14.34.17.4.Premium.Tools.HostX64.TargetX64.base",
-            "Microsoft.VC.14.34.17.4.Prem.HostX64.TargetX64.Res.base",
-            "Microsoft.VisualCpp.PGO.X86",
-            "Microsoft.VC.14.34.17.4.PGO.X86.base",
-            "Microsoft.VisualCpp.PGO.X64",
-            "Microsoft.VC.14.34.17.4.PGO.X64.base",
-            "Microsoft.VisualCpp.PGO.Headers",
-            "Microsoft.VC.14.34.17.4.PGO.Headers.base",
-            "Microsoft.VisualCpp.CRT.x86.Store",
-            "Microsoft.VC.14.34.17.4.CRT.x86.Store.base",
-            "Microsoft.VisualCpp.CRT.x86.OneCore.Desktop",
-            "Microsoft.VC.14.34.17.4.CRT.x86.OneCore.Desktop.base",
-            "Microsoft.VisualCpp.CRT.x64.Store",
-            "Microsoft.VC.14.34.17.4.CRT.x64.Store.base",
-            "Microsoft.VisualCpp.CRT.x64.OneCore.Desktop",
-            "Microsoft.VC.14.34.17.4.CRT.x64.OneCore.Desktop.base",
-            "Microsoft.VisualCpp.CRT.Redist.x86.OneCore.Desktop",
-            "Microsoft.VC.14.34.17.4.CRT.Redist.x86.OneCore.Desktop.base",
-            "Microsoft.VisualCpp.CRT.Redist.x64.OneCore.Desktop",
-            "Microsoft.VC.14.34.17.4.CRT.Redist.x64.OneCore.Desktop.base",
-            "Microsoft.VisualStudio.PackageGroup.VC.Tools.x86",
-            "Microsoft.VisualCpp.Tools.Hostx86.Targetx64.Res",
-            "Microsoft.VisualCpp.Tools.HostX86.TargetX64",
-            "Microsoft.VC.14.34.17.4.Tools.HostX86.TargetX64.base",
-            "Microsoft.VC.14.34.17.4.Props.x64",
-            "Microsoft.VC.14.34.17.4.Tools.Hostx86.Targetx64.Res.base",
-            "Microsoft.VisualCpp.Tools.HostX86.TargetX86.Res",
-            "Microsoft.VisualCpp.Tools.HostX86.TargetX86",
-            "Microsoft.VC.14.34.17.4.Tools.HostX86.TargetX86.base",
-            "Microsoft.VC.14.34.17.4.Servicing.Compilers",
-            "Microsoft.VC.14.34.17.4.Props.x86",
-            "Microsoft.VC.14.34.17.4.Props",
-            "Microsoft.VC.14.34.17.4.Tools.HostX86.TargetX86.Res.base",
-            "Microsoft.VisualCpp.Tools.Core.Resources",
-            "Microsoft.VisualCpp.Tools.Core.x86",
-            "Microsoft.VC.14.34.17.4.Tools.Core.Props",
-            "Microsoft.VisualCpp.DIA.SDK",
-            "Microsoft.VisualCpp.Servicing.DIASDK",
-            "Microsoft.VisualCpp.CRT.x86.Desktop",
-            "Microsoft.VC.14.34.17.4.CRT.x86.Desktop.base",
-            "Microsoft.VisualCpp.CRT.x64.Desktop",
-            "Microsoft.VC.14.34.17.4.CRT.x64.Desktop.base",
-            "Microsoft.VisualCpp.CRT.Source",
-            "Microsoft.VC.14.34.17.4.CRT.Source.base",
-            "Microsoft.VisualCpp.CRT.Redist.X86",
-            "Microsoft.VC.14.34.17.4.CRT.Redist.X86.base",
-            "Microsoft.VisualCpp.CRT.Redist.X64",
-            "Microsoft.VisualCpp.CRT.Redist.Resources",
-            "Microsoft.VC.14.34.17.4.CRT.Redist.X64.base",
-            "Microsoft.VisualCpp.CRT.Headers",
-            "Microsoft.VC.14.34.17.4.CRT.Headers.base",
-            "Microsoft.VC.14.34.17.4.Servicing.CrtHeaders",
-            "Microsoft.VC.14.34.17.4.Servicing",
-            "Microsoft.VisualStudio.Component.VC.CoreIde",
-            "Microsoft.VisualStudio.VC.Ide.Pro",
-            "Microsoft.VisualStudio.VC.Ide.Pro.Resources",
-            "Microsoft.VisualStudio.VC.Templates.General",
-            "Microsoft.VisualStudio.VC.Templates.General.Resources",
-            "Microsoft.VisualStudio.VC.Items.Pro",
-            "Microsoft.VisualStudio.PackageGroup.VC.CoreIDE.Reduced",
-            "Microsoft.VisualStudio.VC.Ide.x64",
-            "Microsoft.VisualStudio.PackageGroup.VC.CoreIDE.Express",
-            "Microsoft.VisualStudio.VC.vcvars",
-            "Microsoft.VS.VC.vcvars.x86.Shortcuts",
-            "Microsoft.VS.VC.vcvars.x64.Shortcuts",
-            "Microsoft.VS.VC.vcvars.arm64_x64.Shortcuts",
-            "Microsoft.VisualStudio.VC.MSBuild.v170.X64.v143",
-            "Microsoft.VisualStudio.VC.MSBuild.v170.X64",
-            "Microsoft.VisualStudio.VC.MSBuild.v170.ARM.v143",
-            "Microsoft.VisualStudio.VC.MSBuild.v170.ARM",
-            "Microsoft.VisualStudio.VC.MSBuild.v170.x86.v143",
-            "Microsoft.VisualStudio.VC.MSBuild.v170.X86",
-            "Microsoft.VisualStudio.VC.MSBuild.v170.Base",
-            "Microsoft.VisualStudio.VC.MSBuild.v170.Base.Resources",
-            "Microsoft.VisualStudio.VC.Ide.WinXPlus",
-            "Microsoft.VisualStudio.VC.Ide.Dskx",
-            "Microsoft.VisualStudio.VC.Ide.Dskx.Resources",
-            "Microsoft.VisualStudio.VC.Ide.Base",
-            "Microsoft.VisualStudio.VC.Ide.LanguageService",
-            "Microsoft.VisualStudio.VC.Ide.SecurityIssueAnalysis.Scripts",
-            "Microsoft.VisualStudio.VC.Ide.SecurityIssueAnalysis.PythonDistro",
-            "Microsoft.VisualStudio.VC.Ide.SecurityIssueAnalysis.3rdPartyLibs.10",
-            "Microsoft.VisualStudio.VC.Ide.SecurityIssueAnalysis.3rdPartyLibs.9",
-            "Microsoft.VisualStudio.VC.Ide.SecurityIssueAnalysis.3rdPartyLibs.8",
-            "Microsoft.VisualStudio.VC.Ide.SecurityIssueAnalysis.3rdPartyLibs.7",
-            "Microsoft.VisualStudio.VC.Ide.SecurityIssueAnalysis.3rdPartyLibs.6",
-            "Microsoft.VisualStudio.VC.Ide.SecurityIssueAnalysis.3rdPartyLibs.5",
-            "Microsoft.VisualStudio.VC.Ide.SecurityIssueAnalysis.3rdPartyLibs.4",
-            "Microsoft.VisualStudio.VC.Ide.SecurityIssueAnalysis.3rdPartyLibs.3",
-            "Microsoft.VisualStudio.VC.Ide.SecurityIssueAnalysis.3rdPartyLibs.2",
-            "Microsoft.VisualStudio.VC.Ide.SecurityIssueAnalysis.3rdPartyLibs.1",
-            "Microsoft.VisualStudio.VC.Ide.VCPkgDatabase",
-            "Microsoft.VisualStudio.VC.Ide.Core",
-            "Microsoft.VisualStudio.VC.Ide.ProjectSystem",
-            "Microsoft.VisualStudio.VC.Ide.ProjectSystem.Resources",
-            "Microsoft.VisualStudio.VC.Ide.Core.VCProjectEngine",
-            "Microsoft.VisualStudio.VC.Ide.Core.VCProjectEngine.Resources",
-            "Microsoft.VisualStudio.VC.Ide.LanguageService.Resources",
-            "Microsoft.VisualStudio.VC.Llvm.Base",
-            "Microsoft.VisualStudio.VC.Ide.Base.Resources",
-            "Microsoft.Net.PackageGroup.4.8.1.Redist",
-            "Microsoft.VisualStudio.Component.IntelliCode",
-            "Microsoft.VisualStudio.IntelliCode.CSharp",
-            "Microsoft.VisualStudio.IntelliCode",
-            "Component.Microsoft.VisualStudio.LiveShare.2022",
-            "Microsoft.VisualStudio.Component.Debugger.JustInTime",
-            "Microsoft.VisualStudio.Debugger.ImmersiveActivateHelper.Msi",
-            "Microsoft.VisualStudio.Debugger.JustInTime",
-            "Microsoft.VisualStudio.Debugger.JustInTime.Msi",
-            "Microsoft.VisualStudio.LiveShare.2022",
-            "Microsoft.Icecap.Analysis",
-            "Microsoft.Icecap.Analysis.Resources",
-            "Microsoft.Icecap.Analysis.Resources.Targeted",
-            "Microsoft.Icecap.Collection.Msi",
-            "Microsoft.Icecap.Collection.Msi.Targeted",
-            "Microsoft.Icecap.Collection.Msi.Resources",
-            "Microsoft.Icecap.Collection.Msi.Resources.Targeted",
-            "Microsoft.DiagnosticsHub.Instrumentation",
-            "Microsoft.DiagnosticsHub.Instrumentation.Targeted",
-            "Microsoft.DiagnosticsHub.CpuSampling",
-            "Microsoft.DiagnosticsHub.CpuSampling.Targeted",
-            "Microsoft.PackageGroup.DiagnosticsHub.Platform",
-            "Microsoft.VisualStudio.InstrumentationEngine.ARM64",
-            "Microsoft.VisualStudio.InstrumentationEngine",
-            "Microsoft.DiagnosticsHub.Runtime.ExternalDependencies",
-            "SQLiteCore",
-            "SQLiteCore.Targeted",
-            "Microsoft.DiagnosticsHub.Runtime.ExternalDependencies.Targeted",
-            "Microsoft.DiagnosticsHub.Runtime",
-            "Microsoft.DiagnosticsHub.Runtime.Targeted",
-            "Microsoft.DiagnosticsHub.Collection.ExternalDependencies.arm64",
-            "Microsoft.DiagnosticsHub.Collection",
-            "Microsoft.DiagnosticsHub.Collection.Service",
-            "Microsoft.VisualStudio.VC.Ide.MDD",
-            "Microsoft.VisualStudio.VC.Ide.Linux.ConnectionManager",
-            "Microsoft.VisualStudio.VisualC.Utilities",
-            "Microsoft.VisualStudio.VisualC.Utilities.Resources",
-            "Microsoft.VisualStudio.VC.Ide.Linux.ConnectionManager.Resources",
-            "Microsoft.VisualStudio.VC.Ide.ResourceEditor",
-            "Microsoft.VisualStudio.VC.Ide.ResourceEditor.Resources",
-            "Microsoft.VisualStudio.PackageGroup.TestTools.Core",
-            "Microsoft.VisualStudio.PackageGroup.TestTools.TestPlatform.V2.CLI",
-            "Microsoft.VisualStudio.TestTools.TestPlatform.V2.CLI",
-            "Microsoft.VisualStudio.TestTools.Pex.Common",
-            "Microsoft.VisualStudio.PackageGroup.TestTools.TestPlatform.V1.CLI",
-            "Microsoft.VisualStudio.PackageGroup.TestTools.TestPlatform.Legacy",
-            "Microsoft.VisualStudio.PackageGroup.MinShell.Interop",
-            "Microsoft.VisualStudio.TestTools.TP.Legacy.Tips.Msi",
-            "Microsoft.VisualStudio.TestTools.TP.Legacy.Tips.Common",
-            "Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Tips",
-            "Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Tips.Resources",
-            "Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.TestSettings",
-            "Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Professional",
-            "Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Common",
-            "Microsoft.VisualStudio.TestTools.TP.Legacy.Common.Res",
-            "Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Core",
-            "Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Core.Resources",
-            "Microsoft.VisualStudio.TestTools.TestPlatform.Legacy.Agent",
-            "Microsoft.VisualStudio.PackageGroup.TestTools.TestPlatform.IDE",
-            "Microsoft.VisualStudio.Cache.Service",
-            "Microsoft.VisualStudio.TestTools.TestWIExtension",
-            "Microsoft.VisualStudio.TestTools.TestPlatform.V1.CLI",
-            "Microsoft.VisualStudio.TestTools.TestPlatform.IDE",
-            "Microsoft.VisualStudio.PackageGroup.TestTools.CodeCoverage",
-            "Microsoft.VisualStudio.PackageGroup.TestTools.DataCollectors",
-            "Microsoft.VisualStudio.Component.NuGet",
-            "Microsoft.CredentialProvider",
-            "Microsoft.VisualStudio.NuGet.Licenses",
-            "Microsoft.VisualStudio.Component.TextTemplating",
-            "Microsoft.VisualStudio.TextTemplating.MSBuild",
-            "Microsoft.VisualStudio.TextTemplating.Integration",
-            "Microsoft.VisualStudio.TextTemplating.Core",
-            "Microsoft.VisualStudio.TextTemplating.Integration.Resources",
-            "Microsoft.VisualCpp.CRT.ClickOnce.Msi",
-            "Microsoft.VisualStudio.Component.Roslyn.LanguageServices",
-            "Microsoft.VisualStudio.InteractiveWindow",
-            "Microsoft.DiaSymReader.Native",
-            "Microsoft.VisualCpp.Redist.14",
-            "Microsoft.VisualCpp.Redist.14",
-            "Microsoft.VisualCpp.Servicing.Redist",
-            "Microsoft.VisualStudio.PackageGroup.StaticAnalysis",
-            "Microsoft.VisualStudio.StaticAnalysis.IDE",
-            "Microsoft.VisualStudio.StaticAnalysis.IDE.Resources",
-            "Microsoft.VisualStudio.StaticAnalysis.FxCop.Resources",
-            "Microsoft.VisualStudio.StaticAnalysis.auxil",
-            "Microsoft.VisualStudio.StaticAnalysis.auxil.Resources",
-            "Roslyn.VisualStudio.Setup.ServiceHub",
-            "Microsoft.Component.MSBuild",
-            "Microsoft.NuGet.Build.Tasks.Setup",
-            "Microsoft.VisualStudio.Component.Roslyn.Compiler",
-            "Microsoft.CodeAnalysis.Compilers",
-            "Microsoft.VisualStudio.Component.JavaScript.TypeScript",
-            "Microsoft.VisualStudio.JavaScript.ProjectSystem",
-            "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions",
-            "Microsoft.VisualStudio.ProTools",
-            "sqlsysclrtypes",
-            "SQLCommon",
-            "Microsoft.VisualStudio.ProTools.Resources",
-            "Microsoft.VisualStudio.Web.Scaffolding",
-            "Microsoft.VisualStudio.WebToolsExtensions",
-            "Microsoft.VisualStudio.ConnectedServices.Core",
-            "Microsoft.VisualStudio.WebTools",
-            "Microsoft.VisualStudio.WebToolsExtensions.MSBuild",
-            "Microsoft.VisualStudio.WebTools.Resources",
-            "Microsoft.VisualStudio.WebTools.WSP.FSA",
-            "Microsoft.VisualStudio.WebTools.WSP.FSA.Resources",
-            "Microsoft.VisualStudio.PackageGroup.Debugger.Script",
-            "Microsoft.VisualStudio.Component.TypeScript.TSServer",
-            "Microsoft.VisualStudio.Package.TypeScript.TSServer",
-            "Microsoft.VisualStudio.PackageGroup.JavaScript.Language",
-            "Microsoft.VisualStudio.Package.NodeJs",
-            "TypeScript.Build",
-            "TypeScript.LanguageService",
-            "TypeScript.Tools",
-            "Microsoft.VisualStudio.PackageGroup.Community",
-            "Microsoft.VisualStudio.Community.VB.x86",
-            "Microsoft.VisualStudio.Community.VB.x64",
-            "Microsoft.VisualStudio.PackageGroup.Core",
-            "Microsoft.VisualStudio.CodeSense.Community",
-            "Microsoft.VisualStudio.TestTools.TeamFoundationClient",
-            "Microsoft.VisualStudio.PackageGroup.Debugger.Core",
-            "Microsoft.VisualStudio.Debugger.BrokeredServices",
-            "Microsoft.VisualStudio.Debugger.VSCodeDebuggerHost",
-            "Microsoft.VisualStudio.Debugger.AzureAttach",
-            "Microsoft.VisualStudio.Web.Azure.Common",
-            "Microsoft.WebTools.Shared",
-            "Microsoft.WebTools.DotNet.Core.ItemTemplates",
-            "Microsoft.VisualStudio.PackageGroup.Debugger.TimeTravel.Replay",
-            "Microsoft.VisualStudio.VC.Ide.Debugger",
-            "Microsoft.VisualStudio.VC.Ide.Debugger.Concord",
-            "Microsoft.VisualStudio.VC.Ide.Debugger.Concord.Resources",
-            "Microsoft.VisualStudio.VC.Ide.Debugger.Resources",
-            "Microsoft.VisualStudio.VC.Ide.Common",
-            "Microsoft.VisualStudio.VC.Ide.Common.Resources",
-            "Microsoft.VisualStudio.Debugger.CollectionAgents",
-            "Microsoft.VisualStudio.Debugger.Parallel",
-            "Microsoft.VisualStudio.Debugger.Parallel.Resources",
-            "Microsoft.VisualStudio.Debugger.Managed",
-            "Microsoft.CodeAnalysis.ExpressionEvaluator",
-            "Microsoft.CodeAnalysis.VisualStudio.Setup",
-            "Microsoft.VisualStudio.Debugger.Concord.Managed",
-            "Microsoft.VisualStudio.Debugger.Concord.Managed.Resources",
-            "Microsoft.VisualStudio.Debugger.Managed.Resources",
-            "Microsoft.VisualStudio.Debugger.TargetComposition",
-            "Microsoft.VisualStudio.Debugger.TargetComposition.Remote.arm64",
-            "Microsoft.VisualStudio.Debugger.TargetComposition.Remote",
-            "Microsoft.VisualStudio.Debugger.TargetComposition.Remote",
-            "Microsoft.VisualStudio.Debugger.Remote",
-            "Microsoft.VisualStudio.Debugger.Concord.Remote",
-            "Microsoft.VisualStudio.Debugger.Concord.Remote.Resources",
-            "Microsoft.VisualStudio.Debugger.Remote",
-            "Microsoft.VisualStudio.Debugger.Remote.ARM64",
-            "Microsoft.VisualStudio.Debugger.Concord.Remote.ARM64",
-            "Microsoft.VisualStudio.Debugger.Concord.Remote.Resources.ARM64",
-            "Microsoft.VisualStudio.Debugger.Remote.ARM",
-            "Microsoft.VisualStudio.Debugger.Concord.Remote.ARM",
-            "Microsoft.VisualStudio.Debugger.Concord.Remote.Resources.ARM",
-            "Microsoft.VisualStudio.Debugger.Remote.Resources.ARM",
-            "Microsoft.VisualStudio.Debugger.Remote.Resources.ARM64",
-            "Microsoft.VisualStudio.Debugger.Concord.Remote",
-            "Microsoft.VisualStudio.Debugger.Concord.Remote.Resources",
-            "Microsoft.VisualStudio.Debugger.Remote.Resources",
-            "Microsoft.VisualStudio.Debugger.Remote.Resources",
-            "Microsoft.VisualStudio.Debugger",
-            "Microsoft.VisualStudio.VC.MSVCDis",
-            "Microsoft.IntelliTrace.DiagnosticsHub",
-            "Microsoft.VisualStudio.Debugger.Concord",
-            "Microsoft.VisualStudio.Debugger.Concord.Resources",
-            "Microsoft.VisualStudio.Debugger.Resources",
-            "Microsoft.VisualStudio.Debugger.Package.DiagHub.Client",
-            "Microsoft.VisualStudio.Debugger.Remote.DiagnosticsHub.Client",
-            "Microsoft.VisualStudio.Debugger.Remote.DiagnosticsHub.Client",
-            "Microsoft.VisualStudio.Debugger.Remote.DiagnosticsHub.Client",
-            "Microsoft.PackageGroup.ClientDiagnostics",
-            "Microsoft.VisualStudio.AppResponsiveness",
-            "Microsoft.VisualStudio.AppResponsiveness.Targeted",
-            "Microsoft.VisualStudio.AppResponsiveness.Resources",
-            "Microsoft.VisualStudio.ClientDiagnostics",
-            "Microsoft.VisualStudio.ClientDiagnostics.Targeted",
-            "Microsoft.VisualStudio.ClientDiagnostics.Resources",
-            "Microsoft.VisualStudio.PackageGroup.CommunityCore",
-            "Microsoft.VisualStudio.ProjectSystem.Full",
-            "Microsoft.VisualStudio.LiveShareApi",
-            "Microsoft.VisualStudio.ProjectSystem.Query",
-            "Microsoft.VisualStudio.ProjectSystem",
-            "Microsoft.VisualStudio.Community.x86",
-            "Microsoft.VisualStudio.Community.x64",
-            "Microsoft.VisualStudio.Community.Msi.Resources",
-            "Microsoft.VisualStudio.Community.Msi",
-            "Microsoft.VisualStudio.Community.Shared.Msi",
-            "Microsoft.VisualStudio.Devenv.Msi",
-            "Microsoft.VisualStudio.Devenv.Shared.Msi",
-            "Microsoft.VisualStudio.MinShell.Interop.Msi",
-            "Microsoft.VisualStudio.MinShell.Interop.Shared.Msi",
-            "Microsoft.VisualStudio.Editors",
-            "Microsoft.VisualStudio.Workload.CoreEditor",
-            "Microsoft.VisualStudio.Component.CoreEditor",
-            "Microsoft.VisualStudio.PackageGroup.CoreEditor",
-            "Microsoft.WebView2",
-            "Microsoft.VisualStudio.ScriptedHost",
-            "Microsoft.VisualStudio.ScriptedHost.Targeted",
-            "Microsoft.VisualCpp.Tools.Common.UtilsPrereq",
-            "Microsoft.VisualCpp.Tools.Common.Utils",
-            "Microsoft.VisualCpp.Tools.Common.Utils.Resources",
-            "Microsoft.VisualStudio.PackageGroup.VsDevCmd",
-            "Microsoft.VisualStudio.VsDevCmd.Ext.NetFxSdk",
-            "Microsoft.VisualStudio.VsDevCmd.Core.WinSdk",
-            "Microsoft.VisualStudio.VsDevCmd.Core.DotNet",
-            "Microsoft.VisualStudio.VC.DevCmd",
-            "Microsoft.VisualStudio.VC.DevCmd.Resources",
-            "Microsoft.VisualStudio.VirtualTree",
-            "Microsoft.DiaSymReader",
-            "Microsoft.Build.Dependencies",
-            "Microsoft.Build.FileTracker.Msi",
-            "Microsoft.Build",
-            "Microsoft.VisualStudio.PackageGroup.NuGet",
-            "Microsoft.DataAI.NuGetRecommender",
-            "Microsoft.VisualStudio.NuGet.Core",
-            "Microsoft.Build.Arm64",
-            "Microsoft.Build.UnGAC",
-            "Microsoft.VisualStudio.TextMateGrammars",
-            "Microsoft.VisualStudio.Platform.Markdown",
-            "Microsoft.VisualStudio.Platform.CrossRepositorySearch",
-            "Microsoft.VisualStudio.PackageGroup.TeamExplorer.Common",
-            "Microsoft.VisualStudio.TeamExplorer",
-            "Microsoft.VisualStudio.PackageGroup.ServiceHub",
-            "Microsoft.ServiceHub.Node",
-            "Microsoft.ServiceHub.Managed",
-            "Microsoft.ServiceHub.arm64",
-            "Microsoft.VisualStudio.ProjectServices",
-            "Microsoft.VisualStudio.OpenFolder.VSIX",
-            "Microsoft.VisualStudio.FileHandler.Msi",
-            "Microsoft.VisualStudio.FileHandler.Msi",
-            "Microsoft.VisualStudio.PackageGroup.MinShell",
-            "Microsoft.VisualStudio.MinShell.Msi",
-            "Microsoft.VisualStudio.MinShell.Shared.Msi",
-            "Microsoft.VisualStudio.MinShell.Msi.Resources",
-            "Microsoft.VisualStudio.MinShell.Interop",
-            "CoreEditorFonts",
-            "Microsoft.VisualStudio.Log",
-            "Microsoft.VisualStudio.Log.Targeted",
-            "Microsoft.VisualStudio.Log.Resources",
-            "Microsoft.VisualStudio.Finalizer",
-            "Microsoft.VisualStudio.Devenv",
-            "Microsoft.VisualStudio.Devenv.Resources",
-            "Microsoft.VisualStudio.CoreEditor",
-            "Microsoft.VisualStudio.Navigation.RichCodeNav",
-            "Microsoft.VisualStudio.Platform.NavigateTo",
-            "Microsoft.VisualStudio.Connected",
-            "SQLitePCLRaw",
-            "SQLitePCLRaw.Targeted",
-            "Microsoft.VisualStudio.Connected.Auto",
-            "Microsoft.VisualStudio.Connected.Auto.Resources",
-            "Microsoft.VisualStudio.AzureSDK",
-            "Microsoft.VisualStudio.PerfLib",
-            "Microsoft.VisualStudio.Connected.Resources",
-            "Microsoft.Net.PackageGroup.4.8.Redist",
-            "Microsoft.VisualStudio.PackageGroup.Progression",
-            "Microsoft.VisualStudio.PerformanceProvider",
-            "Microsoft.VisualStudio.GraphModel",
-            "Microsoft.VisualStudio.GraphProvider",
-            "Microsoft.VisualStudio.Community.VB.Targeted",
-            "Microsoft.VisualStudio.Community.VB.Neutral",
-            "Microsoft.VisualStudio.Community.CSharp.Targeted",
-            "Microsoft.VisualStudio.Community.CSharp.Neutral",
-            "Microsoft.VisualStudio.Community.ProductArch.TargetedExtra",
-            "Microsoft.VisualStudio.Community.ProductArch.Targeted",
-            "Microsoft.VisualStudio.Community.ProductArch.NeutralExtra",
-            "Microsoft.DiaSymReader.PortablePdb",
-            "Microsoft.IntelliTrace.CollectorCab",
-            "Microsoft.VisualStudio.Community.VB.Resources.Targeted",
-            "Microsoft.VisualStudio.Community.VB.Resources.Neutral",
-            "Microsoft.VisualStudio.Community.CSharp.Resources.Targeted",
-            "Microsoft.VisualStudio.Community.CSharp.Resources.Neutral",
-            "Microsoft.VisualStudio.Community.ProductArch.Resources.Targeted",
-            "Microsoft.VisualStudio.Community.ProductArch.Resources.NeutralExtra",
-            "Microsoft.VisualStudio.Net.Eula.Resources",
-            "Microsoft.VisualStudio.Community.ProductArch.Resources.Neutral",
-            "Microsoft.VisualStudio.WebSiteProject.DTE",
-            "Microsoft.VisualStudio.Diagnostics.AspNetHelper",
-            "Microsoft.VisualStudio.Diagnostics.AspNetHelper.Standard",
-            "Microsoft.MSHtml",
-            "Microsoft.VisualStudio.Platform.CallHierarchy",
-            "Microsoft.VisualStudio.Community.ProductArch.Neutral",
-            "Microsoft.VisualStudio.MinShell",
-            "Microsoft.VisualStudio.VsWebProtocolSelector.Msi",
-            "Microsoft.Net.6.WindowsDesktop.Runtime",
-            "Microsoft.Net.6.Runtime",
-            "Microsoft.VisualStudio.PackageGroup.Setup.Common",
-            "Microsoft.VisualStudio.Setup.WMIProvider",
-            "Microsoft.VisualStudio.Setup.Configuration.Interop",
-            "Microsoft.VisualStudio.Setup.Configuration",
-            "Microsoft.VisualStudio.Extensibility.Container",
-            "Microsoft.VisualStudio.LanguageServer",
-            "Microsoft.VisualStudio.Platform.Terminal",
-            "Microsoft.VisualStudio.MefHosting",
-            "Microsoft.VisualStudio.Initializer",
-            "Microsoft.VisualStudio.ExtensionManager",
-            "Microsoft.VisualStudio.Platform.Editor",
-            "Microsoft.VisualStudio.MinShell.Targeted",
-            "Microsoft.VisualStudio.NativeImageSupport",
-            "Microsoft.VisualStudio.Devenv.Config",
-            "Microsoft.VisualStudio.MinShell.Resources.arm64",
-            "Microsoft.VisualStudio.MinShell.Auto",
-            "Microsoft.VisualStudio.MinShell.Auto.Resources",
-            "Microsoft.VisualStudio.Branding.Community"
-        ]
-    }
-]
diff --git a/deps/npm/node_modules/node-gyp/test/fixtures/certs.js b/deps/npm/node_modules/node-gyp/test/fixtures/certs.js
deleted file mode 100644
index 766e54b5ed3900..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/fixtures/certs.js
+++ /dev/null
@@ -1,150 +0,0 @@
-module.exports['ca.key'] = `
------BEGIN RSA PRIVATE KEY-----
-MIIEowIBAAKCAQEAtTbG0k2UFUyCdZuip0TTEtXRHh57qosegrpHPBreSNTxt7OT
-KfOUZp2rToTHeN9w0ZbV2eKRI5AuFx8Cmlm73/KIHKzSNTBATGMeeHnGaxvL/W/s
-KJdTDRNf7/qCXHQ+gsuEWWCFzOZuHmmAQa2IBX2HAQTqXJI8+2iJ9gytFfJLxjqy
-6O4u9ugZVHSyQJWs49tGRcWMlNm7EMStADFvJn3S11xe/kwIA2mSI/eddDnzL0Mx
-AkR9dQBL66xOABLL5v3QQdhipfHluX6HLbDd/1YsFTuOpgvLRlr72rTAFrQZCokV
-hXPiqstn5zJFW5arHakvMR0+OPaICF5feh/4qQIDAQABAoIBAHWg6exnWUF+GY0Y
-CrwDS/QFASpI5UNt7M809bqJQlMKjyEMmvF3YJQ/soxUWlsWx1f1TjmR/V6VX6W4
-hmsE5pRXDY13jTfja0lqacQQYAD02TRY63XpzIpHUlYnSWmUN2OVkgKmShQYW9C3
-8P4xE4Nk2TaLJ0oRzy3uzOb/kXcVaJfknBRUnOhuaTSs+w4l4pPXueYA7xuHgVsL
-Qq0S4kK+PmdwCMB7gzlAAQhCM3vQ1U4cjC9JIIKSmPy7BcvD0kBfVPIFQ2byGpA1
-VkWBLSyeig0YxA5oIshK5cLiDIfBIiCSEzm4AMhVhGf0tbGEwiPljxKjbarYUUIi
-ATMk83UCgYEA7kKeOveuPbMqxmT42swfa9OU5jLUjH+VExU0Kv3BbEjv/OGt0fac
-/cs1Ze3vnrtCHudVajocFjydb8B4c62DbA4/T+LcUw/HaMaORbOoICQidi/zZ1Lj
-gjg8Ip2WKXEhSAwqUpaFd6w16NZOxiTh+NDaRKywwbe8j57eDH4uR6MCgYEAwrTS
-q5ra6+WDGUFMs0y3GMbL8j14PGhxBQBYSTM//NysI+EM6eeKn1cV3BbphEw//jgE
-0pVokkjvLAQWWEG2dZyRxRE3YAMgOAIPx5zbJCim3iBVuoqY9ckLg2jF8Fqqubsb
-3Rf2/Xzn/rFqsXdhsjGcJpdN66T9aEjwEkAnc0MCgYA5cOYk4UGormFJo147oaqR
-nFjxhp+nn7qY9yu0kajoKk1xchct337J0Qv2nv5+DjdKrArzqT7MPaDXKFfhy5s7
-mdO5tr/XZp50rCnws/d8iDmmtLjB2EHxSw10avmg1B1p+UTa1F8pEuOMVt529r1j
-9zYoCFo02c8j8PEnoeQWcQKBgQCVBCuQZu5SSM/zTkTTnU0sy0lf1qflI9IMD92B
-+JVqg8HDnAR0KF+x38a9MVP7ixgXCuy19t+XxfY269HmLjTlArWV671D4GCSPRGy
-plwZ6nr72ieCo3y57+q94jxL3jh3+bozlpnUG/q6tTKBLGs7JDjsWDSsuxOu8tO6
-RBttXQKBgB6LQFOTjDMfsFHKsnQXFUZId3GG/iLg3WCWxEo88T5Rq3JIR0zDpW8H
-cKhl/sPY+JVHsxizNCMPtp7Hn7GrB6D/v9LbO0jpG2U0BFiJ6zhiDopbP9B0EAW4
-5JJ+JGKRKoCxs3DmSVyns0gU4j4rVte97UWyVy5TZ8Acr/qrgOA1
------END RSA PRIVATE KEY-----
-`
-
-module.exports['ca.crt'] = `
------BEGIN CERTIFICATE-----
-MIIDmzCCAoOgAwIBAgIUDA0GrvcnG41XT6LYFeNwvq8YV1UwDQYJKoZIhvcNAQEL
-BQAwXTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRAwDgYDVQQKDAdOb2RlLmpz
-MREwDwYDVQQLDAhub2RlLWd5cDEcMBoGA1UEAwwTbm9kZS1neXAubm9kZWpzLm9y
-ZzAeFw0yMjA1MTEwNDIyMjRaFw00OTA5MjUwNDIyMjRaMF0xCzAJBgNVBAYTAlVT
-MQswCQYDVQQIDAJDQTEQMA4GA1UECgwHTm9kZS5qczERMA8GA1UECwwIbm9kZS1n
-eXAxHDAaBgNVBAMME25vZGUtZ3lwLm5vZGVqcy5vcmcwggEiMA0GCSqGSIb3DQEB
-AQUAA4IBDwAwggEKAoIBAQC1NsbSTZQVTIJ1m6KnRNMS1dEeHnuqix6Cukc8Gt5I
-1PG3s5Mp85RmnatOhMd433DRltXZ4pEjkC4XHwKaWbvf8ogcrNI1MEBMYx54ecZr
-G8v9b+wol1MNE1/v+oJcdD6Cy4RZYIXM5m4eaYBBrYgFfYcBBOpckjz7aIn2DK0V
-8kvGOrLo7i726BlUdLJAlazj20ZFxYyU2bsQxK0AMW8mfdLXXF7+TAgDaZIj9510
-OfMvQzECRH11AEvrrE4AEsvm/dBB2GKl8eW5foctsN3/ViwVO46mC8tGWvvatMAW
-tBkKiRWFc+Kqy2fnMkVblqsdqS8xHT449ogIXl96H/ipAgMBAAGjUzBRMB0GA1Ud
-DgQWBBT6LcYYABEOAMv4hI/5bC82rGlD/DAfBgNVHSMEGDAWgBT6LcYYABEOAMv4
-hI/5bC82rGlD/DAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQA9
-D+qoKw0njub+NaFRS2DFbSiKb5JKTxVjU5aNusFONFLSXBuRpnYyjjkXpJy8JMWz
-g8GFDEPP6kiSb8xaPNrFcUzb4PFzJabNTuaLJpBpd2gNBj5AeYwwpRa2DPv/b4yw
-y2mfULuCWS09ZAguI2OcaARlAsFxYN0IuQ6pN1AvGFGee67ve9l2VF/hhwEi4lCk
-MM0CWlP6COJ8TX7X0MTtexVOgo9m3hBuTSYEZClYFIdSOk10xkPl8Y3Iz/x6mzfK
-Uu2l2ZtYvSdAX1CQMds3ZWt0ChNNEjOKPv4g2QSDhGkiqrmi4wUS81g68wKqOpqn
-GbN8uKxIfyMjqZKaujPR
------END CERTIFICATE-----
-`
-
-module.exports['server.key'] = `
------BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEAvPM99BkYrBcTM355dhz4XzhSDRGxa9qttUlBSgEsbu2UjsRm
-XjDS+60XXd66tWpPwLeUd2uvlC/ltv5ekv+EBu35j1KfA1+K1rtFzb1i40kMCsns
-OoXjgpsN2wvkxMdFkT2bkqKCS6X0xzlWea1t4poKh9iG7n3otk4RzPNawfwQ9W5n
-o9/8i6AUwDbuK4dhAId/Inw2aKrMyQ+AiSvsDM2wUMq+pV7nP46f7MhR4xiGz14z
-ATFdjM3Oo/1NKrr0WgVM6i0eNAtuIDqIs8YE7SfODe/SzpJySxewutfYi62OaLh/
-hmWByj/pF5SoNMLyJHxn4GyKK+Qle9NJAThLiwIDAQABAoIBAQCZs4h/Cvct7etZ
-pRUqxnAoDQl5xh28LXvGj1uD1qaNacfBxvO6xR6rSedLHcZlkqBjlTI5XqjJ85h6
-njrSevWsKWMrejsNpGetO1OSA+/wEVixYgY+qPEkKftAZ1Fl3O+zMRlfU8CHxuzy
-Lqsweap8fW/5h2JjmJp3ydPjE0aNqpQ+0LtYBBawKDIe2zPNOmTPwz3D8qJNQJKU
-Qdj08dO/vPZncllPagGvpqhfv4hMyNChr71eBbEFsi3O5VJxfZyj+fQG0DGocr/y
-sV54HtYk5j06wMxZFLQtaJn+1pOXquZMNwodSPnbrR/+CI1SZeB8N6VyqqOdmrDz
-5NbfGJiRAoGBAPrCuQxJwgc2MzpEtrXA4+1uuV8QWGy3+wNKxKw4lgyC7peXXrVK
-l9FkOOAPr8puPRABgDS9t6vo59BAP3Wrx0oJ9PA/Qn03WYLfJMepWqlK7ni9kS04
-5owRTduK7P190sp0m6iicsnchGSSOchECwB5UmtHysEFiuY0T+0pdNbjAoGBAMDl
-57lwZDfNTGGDxLQYVzbrXgKcD60DW9MhvH3uso6cw5NYs3tmENCh9D6YrCNN4PmL
-zdp4dKbOFoGJdy22TK31nrezUuNKSK+QKH2gsmNVI+a5QokNO1Cfk+PMLoOR5du2
-nwyVvzdaBwuXU4fhmwvLv/SCFNEJ0EgUILeMETE5AoGBAIwLXf9v3e3bJkb/gy8E
-mAbNVLez0D5/ja9r/WTVgW9hXFDLF/iVvS4TE/SGrj2WzYF35RsPbVmUDIrwpsBX
-/EfsQaA/JCn8VIBTkR31Bg4QLBjAfijMY22MaHgZIXv83lF1SE2o1ATKpCHqzFx9
-K8vK9e22PZUJPGaOhqjEA13TAoGAEPipSJFw38/6NmInfkjd84EFxmkAoBI5k/vV
-36aOoyl7s40MTYEPXavCF3fLPVfuwUXhmKUcbkiXhlIX4De3y15e1n66fjDc8EVY
-qqTmzQKCpBwMlI5Ld65yjoo6VW0SsiABIlRSfIY5NHXd7YiV4ZXNj6+aMUIRxyWu
-Mzfpk1ECgYBZw8lML+F8XbcmCLGYuicf0V/wgFaJr8nnPeW7AiQrv13Ju1ItEaC8
-Tz8F7OfC+FoUb0MGjXHKquDVBDs4xSuS+Ol+rlZEK68ALpm8sUgp6YjARYiXlprs
-6o4kN0P5F+DVU2SP6fo9zKLCxaTH9VAQ9C3VUViGAFLBt4DVDmj77g==
------END RSA PRIVATE KEY-----
-`
-
-module.exports['server.crt'] = `
------BEGIN CERTIFICATE-----
-MIIDNzCCAh8CFBg1Ph5t5rBlAbCrEn/PexNy9WunMA0GCSqGSIb3DQEBCwUAMF0x
-CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEQMA4GA1UECgwHTm9kZS5qczERMA8G
-A1UECwwIbm9kZS1neXAxHDAaBgNVBAMME25vZGUtZ3lwLm5vZGVqcy5vcmcwHhcN
-MjIwNTExMDQyMjI0WhcNMjMwOTIzMDQyMjI0WjBTMQswCQYDVQQGEwJVUzELMAkG
-A1UECAwCQ0ExEDAOBgNVBAoMB05vZGUuanMxETAPBgNVBAsMCG5vZGUtZ3lwMRIw
-EAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
-AQC88z30GRisFxMzfnl2HPhfOFINEbFr2q21SUFKASxu7ZSOxGZeMNL7rRdd3rq1
-ak/At5R3a6+UL+W2/l6S/4QG7fmPUp8DX4rWu0XNvWLjSQwKyew6heOCmw3bC+TE
-x0WRPZuSooJLpfTHOVZ5rW3imgqH2Ibufei2ThHM81rB/BD1bmej3/yLoBTANu4r
-h2EAh38ifDZoqszJD4CJK+wMzbBQyr6lXuc/jp/syFHjGIbPXjMBMV2Mzc6j/U0q
-uvRaBUzqLR40C24gOoizxgTtJ84N79LOknJLF7C619iLrY5ouH+GZYHKP+kXlKg0
-wvIkfGfgbIor5CV700kBOEuLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAEhaNEye
-JsE4eG1xaGmHq7w9eV0neOaZ58XCuF1sSEMIy9uMnl3aOdctxh/1SYkqJyMct79q
-Ra2UZ6mauRlOeqdHb+HZKrFYYUOtd1HOWWJ44Gaya2EQMiTbd/Ns9Th2KTbTOCbL
-CHFNska9Ty2ioT7VcrVuIEXFPMua5T4lnCkNJQla800pHHOak2baN/c66Io+8XI2
-xiqaVrLT3qvpzdiiEjo4POeRnWMIgJJshy77Am5JlhaJiAqP1AHfh/tYpliGkjXF
-8DSgSoLHSQfalJ4VQvP4XLc/XnmF5Zt6bvwUxCllEBFRneU74bW7/euYX/TpYobr
-Y+YM7fGiCqwHdUs=
------END CERTIFICATE-----
-`
-
-module.exports['ca-bundle.crt'] = `
------BEGIN CERTIFICATE-----
-MIIDJjCCAg4CAhnOMA0GCSqGSIb3DQEBBQUAMH0xCzAJBgNVBAYTAlVTMQswCQYD
-VQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEZMBcGA1UECgwQU3Ryb25n
-TG9vcCwgSW5jLjESMBAGA1UECwwJU3Ryb25nT3BzMRowGAYDVQQDDBFjYS5zdHJv
-bmdsb29wLmNvbTAeFw0xNTEyMDgyMzM1MzNaFw00MzA0MjQyMzM1MzNaMBkxFzAV
-BgNVBAMMDnN0cm9uZ2xvb3AuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEAwOYI7OZ2FX/YjRgLZoDQlbPc5UZXU/j0e1wwiJNPtPEax9Y5Uoza0Pnt
-Ikzkc2SfvQ+IJrhXo385tI0W5juuqbHnE7UrjUuPjUX6NHevkxcs/flmjan5wnZM
-cPsGhH71WDuUEEflvZihf2Se2x+xgZtMhc5XGmVmRuZFYKvkgUhA2/w8/QrK+jPT
-n9QRJxZjWNh2RBdC1B7u4jffSmOSUljYFH1I2eTeY+Rdi6YUIYSU9gEoZxsv3Tia
-SomfMF5jt2Mouo6MzA+IhLvvFjcrcph1Qxgi9RkfdCMMd+Ipm9YWELkyG1bDRpQy
-0iyHD4gvVsAqz1Y2KdRSdc3Kt+nTqwIDAQABoxkwFzAVBgNVHREEDjAMhwQAAAAA
-hwR/AAABMA0GCSqGSIb3DQEBBQUAA4IBAQAhy4J0hML3NgmDRHdL5/iTucBe22Mf
-jJjg2aifD1S187dHm+Il4qZNO2plWwAhN0h704f+8wpsaALxUvBIu6nvlvcMP5PH
-jGN5JLe2Km3UaPvYOQU2SgacLilu+uBcIo2JSHLV6O7ziqUj5Gior6YxDLCtEZie
-Ea8aX5/YjuACtEMJ1JjRqjgkM66XAoUe0E8onOK3FgTIO3tGoTJwRp0zS50pFuP0
-PsZtT04ck6mmXEXXknNoAyBCvPypfms9OHqcUIW9fiQnrGbS/Ri4QSQYj0DtFk/1
-na4fY1gf3zTHxH8259b/TOOaPfTnCEsOQtjUrWNR4xhmVZ+HJy4yytUW
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDbzCCAlcCAmm6MA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNVBAYTAlVTMQswCQYD
-VQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEZMBcGA1UECgwQU3Ryb25n
-TG9vcCwgSW5jLjESMBAGA1UECwwJU3Ryb25nT3BzMRowGAYDVQQDDBFjYS5zdHJv
-bmdsb29wLmNvbTAeFw0xNTEyMDgyMzM1MzNaFw00MzA0MjQyMzM1MzNaMH0xCzAJ
-BgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEZ
-MBcGA1UECgwQU3Ryb25nTG9vcCwgSW5jLjESMBAGA1UECwwJU3Ryb25nT3BzMRow
-GAYDVQQDDBFjYS5zdHJvbmdsb29wLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP
-ADCCAQoCggEBANfj86jkvvYDjHBgiqWhk9Cj+bqiMq3MqnV0CBO4iuK33Fo6XssE
-H+yVdXlIBFbFe6t655MdBVOR2Sfj7WqNh96vhu6PyDHiwcQlTaiLU6nhIed1J4Wv
-lvnJHFmp8Wbtx5AgLT4UYu03ftvXEl2DLi3vhSL2tRM1ebXHB/KPbRWkb25DPX0P
-foOHot3f2dgNe2x6kponf7E/QDmAu3s7Nlkfh+ryDhgGU7wocXEhXbprNqRqOGNo
-xbXgUI+/9XDxYT/7Gn5LF/fPjtN+aB0SKMnTsDhprVlZie83mlqJ46fOOrR+vrsQ
-mi/1m/TadrARtZoIExC/cQRdVM05EK4tUa8CAwEAATANBgkqhkiG9w0BAQsFAAOC
-AQEAQ7k5WhyhDTIGYCNzRnrMHWSzGqa1y4tJMW06wafJNRqTm1cthq1ibc6Hfq5a
-K10K0qMcgauRTfQ1MWrVCTW/KnJ1vkhiTOH+RvxapGn84gSaRmV6KZen0+gMsgae
-KEGe/3Hn+PmDVV+PTamHgPACfpTww38WHIe/7Ce9gHfG7MZ8cKHNZhDy0IAYPln+
-YRwMLd7JNQffHAbWb2CE1mcea4H/12U8JZW5tHCF6y9V+7IuDzqwIrLKcW3lG17n
-VUG6ODF/Ryqn3V5X+TL91YyXi6c34y34IpC7MQDV/67U7+5Bp5CfeDPWW2wVSrW+
-uGZtfEvhbNm6m2i4UNmpCXxUZQ==
------END CERTIFICATE-----
-`
diff --git a/deps/npm/node_modules/node-gyp/test/fixtures/nodedir/include/node/config.gypi b/deps/npm/node_modules/node-gyp/test/fixtures/nodedir/include/node/config.gypi
deleted file mode 100644
index e767534082f8ce..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/fixtures/nodedir/include/node/config.gypi
+++ /dev/null
@@ -1,6 +0,0 @@
-# Test configuration
-{
-  'variables': {
-    'build_with_electron': true
-  }
-}
diff --git a/deps/npm/node_modules/node-gyp/test/fixtures/test-charmap.py b/deps/npm/node_modules/node-gyp/test/fixtures/test-charmap.py
deleted file mode 100644
index 63aa77bb482ef2..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/fixtures/test-charmap.py
+++ /dev/null
@@ -1,31 +0,0 @@
-import sys
-import locale
-
-try:
-    reload(sys)
-except NameError:  # Python 3
-    pass
-
-
-def main():
-    encoding = locale.getdefaultlocale()[1]
-    if not encoding:
-        return False
-
-    try:
-        sys.setdefaultencoding(encoding)
-    except AttributeError:  # Python 3
-        pass
-
-    textmap = {
-        "cp936": "\u4e2d\u6587",
-        "cp1252": "Lat\u012Bna",
-        "cp932": "\u306b\u307b\u3093\u3054",
-    }
-    if encoding in textmap:
-        print(textmap[encoding])
-    return True
-
-
-if __name__ == "__main__":
-    print(main())
diff --git a/deps/npm/node_modules/node-gyp/test/process-exec-sync.js b/deps/npm/node_modules/node-gyp/test/process-exec-sync.js
deleted file mode 100644
index 21763bc26de108..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/process-exec-sync.js
+++ /dev/null
@@ -1,140 +0,0 @@
-'use strict'
-
-const fs = require('graceful-fs')
-const childProcess = require('child_process')
-
-function startsWith (str, search, pos) {
-  if (String.prototype.startsWith) {
-    return str.startsWith(search, pos)
-  }
-
-  return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search
-}
-
-function processExecSync (file, args, options) {
-  var child, error, timeout, tmpdir, command
-  command = makeCommand(file, args)
-
-  /*
-    this function emulates child_process.execSync for legacy node <= 0.10.x
-    derived from https://github.com/gvarsanyi/sync-exec/blob/master/js/sync-exec.js
-  */
-
-  options = options || {}
-  // init timeout
-  timeout = Date.now() + options.timeout
-  // init tmpdir
-  var osTempBase = '/tmp'
-  var os = determineOS()
-  osTempBase = '/tmp'
-
-  if (process.env.TMP) {
-    osTempBase = process.env.TMP
-  }
-
-  if (osTempBase[osTempBase.length - 1] !== '/') {
-    osTempBase += '/'
-  }
-
-  tmpdir = osTempBase + 'processExecSync.' + Date.now() + Math.random()
-  fs.mkdirSync(tmpdir)
-
-  // init command
-  if (os === 'linux') {
-    command = '(' + command + ' > ' + tmpdir + '/stdout 2> ' + tmpdir +
-      '/stderr); echo $? > ' + tmpdir + '/status'
-  } else {
-    command = '(' + command + ' > ' + tmpdir + '/stdout 2> ' + tmpdir +
-      '/stderr) | echo %errorlevel% > ' + tmpdir + '/status | exit'
-  }
-
-  // init child
-  child = childProcess.exec(command, options)
-
-  var maxTry = 100000 // increases the test time by 6 seconds on win-2016-node-0.10
-  var tryCount = 0
-  while (tryCount < maxTry) {
-    try {
-      var x = fs.readFileSync(tmpdir + '/status')
-      if (x.toString() === '0') {
-        break
-      }
-    } catch (ignore) {}
-    tryCount++
-    if (Date.now() > timeout) {
-      error = child
-      break
-    }
-  }
-
-  ['stdout', 'stderr', 'status'].forEach(function (file) {
-    child[file] = fs.readFileSync(tmpdir + '/' + file, options.encoding)
-    setTimeout(unlinkFile, 500, tmpdir + '/' + file)
-  })
-
-  child.status = Number(child.status)
-  if (child.status !== 0) {
-    error = child
-  }
-
-  try {
-    fs.rmdirSync(tmpdir)
-  } catch (ignore) {}
-  if (error) {
-    throw error
-  }
-  return child.stdout
-}
-
-function makeCommand (file, args) {
-  var command, quote
-  command = file
-  if (args.length > 0) {
-    for (var i in args) {
-      command = command + ' '
-      if (args[i][0] === '-') {
-        command = command + args[i]
-      } else {
-        if (!quote) {
-          command = command + '"'
-          quote = true
-        }
-        command = command + args[i]
-        if (quote) {
-          if (args.length === (parseInt(i) + 1)) {
-            command = command + '"'
-          }
-        }
-      }
-    }
-  }
-  return command
-}
-
-function determineOS () {
-  var os = ''
-  var tmpVar = ''
-  if (process.env.OSTYPE) {
-    tmpVar = process.env.OSTYPE
-  } else if (process.env.OS) {
-    tmpVar = process.env.OS
-  } else {
-    // default is linux
-    tmpVar = 'linux'
-  }
-
-  if (startsWith(tmpVar, 'linux')) {
-    os = 'linux'
-  }
-  if (startsWith(tmpVar, 'win')) {
-    os = 'win'
-  }
-
-  return os
-}
-
-function unlinkFile (file) {
-  fs.unlinkSync(file)
-}
-
-module.exports = processExecSync
diff --git a/deps/npm/node_modules/node-gyp/test/reporter.js b/deps/npm/node_modules/node-gyp/test/reporter.js
deleted file mode 100644
index 9964b1b5d504c0..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/reporter.js
+++ /dev/null
@@ -1,75 +0,0 @@
-const Mocha = require('mocha')
-
-class Reporter {
-  constructor (runner) {
-    this.failedTests = []
-
-    runner.on(Mocha.Runner.constants.EVENT_RUN_BEGIN, () => {
-      console.log('Starting tests')
-    })
-
-    runner.on(Mocha.Runner.constants.EVENT_RUN_END, () => {
-      console.log('Tests finished')
-      console.log()
-      console.log('****************')
-      console.log('* TESTS REPORT *')
-      console.log('****************')
-      console.log()
-      console.log(`Executed ${runner.stats.suites} suites with ${runner.stats.tests} tests in ${runner.stats.duration} ms`)
-      console.log(`  Passed: ${runner.stats.passes}`)
-      console.log(`  Skipped: ${runner.stats.pending}`)
-      console.log(`  Failed: ${runner.stats.failures}`)
-      if (this.failedTests.length > 0) {
-        console.log()
-        console.log('  Failed test details')
-        this.failedTests.forEach((failedTest, index) => {
-          console.log()
-          console.log(`    ${index + 1}.'${failedTest.test.fullTitle()}'`)
-          console.log(`      Name: ${failedTest.error.name}`)
-          console.log(`      Message: ${failedTest.error.message}`)
-          console.log(`      Code: ${failedTest.error.code}`)
-          console.log(`      Stack: ${failedTest.error.stack}`)
-        })
-      }
-      console.log()
-    })
-
-    runner.on(Mocha.Runner.constants.EVENT_SUITE_BEGIN, (suite) => {
-      if (suite.root) {
-        return
-      }
-      console.log(`Starting suite '${suite.title}'`)
-    })
-
-    runner.on(Mocha.Runner.constants.EVENT_SUITE_END, (suite) => {
-      if (suite.root) {
-        return
-      }
-      console.log(`Suite '${suite.title}' finished`)
-      console.log()
-    })
-
-    runner.on(Mocha.Runner.constants.EVENT_TEST_BEGIN, (test) => {
-      console.log(`Starting test '${test.title}'`)
-    })
-
-    runner.on(Mocha.Runner.constants.EVENT_TEST_PASS, (test) => {
-      console.log(`Test '${test.title}' passed in ${test.duration} ms`)
-    })
-
-    runner.on(Mocha.Runner.constants.EVENT_TEST_PENDING, (test) => {
-      console.log(`Test '${test.title}' skipped in ${test.duration} ms`)
-    })
-
-    runner.on(Mocha.Runner.constants.EVENT_TEST_FAIL, (test, error) => {
-      this.failedTests.push({ test, error })
-      console.log(`Test '${test.title}' failed in ${test.duration} ms with ${error}`)
-    })
-
-    runner.on(Mocha.Runner.constants.EVENT_TEST_END, (test) => {
-      console.log()
-    })
-  }
-}
-
-module.exports = Reporter
diff --git a/deps/npm/node_modules/node-gyp/test/simple-proxy.js b/deps/npm/node_modules/node-gyp/test/simple-proxy.js
deleted file mode 100644
index cb0dfcfec7edcd..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/simple-proxy.js
+++ /dev/null
@@ -1,27 +0,0 @@
-'use strict'
-
-const http = require('http')
-const https = require('https')
-const server = http.createServer(handler)
-const port = +process.argv[2]
-const prefix = process.argv[3]
-const upstream = process.argv[4]
-var calls = 0
-
-server.listen(port)
-
-function handler (req, res) {
-  if (req.url.indexOf(prefix) !== 0) {
-    throw new Error('request url [' + req.url + '] does not start with [' + prefix + ']')
-  }
-
-  var upstreamUrl = upstream + req.url.substring(prefix.length)
-  https.get(upstreamUrl, function (ures) {
-    ures.on('end', function () {
-      if (++calls === 2) {
-        server.close()
-      }
-    })
-    ures.pipe(res)
-  })
-}
diff --git a/deps/npm/node_modules/node-gyp/test/test-addon.js b/deps/npm/node_modules/node-gyp/test/test-addon.js
deleted file mode 100644
index 43556620a85abb..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/test-addon.js
+++ /dev/null
@@ -1,152 +0,0 @@
-'use strict'
-
-const { describe, it } = require('mocha')
-const assert = require('assert')
-const path = require('path')
-const fs = require('graceful-fs')
-const childProcess = require('child_process')
-const os = require('os')
-const addonPath = path.resolve(__dirname, 'node_modules', 'hello_world')
-const nodeGyp = path.resolve(__dirname, '..', 'bin', 'node-gyp.js')
-const execFileSync = childProcess.execFileSync || require('./process-exec-sync')
-const execFile = childProcess.execFile
-
-function runHello (hostProcess) {
-  if (!hostProcess) {
-    hostProcess = process.execPath
-  }
-  var testCode = "console.log(require('hello_world').hello())"
-  return execFileSync(hostProcess, ['-e', testCode], { cwd: __dirname }).toString()
-}
-
-function getEncoding () {
-  var code = 'import locale;print(locale.getdefaultlocale()[1])'
-  return execFileSync('python', ['-c', code]).toString().trim()
-}
-
-function checkCharmapValid () {
-  var data
-  try {
-    data = execFileSync('python', ['fixtures/test-charmap.py'],
-      { cwd: __dirname })
-  } catch (err) {
-    return false
-  }
-  var lines = data.toString().trim().split('\n')
-  return lines.pop() === 'True'
-}
-
-describe('addon', function () {
-  this.timeout(300000)
-
-  it('build simple addon', function (done) {
-    // Set the loglevel otherwise the output disappears when run via 'npm test'
-    var cmd = [nodeGyp, 'rebuild', '-C', addonPath, '--loglevel=verbose']
-    var proc = execFile(process.execPath, cmd, function (err, stdout, stderr) {
-      var logLines = stderr.toString().trim().split(/\r?\n/)
-      var lastLine = logLines[logLines.length - 1]
-      assert.strictEqual(err, null)
-      assert.strictEqual(lastLine, 'gyp info ok', 'should end in ok')
-      assert.strictEqual(runHello().trim(), 'world')
-      done()
-    })
-    proc.stdout.setEncoding('utf-8')
-    proc.stderr.setEncoding('utf-8')
-  })
-
-  it('build simple addon in path with non-ascii characters', function (done) {
-    if (!checkCharmapValid()) {
-      return this.skip('python console app can\'t encode non-ascii character.')
-    }
-
-    var testDirNames = {
-      cp936: '文件夹',
-      cp1252: 'Latīna',
-      cp932: 'フォルダ'
-    }
-    // Select non-ascii characters by current encoding
-    var testDirName = testDirNames[getEncoding()]
-    // If encoding is UTF-8 or other then no need to test
-    if (!testDirName) {
-      return this.skip('no need to test')
-    }
-
-    this.timeout(300000)
-
-    var data
-    var configPath = path.join(addonPath, 'build', 'config.gypi')
-    try {
-      data = fs.readFileSync(configPath, 'utf8')
-    } catch (err) {
-      assert.fail(err)
-      return
-    }
-    var config = JSON.parse(data.replace(/#.+\n/, ''))
-    var nodeDir = config.variables.nodedir
-    var testNodeDir = path.join(addonPath, testDirName)
-    // Create symbol link to path with non-ascii characters
-    try {
-      fs.symlinkSync(nodeDir, testNodeDir, 'dir')
-    } catch (err) {
-      switch (err.code) {
-        case 'EEXIST': break
-        case 'EPERM':
-          assert.fail(err, null, 'Please try to running console as an administrator')
-          return
-        default:
-          assert.fail(err)
-          return
-      }
-    }
-
-    var cmd = [
-      nodeGyp,
-      'rebuild',
-      '-C',
-      addonPath,
-      '--loglevel=verbose',
-      '-nodedir=' + testNodeDir
-    ]
-    var proc = execFile(process.execPath, cmd, function (err, stdout, stderr) {
-      try {
-        fs.unlink(testNodeDir)
-      } catch (err) {
-        assert.fail(err)
-      }
-
-      var logLines = stderr.toString().trim().split(/\r?\n/)
-      var lastLine = logLines[logLines.length - 1]
-      assert.strictEqual(err, null)
-      assert.strictEqual(lastLine, 'gyp info ok', 'should end in ok')
-      assert.strictEqual(runHello().trim(), 'world')
-      done()
-    })
-    proc.stdout.setEncoding('utf-8')
-    proc.stderr.setEncoding('utf-8')
-  })
-
-  it('addon works with renamed host executable', function (done) {
-    // No `fs.copyFileSync` before node8.
-    if (process.version.substr(1).split('.')[0] < 8) {
-      return this.skip('skipping test for old node version')
-    }
-
-    this.timeout(300000)
-
-    var notNodePath = path.join(os.tmpdir(), 'notnode' + path.extname(process.execPath))
-    fs.copyFileSync(process.execPath, notNodePath)
-
-    var cmd = [nodeGyp, 'rebuild', '-C', addonPath, '--loglevel=verbose']
-    var proc = execFile(process.execPath, cmd, function (err, stdout, stderr) {
-      var logLines = stderr.toString().trim().split(/\r?\n/)
-      var lastLine = logLines[logLines.length - 1]
-      assert.strictEqual(err, null)
-      assert.strictEqual(lastLine, 'gyp info ok', 'should end in ok')
-      assert.strictEqual(runHello(notNodePath).trim(), 'world')
-      fs.unlinkSync(notNodePath)
-      done()
-    })
-    proc.stdout.setEncoding('utf-8')
-    proc.stderr.setEncoding('utf-8')
-  })
-})
diff --git a/deps/npm/node_modules/node-gyp/test/test-configure-python.js b/deps/npm/node_modules/node-gyp/test/test-configure-python.js
deleted file mode 100644
index ab1e5511fad980..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/test-configure-python.js
+++ /dev/null
@@ -1,81 +0,0 @@
-'use strict'
-
-const { describe, it } = require('mocha')
-const assert = require('assert')
-const path = require('path')
-const devDir = require('./common').devDir()
-const gyp = require('../lib/node-gyp')
-const requireInject = require('require-inject')
-const configure = requireInject('../lib/configure', {
-  'graceful-fs': {
-    openSync: function () { return 0 },
-    closeSync: function () { },
-    writeFile: function (file, data, cb) { cb() },
-    stat: function (file, cb) { cb(null, {}) },
-    mkdir: function (dir, options, cb) { cb() },
-    promises: {
-      writeFile: function (file, data) { return Promise.resolve(null) }
-    },
-    unlink: function (path, cb) { cb() },
-    symlink: function (target, path, cb) { cb() }
-  }
-})
-
-const EXPECTED_PYPATH = path.join(__dirname, '..', 'gyp', 'pylib')
-const SEPARATOR = process.platform === 'win32' ? ';' : ':'
-const SPAWN_RESULT = cb => ({ on: function () { cb() } })
-
-require('npmlog').level = 'warn'
-
-describe('configure-python', function () {
-  it('configure PYTHONPATH with no existing env', function (done) {
-    delete process.env.PYTHONPATH
-
-    var prog = gyp()
-    prog.parseArgv([])
-    prog.spawn = function () {
-      assert.strictEqual(process.env.PYTHONPATH, EXPECTED_PYPATH)
-      return SPAWN_RESULT(done)
-    }
-    prog.devDir = devDir
-    configure(prog, [], assert.fail)
-  })
-
-  it('configure PYTHONPATH with existing env of one dir', function (done) {
-    var existingPath = path.join('a', 'b')
-    process.env.PYTHONPATH = existingPath
-
-    var prog = gyp()
-    prog.parseArgv([])
-    prog.spawn = function () {
-      assert.strictEqual(process.env.PYTHONPATH, [EXPECTED_PYPATH, existingPath].join(SEPARATOR))
-
-      var dirs = process.env.PYTHONPATH.split(SEPARATOR)
-      assert.deepStrictEqual(dirs, [EXPECTED_PYPATH, existingPath])
-
-      return SPAWN_RESULT(done)
-    }
-    prog.devDir = devDir
-    configure(prog, [], assert.fail)
-  })
-
-  it('configure PYTHONPATH with existing env of multiple dirs', function (done) {
-    var pythonDir1 = path.join('a', 'b')
-    var pythonDir2 = path.join('b', 'c')
-    var existingPath = [pythonDir1, pythonDir2].join(SEPARATOR)
-    process.env.PYTHONPATH = existingPath
-
-    var prog = gyp()
-    prog.parseArgv([])
-    prog.spawn = function () {
-      assert.strictEqual(process.env.PYTHONPATH, [EXPECTED_PYPATH, existingPath].join(SEPARATOR))
-
-      var dirs = process.env.PYTHONPATH.split(SEPARATOR)
-      assert.deepStrictEqual(dirs, [EXPECTED_PYPATH, pythonDir1, pythonDir2])
-
-      return SPAWN_RESULT(done)
-    }
-    prog.devDir = devDir
-    configure(prog, [], assert.fail)
-  })
-})
diff --git a/deps/npm/node_modules/node-gyp/test/test-create-config-gypi.js b/deps/npm/node_modules/node-gyp/test/test-create-config-gypi.js
deleted file mode 100644
index 725819b6aa1029..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/test-create-config-gypi.js
+++ /dev/null
@@ -1,61 +0,0 @@
-'use strict'
-
-const path = require('path')
-const { describe, it } = require('mocha')
-const assert = require('assert')
-const gyp = require('../lib/node-gyp')
-const createConfigGypi = require('../lib/create-config-gypi')
-const { parseConfigGypi, getCurrentConfigGypi } = createConfigGypi.test
-
-describe('create-config-gypi', function () {
-  it('config.gypi with no options', async function () {
-    const prog = gyp()
-    prog.parseArgv([])
-
-    const config = await getCurrentConfigGypi({ gyp: prog, vsInfo: {} })
-    assert.strictEqual(config.target_defaults.default_configuration, 'Release')
-    assert.strictEqual(config.variables.target_arch, process.arch)
-  })
-
-  it('config.gypi with --debug', async function () {
-    const prog = gyp()
-    prog.parseArgv(['_', '_', '--debug'])
-
-    const config = await getCurrentConfigGypi({ gyp: prog, vsInfo: {} })
-    assert.strictEqual(config.target_defaults.default_configuration, 'Debug')
-  })
-
-  it('config.gypi with custom options', async function () {
-    const prog = gyp()
-    prog.parseArgv(['_', '_', '--shared-libxml2'])
-
-    const config = await getCurrentConfigGypi({ gyp: prog, vsInfo: {} })
-    assert.strictEqual(config.variables.shared_libxml2, true)
-  })
-
-  it('config.gypi with nodedir', async function () {
-    const nodeDir = path.join(__dirname, 'fixtures', 'nodedir')
-
-    const prog = gyp()
-    prog.parseArgv(['_', '_', `--nodedir=${nodeDir}`])
-
-    const config = await getCurrentConfigGypi({ gyp: prog, nodeDir, vsInfo: {} })
-    assert.strictEqual(config.variables.build_with_electron, true)
-  })
-
-  it('config.gypi with --force-process-config', async function () {
-    const nodeDir = path.join(__dirname, 'fixtures', 'nodedir')
-
-    const prog = gyp()
-    prog.parseArgv(['_', '_', '--force-process-config', `--nodedir=${nodeDir}`])
-
-    const config = await getCurrentConfigGypi({ gyp: prog, nodeDir, vsInfo: {} })
-    assert.strictEqual(config.variables.build_with_electron, undefined)
-  })
-
-  it('config.gypi parsing', function () {
-    const str = "# Some comments\n{'variables': {'multiline': 'A'\n'B'}}"
-    const config = parseConfigGypi(str)
-    assert.deepStrictEqual(config, { variables: { multiline: 'AB' } })
-  })
-})
diff --git a/deps/npm/node_modules/node-gyp/test/test-download.js b/deps/npm/node_modules/node-gyp/test/test-download.js
deleted file mode 100644
index 1dd5a51b062c0b..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/test-download.js
+++ /dev/null
@@ -1,210 +0,0 @@
-'use strict'
-
-const { describe, it, after } = require('mocha')
-const assert = require('assert')
-const fs = require('fs')
-const path = require('path')
-const util = require('util')
-const http = require('http')
-const https = require('https')
-const install = require('../lib/install')
-const semver = require('semver')
-const devDir = require('./common').devDir()
-const rimraf = require('rimraf')
-const gyp = require('../lib/node-gyp')
-const log = require('npmlog')
-const certs = require('./fixtures/certs')
-
-log.level = 'warn'
-
-describe('download', function () {
-  it('download over http', async function () {
-    const server = http.createServer((req, res) => {
-      assert.strictEqual(req.headers['user-agent'], `node-gyp v42 (node ${process.version})`)
-      res.end('ok')
-    })
-
-    after(() => new Promise((resolve) => server.close(resolve)))
-
-    const host = 'localhost'
-    await new Promise((resolve) => server.listen(0, host, resolve))
-    const { port } = server.address()
-    const gyp = {
-      opts: {},
-      version: '42'
-    }
-    const url = `http://${host}:${port}`
-    const res = await install.test.download(gyp, url)
-    assert.strictEqual(await res.text(), 'ok')
-  })
-
-  it('download over https with custom ca', async function () {
-    const cafile = path.join(__dirname, 'fixtures/ca.crt')
-    const cacontents = certs['ca.crt']
-    const cert = certs['server.crt']
-    const key = certs['server.key']
-    await fs.promises.writeFile(cafile, cacontents, 'utf8')
-    const ca = await install.test.readCAFile(cafile)
-
-    assert.strictEqual(ca.length, 1)
-
-    const options = { ca: ca, cert: cert, key: key }
-    const server = https.createServer(options, (req, res) => {
-      assert.strictEqual(req.headers['user-agent'], `node-gyp v42 (node ${process.version})`)
-      res.end('ok')
-    })
-
-    after(async () => {
-      await new Promise((resolve) => server.close(resolve))
-      await fs.promises.unlink(cafile)
-    })
-
-    server.on('clientError', (err) => { throw err })
-
-    const host = 'localhost'
-    await new Promise((resolve) => server.listen(0, host, resolve))
-    const { port } = server.address()
-    const gyp = {
-      opts: { cafile },
-      version: '42'
-    }
-    const url = `https://${host}:${port}`
-    const res = await install.test.download(gyp, url)
-    assert.strictEqual(await res.text(), 'ok')
-  })
-
-  it('download over http with proxy', async function () {
-    const server = http.createServer((_, res) => {
-      res.end('ok')
-    })
-
-    const pserver = http.createServer((req, res) => {
-      assert.strictEqual(req.headers['user-agent'], `node-gyp v42 (node ${process.version})`)
-      res.end('proxy ok')
-    })
-
-    after(() => Promise.all([
-      new Promise((resolve) => server.close(resolve)),
-      new Promise((resolve) => pserver.close(resolve))
-    ]))
-
-    const host = 'localhost'
-    await new Promise((resolve) => server.listen(0, host, resolve))
-    const { port } = server.address()
-    await new Promise((resolve) => pserver.listen(port + 1, host, resolve))
-    const gyp = {
-      opts: {
-        proxy: `http://${host}:${port + 1}`,
-        noproxy: 'bad'
-      },
-      version: '42'
-    }
-    const url = `http://${host}:${port}`
-    const res = await install.test.download(gyp, url)
-    assert.strictEqual(await res.text(), 'proxy ok')
-  })
-
-  it('download over http with noproxy', async function () {
-    const server = http.createServer((req, res) => {
-      assert.strictEqual(req.headers['user-agent'], `node-gyp v42 (node ${process.version})`)
-      res.end('ok')
-    })
-
-    const pserver = http.createServer((_, res) => {
-      res.end('proxy ok')
-    })
-
-    after(() => Promise.all([
-      new Promise((resolve) => server.close(resolve)),
-      new Promise((resolve) => pserver.close(resolve))
-    ]))
-
-    const host = 'localhost'
-    await new Promise((resolve) => server.listen(0, host, resolve))
-    const { port } = server.address()
-    await new Promise((resolve) => pserver.listen(port + 1, host, resolve))
-    const gyp = {
-      opts: {
-        proxy: `http://${host}:${port + 1}`,
-        noproxy: host
-      },
-      version: '42'
-    }
-    const url = `http://${host}:${port}`
-    const res = await install.test.download(gyp, url)
-    assert.strictEqual(await res.text(), 'ok')
-  })
-
-  it('download with missing cafile', async function () {
-    const gyp = {
-      opts: { cafile: 'no.such.file' }
-    }
-    try {
-      await install.test.download(gyp, {}, 'http://bad/')
-    } catch (e) {
-      assert.ok(/no.such.file/.test(e.message))
-    }
-  })
-
-  it('check certificate splitting', async function () {
-    const cafile = path.join(__dirname, 'fixtures/ca-bundle.crt')
-    const cacontents = certs['ca-bundle.crt']
-    await fs.promises.writeFile(cafile, cacontents, 'utf8')
-    after(async () => {
-      await fs.promises.unlink(cafile)
-    })
-    const cas = await install.test.readCAFile(path.join(__dirname, 'fixtures/ca-bundle.crt'))
-    assert.strictEqual(cas.length, 2)
-    assert.notStrictEqual(cas[0], cas[1])
-  })
-
-  // only run this test if we are running a version of Node with predictable version path behavior
-
-  it('download headers (actual)', async function () {
-    if (process.env.FAST_TEST ||
-        process.release.name !== 'node' ||
-        semver.prerelease(process.version) !== null ||
-        semver.satisfies(process.version, '<10')) {
-      return this.skip('Skipping actual download of headers due to test environment configuration')
-    }
-
-    this.timeout(300000)
-
-    const expectedDir = path.join(devDir, process.version.replace(/^v/, ''))
-    await util.promisify(rimraf)(expectedDir)
-
-    const prog = gyp()
-    prog.parseArgv([])
-    prog.devDir = devDir
-    log.level = 'warn'
-    await util.promisify(install)(prog, [])
-
-    const data = await fs.promises.readFile(path.join(expectedDir, 'installVersion'), 'utf8')
-    assert.strictEqual(data, '11\n', 'correct installVersion')
-
-    const list = await fs.promises.readdir(path.join(expectedDir, 'include/node'))
-    assert.ok(list.includes('common.gypi'))
-    assert.ok(list.includes('config.gypi'))
-    assert.ok(list.includes('node.h'))
-    assert.ok(list.includes('node_version.h'))
-    assert.ok(list.includes('openssl'))
-    assert.ok(list.includes('uv'))
-    assert.ok(list.includes('uv.h'))
-    assert.ok(list.includes('v8-platform.h'))
-    assert.ok(list.includes('v8.h'))
-    assert.ok(list.includes('zlib.h'))
-
-    const lines = (await fs.promises.readFile(path.join(expectedDir, 'include/node/node_version.h'), 'utf8')).split('\n')
-
-    // extract the 3 version parts from the defines to build a valid version string and
-    // and check them against our current env version
-    const version = ['major', 'minor', 'patch'].reduce((version, type) => {
-      const re = new RegExp(`^#define\\sNODE_${type.toUpperCase()}_VERSION`)
-      const line = lines.find((l) => re.test(l))
-      const i = line ? parseInt(line.replace(/^[^0-9]+([0-9]+).*$/, '$1'), 10) : 'ERROR'
-      return `${version}${type !== 'major' ? '.' : 'v'}${i}`
-    }, '')
-
-    assert.strictEqual(version, process.version)
-  })
-})
diff --git a/deps/npm/node_modules/node-gyp/test/test-find-accessible-sync.js b/deps/npm/node_modules/node-gyp/test/test-find-accessible-sync.js
deleted file mode 100644
index 7edbc0c76446ed..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/test-find-accessible-sync.js
+++ /dev/null
@@ -1,73 +0,0 @@
-'use strict'
-
-const { describe, it } = require('mocha')
-const assert = require('assert')
-const path = require('path')
-const requireInject = require('require-inject')
-const configure = requireInject('../lib/configure', {
-  'graceful-fs': {
-    closeSync: function () { return undefined },
-    openSync: function (path) {
-      if (readableFiles.some(function (f) { return f === path })) {
-        return 0
-      } else {
-        var error = new Error('ENOENT - not found')
-        throw error
-      }
-    }
-  }
-})
-
-const dir = path.sep + 'testdir'
-const readableFile = 'readable_file'
-const anotherReadableFile = 'another_readable_file'
-const readableFileInDir = 'somedir' + path.sep + readableFile
-const readableFiles = [
-  path.resolve(dir, readableFile),
-  path.resolve(dir, anotherReadableFile),
-  path.resolve(dir, readableFileInDir)
-]
-
-describe('find-accessible-sync', function () {
-  it('find accessible - empty array', function () {
-    var candidates = []
-    var found = configure.test.findAccessibleSync('test', dir, candidates)
-    assert.strictEqual(found, undefined)
-  })
-
-  it('find accessible - single item array, readable', function () {
-    var candidates = [readableFile]
-    var found = configure.test.findAccessibleSync('test', dir, candidates)
-    assert.strictEqual(found, path.resolve(dir, readableFile))
-  })
-
-  it('find accessible - single item array, readable in subdir', function () {
-    var candidates = [readableFileInDir]
-    var found = configure.test.findAccessibleSync('test', dir, candidates)
-    assert.strictEqual(found, path.resolve(dir, readableFileInDir))
-  })
-
-  it('find accessible - single item array, unreadable', function () {
-    var candidates = ['unreadable_file']
-    var found = configure.test.findAccessibleSync('test', dir, candidates)
-    assert.strictEqual(found, undefined)
-  })
-
-  it('find accessible - multi item array, no matches', function () {
-    var candidates = ['non_existent_file', 'unreadable_file']
-    var found = configure.test.findAccessibleSync('test', dir, candidates)
-    assert.strictEqual(found, undefined)
-  })
-
-  it('find accessible - multi item array, single match', function () {
-    var candidates = ['non_existent_file', readableFile]
-    var found = configure.test.findAccessibleSync('test', dir, candidates)
-    assert.strictEqual(found, path.resolve(dir, readableFile))
-  })
-
-  it('find accessible - multi item array, return first match', function () {
-    var candidates = ['non_existent_file', anotherReadableFile, readableFile]
-    var found = configure.test.findAccessibleSync('test', dir, candidates)
-    assert.strictEqual(found, path.resolve(dir, anotherReadableFile))
-  })
-})
diff --git a/deps/npm/node_modules/node-gyp/test/test-find-node-directory.js b/deps/npm/node_modules/node-gyp/test/test-find-node-directory.js
deleted file mode 100644
index ca299f63306469..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/test-find-node-directory.js
+++ /dev/null
@@ -1,115 +0,0 @@
-'use strict'
-
-const { describe, it } = require('mocha')
-const assert = require('assert')
-const path = require('path')
-const findNodeDirectory = require('../lib/find-node-directory')
-
-const platforms = ['darwin', 'freebsd', 'linux', 'sunos', 'win32', 'aix', 'os400']
-
-describe('find-node-directory', function () {
-  // we should find the directory based on the directory
-  // the script is running in and it should match the layout
-  // in a build tree where npm is installed in
-  // .... /deps/npm
-  it('test find-node-directory - node install', function () {
-    for (var next = 0; next < platforms.length; next++) {
-      var processObj = { execPath: '/x/y/bin/node', platform: platforms[next] }
-      assert.strictEqual(
-        findNodeDirectory('/x/deps/npm/node_modules/node-gyp/lib', processObj),
-        path.join('/x'))
-    }
-  })
-
-  // we should find the directory based on the directory
-  // the script is running in and it should match the layout
-  // in an installed tree where npm is installed in
-  // .... /lib/node_modules/npm or .../node_modules/npm
-  // depending on the patform
-  it('test find-node-directory - node build', function () {
-    for (var next = 0; next < platforms.length; next++) {
-      var processObj = { execPath: '/x/y/bin/node', platform: platforms[next] }
-      if (platforms[next] === 'win32') {
-        assert.strictEqual(
-          findNodeDirectory('/y/node_modules/npm/node_modules/node-gyp/lib',
-            processObj), path.join('/y'))
-      } else {
-        assert.strictEqual(
-          findNodeDirectory('/y/lib/node_modules/npm/node_modules/node-gyp/lib',
-            processObj), path.join('/y'))
-      }
-    }
-  })
-
-  // we should find the directory based on the execPath
-  // for node and match because it was in the bin directory
-  it('test find-node-directory - node in bin directory', function () {
-    for (var next = 0; next < platforms.length; next++) {
-      var processObj = { execPath: '/x/y/bin/node', platform: platforms[next] }
-      assert.strictEqual(
-        findNodeDirectory('/nothere/npm/node_modules/node-gyp/lib', processObj),
-        path.join('/x/y'))
-    }
-  })
-
-  // we should find the directory based on the execPath
-  // for node and match because it was in the Release directory
-  it('test find-node-directory - node in build release dir', function () {
-    for (var next = 0; next < platforms.length; next++) {
-      var processObj
-      if (platforms[next] === 'win32') {
-        processObj = { execPath: '/x/y/Release/node', platform: platforms[next] }
-      } else {
-        processObj = {
-          execPath: '/x/y/out/Release/node',
-          platform: platforms[next]
-        }
-      }
-
-      assert.strictEqual(
-        findNodeDirectory('/nothere/npm/node_modules/node-gyp/lib', processObj),
-        path.join('/x/y'))
-    }
-  })
-
-  // we should find the directory based on the execPath
-  // for node and match because it was in the Debug directory
-  it('test find-node-directory - node in Debug release dir', function () {
-    for (var next = 0; next < platforms.length; next++) {
-      var processObj
-      if (platforms[next] === 'win32') {
-        processObj = { execPath: '/a/b/Debug/node', platform: platforms[next] }
-      } else {
-        processObj = { execPath: '/a/b/out/Debug/node', platform: platforms[next] }
-      }
-
-      assert.strictEqual(
-        findNodeDirectory('/nothere/npm/node_modules/node-gyp/lib', processObj),
-        path.join('/a/b'))
-    }
-  })
-
-  // we should not find it as it will not match based on the execPath nor
-  // the directory from which the script is running
-  it('test find-node-directory - not found', function () {
-    for (var next = 0; next < platforms.length; next++) {
-      var processObj = { execPath: '/x/y/z/y', platform: next }
-      assert.strictEqual(findNodeDirectory('/a/b/c/d', processObj), '')
-    }
-  })
-
-  // we should find the directory based on the directory
-  // the script is running in and it should match the layout
-  // in a build tree where npm is installed in
-  // .... /deps/npm
-  // same test as above but make sure additional directory entries
-  // don't cause an issue
-  it('test find-node-directory - node install', function () {
-    for (var next = 0; next < platforms.length; next++) {
-      var processObj = { execPath: '/x/y/bin/node', platform: platforms[next] }
-      assert.strictEqual(
-        findNodeDirectory('/x/y/z/a/b/c/deps/npm/node_modules/node-gyp/lib',
-          processObj), path.join('/x/y/z/a/b/c'))
-    }
-  })
-})
diff --git a/deps/npm/node_modules/node-gyp/test/test-find-python.js b/deps/npm/node_modules/node-gyp/test/test-find-python.js
deleted file mode 100644
index 592c480f24fef2..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/test-find-python.js
+++ /dev/null
@@ -1,213 +0,0 @@
-'use strict'
-
-delete process.env.PYTHON
-
-const { describe, it } = require('mocha')
-const assert = require('assert')
-const findPython = require('../lib/find-python')
-const execFile = require('child_process').execFile
-const PythonFinder = findPython.test.PythonFinder
-
-require('npmlog').level = 'warn'
-
-describe('find-python', function () {
-  it('find python', function () {
-    findPython.test.findPython(null, function (err, found) {
-      assert.strictEqual(err, null)
-      var proc = execFile(found, ['-V'], function (err, stdout, stderr) {
-        assert.strictEqual(err, null)
-        assert.ok(/Python 3/.test(stdout))
-        assert.strictEqual(stderr, '')
-      })
-      proc.stdout.setEncoding('utf-8')
-      proc.stderr.setEncoding('utf-8')
-    })
-  })
-
-  function poison (object, property) {
-    function fail () {
-      console.error(Error(`Property ${property} should not have been accessed.`))
-      process.abort()
-    }
-    var descriptor = {
-      configurable: false,
-      enumerable: false,
-      get: fail,
-      set: fail
-    }
-    Object.defineProperty(object, property, descriptor)
-  }
-
-  function TestPythonFinder () {
-    PythonFinder.apply(this, arguments)
-  }
-  TestPythonFinder.prototype = Object.create(PythonFinder.prototype)
-  // Silence npmlog - remove for debugging
-  TestPythonFinder.prototype.log = {
-    silly: () => {},
-    verbose: () => {},
-    info: () => {},
-    warn: () => {},
-    error: () => {}
-  }
-  delete TestPythonFinder.prototype.env.NODE_GYP_FORCE_PYTHON
-
-  it('find python - python', function () {
-    var f = new TestPythonFinder('python', done)
-    f.execFile = function (program, args, opts, cb) {
-      f.execFile = function (program, args, opts, cb) {
-        poison(f, 'execFile')
-        assert.strictEqual(program, '/path/python')
-        assert.ok(/sys\.version_info/.test(args[1]))
-        cb(null, '3.9.1')
-      }
-      assert.strictEqual(program,
-        process.platform === 'win32' ? '"python"' : 'python')
-      assert.ok(/sys\.executable/.test(args[1]))
-      cb(null, '/path/python')
-    }
-    f.findPython()
-
-    function done (err, python) {
-      assert.strictEqual(err, null)
-      assert.strictEqual(python, '/path/python')
-    }
-  })
-
-  it('find python - python too old', function () {
-    var f = new TestPythonFinder(null, done)
-    f.execFile = function (program, args, opts, cb) {
-      if (/sys\.executable/.test(args[args.length - 1])) {
-        cb(null, '/path/python')
-      } else if (/sys\.version_info/.test(args[args.length - 1])) {
-        cb(null, '2.3.4')
-      } else {
-        assert.fail()
-      }
-    }
-    f.findPython()
-
-    function done (err) {
-      assert.ok(/Could not find any Python/.test(err))
-      assert.ok(/not supported/i.test(f.errorLog))
-    }
-  })
-
-  it('find python - no python', function () {
-    var f = new TestPythonFinder(null, done)
-    f.execFile = function (program, args, opts, cb) {
-      if (/sys\.executable/.test(args[args.length - 1])) {
-        cb(new Error('not found'))
-      } else if (/sys\.version_info/.test(args[args.length - 1])) {
-        cb(new Error('not a Python executable'))
-      } else {
-        assert.fail()
-      }
-    }
-    f.findPython()
-
-    function done (err) {
-      assert.ok(/Could not find any Python/.test(err))
-      assert.ok(/not in PATH/.test(f.errorLog))
-    }
-  })
-
-  it('find python - no python2, no python, unix', function () {
-    var f = new TestPythonFinder(null, done)
-    f.checkPyLauncher = assert.fail
-    f.win = false
-
-    f.execFile = function (program, args, opts, cb) {
-      if (/sys\.executable/.test(args[args.length - 1])) {
-        cb(new Error('not found'))
-      } else {
-        assert.fail()
-      }
-    }
-    f.findPython()
-
-    function done (err) {
-      assert.ok(/Could not find any Python/.test(err))
-      assert.ok(/not in PATH/.test(f.errorLog))
-    }
-  })
-
-  it('find python - no python, use python launcher', function () {
-    var f = new TestPythonFinder(null, done)
-    f.win = true
-
-    f.execFile = function (program, args, opts, cb) {
-      if (program === 'py.exe') {
-        assert.notStrictEqual(args.indexOf('-3'), -1)
-        assert.notStrictEqual(args.indexOf('-c'), -1)
-        return cb(null, 'Z:\\snake.exe')
-      }
-      if (/sys\.executable/.test(args[args.length - 1])) {
-        cb(new Error('not found'))
-      } else if (f.winDefaultLocations.includes(program)) {
-        cb(new Error('not found'))
-      } else if (/sys\.version_info/.test(args[args.length - 1])) {
-        if (program === 'Z:\\snake.exe') {
-          cb(null, '3.9.0')
-        } else {
-          assert.fail()
-        }
-      } else {
-        assert.fail()
-      }
-    }
-    f.findPython()
-
-    function done (err, python) {
-      assert.strictEqual(err, null)
-      assert.strictEqual(python, 'Z:\\snake.exe')
-    }
-  })
-
-  it('find python - no python, no python launcher, good guess', function () {
-    var f = new TestPythonFinder(null, done)
-    f.win = true
-    const expectedProgram = f.winDefaultLocations[0]
-
-    f.execFile = function (program, args, opts, cb) {
-      if (program === 'py.exe') {
-        return cb(new Error('not found'))
-      }
-      if (/sys\.executable/.test(args[args.length - 1])) {
-        cb(new Error('not found'))
-      } else if (program === expectedProgram &&
-                 /sys\.version_info/.test(args[args.length - 1])) {
-        cb(null, '3.7.3')
-      } else {
-        assert.fail()
-      }
-    }
-    f.findPython()
-
-    function done (err, python) {
-      assert.strictEqual(err, null)
-      assert.ok(python === expectedProgram)
-    }
-  })
-
-  it('find python - no python, no python launcher, bad guess', function () {
-    var f = new TestPythonFinder(null, done)
-    f.win = true
-
-    f.execFile = function (program, args, opts, cb) {
-      if (/sys\.executable/.test(args[args.length - 1])) {
-        cb(new Error('not found'))
-      } else if (/sys\.version_info/.test(args[args.length - 1])) {
-        cb(new Error('not a Python executable'))
-      } else {
-        assert.fail()
-      }
-    }
-    f.findPython()
-
-    function done (err) {
-      assert.ok(/Could not find any Python/.test(err))
-      assert.ok(/not in PATH/.test(f.errorLog))
-    }
-  })
-})
diff --git a/deps/npm/node_modules/node-gyp/test/test-find-visualstudio.js b/deps/npm/node_modules/node-gyp/test/test-find-visualstudio.js
deleted file mode 100644
index 29d9a7dba5f550..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/test-find-visualstudio.js
+++ /dev/null
@@ -1,670 +0,0 @@
-'use strict'
-
-const { describe, it } = require('mocha')
-const assert = require('assert')
-const fs = require('fs')
-const path = require('path')
-const findVisualStudio = require('../lib/find-visualstudio')
-const VisualStudioFinder = findVisualStudio.test.VisualStudioFinder
-
-const semverV1 = { major: 1, minor: 0, patch: 0 }
-
-delete process.env.VCINSTALLDIR
-
-function poison (object, property) {
-  function fail () {
-    console.error(Error(`Property ${property} should not have been accessed.`))
-    process.abort()
-  }
-  var descriptor = {
-    configurable: false,
-    enumerable: false,
-    get: fail,
-    set: fail
-  }
-  Object.defineProperty(object, property, descriptor)
-}
-
-function TestVisualStudioFinder () { VisualStudioFinder.apply(this, arguments) }
-TestVisualStudioFinder.prototype = Object.create(VisualStudioFinder.prototype)
-// Silence npmlog - remove for debugging
-TestVisualStudioFinder.prototype.log = {
-  silly: () => {},
-  verbose: () => {},
-  info: () => {},
-  warn: () => {},
-  error: () => {}
-}
-
-describe('find-visualstudio', function () {
-  it('VS2013', function () {
-    const finder = new TestVisualStudioFinder(semverV1, null, (err, info) => {
-      assert.strictEqual(err, null)
-      assert.deepStrictEqual(info, {
-        msBuild: 'C:\\MSBuild12\\MSBuild.exe',
-        path: 'C:\\VS2013',
-        sdk: null,
-        toolset: 'v120',
-        version: '12.0',
-        versionMajor: 12,
-        versionMinor: 0,
-        versionYear: 2013
-      })
-    })
-
-    finder.findVisualStudio2017OrNewer = (cb) => {
-      finder.parseData(new Error(), '', '', cb)
-    }
-    finder.regSearchKeys = (keys, value, addOpts, cb) => {
-      for (var i = 0; i < keys.length; ++i) {
-        const fullName = `${keys[i]}\\${value}`
-        switch (fullName) {
-          case 'HKLM\\Software\\Microsoft\\VisualStudio\\SxS\\VC7\\14.0':
-          case 'HKLM\\Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7\\14.0':
-            continue
-          case 'HKLM\\Software\\Microsoft\\VisualStudio\\SxS\\VC7\\12.0':
-            assert.ok(true, `expected search for registry value ${fullName}`)
-            return cb(null, 'C:\\VS2013\\VC\\')
-          case 'HKLM\\Software\\Microsoft\\MSBuild\\ToolsVersions\\12.0\\MSBuildToolsPath':
-            assert.ok(true, `expected search for registry value ${fullName}`)
-            return cb(null, 'C:\\MSBuild12\\')
-          default:
-            assert.fail(`unexpected search for registry value ${fullName}`)
-        }
-      }
-      return cb(new Error())
-    }
-    finder.findVisualStudio()
-  })
-
-  it('VS2013 should not be found on new node versions', function () {
-    const finder = new TestVisualStudioFinder({
-      major: 10,
-      minor: 0,
-      patch: 0
-    }, null, (err, info) => {
-      assert.ok(/find .* Visual Studio/i.test(err), 'expect error')
-      assert.ok(!info, 'no data')
-    })
-
-    finder.findVisualStudio2017OrNewer = (cb) => {
-      const file = path.join(__dirname, 'fixtures', 'VS_2017_Unusable.txt')
-      const data = fs.readFileSync(file)
-      finder.parseData(null, data, '', cb)
-    }
-    finder.regSearchKeys = (keys, value, addOpts, cb) => {
-      for (var i = 0; i < keys.length; ++i) {
-        const fullName = `${keys[i]}\\${value}`
-        switch (fullName) {
-          case 'HKLM\\Software\\Microsoft\\VisualStudio\\SxS\\VC7\\14.0':
-          case 'HKLM\\Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7\\14.0':
-            continue
-          default:
-            assert.fail(`unexpected search for registry value ${fullName}`)
-        }
-      }
-      return cb(new Error())
-    }
-    finder.findVisualStudio()
-  })
-
-  it('VS2015', function () {
-    const finder = new TestVisualStudioFinder(semverV1, null, (err, info) => {
-      assert.strictEqual(err, null)
-      assert.deepStrictEqual(info, {
-        msBuild: 'C:\\MSBuild14\\MSBuild.exe',
-        path: 'C:\\VS2015',
-        sdk: null,
-        toolset: 'v140',
-        version: '14.0',
-        versionMajor: 14,
-        versionMinor: 0,
-        versionYear: 2015
-      })
-    })
-
-    finder.findVisualStudio2017OrNewer = (cb) => {
-      finder.parseData(new Error(), '', '', cb)
-    }
-    finder.regSearchKeys = (keys, value, addOpts, cb) => {
-      for (var i = 0; i < keys.length; ++i) {
-        const fullName = `${keys[i]}\\${value}`
-        switch (fullName) {
-          case 'HKLM\\Software\\Microsoft\\VisualStudio\\SxS\\VC7\\14.0':
-            assert.ok(true, `expected search for registry value ${fullName}`)
-            return cb(null, 'C:\\VS2015\\VC\\')
-          case 'HKLM\\Software\\Microsoft\\MSBuild\\ToolsVersions\\14.0\\MSBuildToolsPath':
-            assert.ok(true, `expected search for registry value ${fullName}`)
-            return cb(null, 'C:\\MSBuild14\\')
-          default:
-            assert.fail(`unexpected search for registry value ${fullName}`)
-        }
-      }
-      return cb(new Error())
-    }
-    finder.findVisualStudio()
-  })
-
-  it('error from PowerShell', function () {
-    const finder = new TestVisualStudioFinder(semverV1, null, null)
-
-    finder.parseData(new Error(), '', '', (info) => {
-      assert.ok(/use PowerShell/i.test(finder.errorLog[0]), 'expect error')
-      assert.ok(!info, 'no data')
-    })
-  })
-
-  it('empty output from PowerShell', function () {
-    const finder = new TestVisualStudioFinder(semverV1, null, null)
-
-    finder.parseData(null, '', '', (info) => {
-      assert.ok(/use PowerShell/i.test(finder.errorLog[0]), 'expect error')
-      assert.ok(!info, 'no data')
-    })
-  })
-
-  it('output from PowerShell not JSON', function () {
-    const finder = new TestVisualStudioFinder(semverV1, null, null)
-
-    finder.parseData(null, 'AAAABBBB', '', (info) => {
-      assert.ok(/use PowerShell/i.test(finder.errorLog[0]), 'expect error')
-      assert.ok(!info, 'no data')
-    })
-  })
-
-  it('wrong JSON from PowerShell', function () {
-    const finder = new TestVisualStudioFinder(semverV1, null, null)
-
-    finder.parseData(null, '{}', '', (info) => {
-      assert.ok(/use PowerShell/i.test(finder.errorLog[0]), 'expect error')
-      assert.ok(!info, 'no data')
-    })
-  })
-
-  it('empty JSON from PowerShell', function () {
-    const finder = new TestVisualStudioFinder(semverV1, null, null)
-
-    finder.parseData(null, '[]', '', (info) => {
-      assert.ok(/find .* Visual Studio/i.test(finder.errorLog[0]), 'expect error')
-      assert.ok(!info, 'no data')
-    })
-  })
-
-  it('future version', function () {
-    const finder = new TestVisualStudioFinder(semverV1, null, null)
-
-    finder.parseData(null, JSON.stringify([{
-      packages: [
-        'Microsoft.VisualStudio.Component.VC.Tools.x86.x64',
-        'Microsoft.VisualStudio.Component.Windows10SDK.17763',
-        'Microsoft.VisualStudio.VC.MSBuild.Base'
-      ],
-      path: 'C:\\VS',
-      version: '9999.9999.9999.9999'
-    }]), '', (info) => {
-      assert.ok(/unknown version/i.test(finder.errorLog[0]), 'expect error')
-      assert.ok(/find .* Visual Studio/i.test(finder.errorLog[1]), 'expect error')
-      assert.ok(!info, 'no data')
-    })
-  })
-
-  it('single unusable VS2017', function () {
-    const finder = new TestVisualStudioFinder(semverV1, null, null)
-
-    const file = path.join(__dirname, 'fixtures', 'VS_2017_Unusable.txt')
-    const data = fs.readFileSync(file)
-    finder.parseData(null, data, '', (info) => {
-      assert.ok(/checking/i.test(finder.errorLog[0]), 'expect error')
-      assert.ok(/find .* Visual Studio/i.test(finder.errorLog[2]), 'expect error')
-      assert.ok(!info, 'no data')
-    })
-  })
-
-  it('minimal VS2017 Build Tools', function () {
-    const finder = new TestVisualStudioFinder(semverV1, null, (err, info) => {
-      assert.strictEqual(err, null)
-      assert.deepStrictEqual(info, {
-        msBuild: 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\' +
-          'BuildTools\\MSBuild\\15.0\\Bin\\MSBuild.exe',
-        path:
-          'C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools',
-        sdk: '10.0.17134.0',
-        toolset: 'v141',
-        version: '15.9.28307.665',
-        versionMajor: 15,
-        versionMinor: 9,
-        versionYear: 2017
-      })
-    })
-
-    poison(finder, 'regSearchKeys')
-    finder.findVisualStudio2017OrNewer = (cb) => {
-      const file = path.join(__dirname, 'fixtures',
-        'VS_2017_BuildTools_minimal.txt')
-      const data = fs.readFileSync(file)
-      finder.parseData(null, data, '', cb)
-    }
-    finder.findVisualStudio()
-  })
-
-  it('VS2017 Community with C++ workload', function () {
-    const finder = new TestVisualStudioFinder(semverV1, null, (err, info) => {
-      assert.strictEqual(err, null)
-      assert.deepStrictEqual(info, {
-        msBuild: 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\' +
-          'Community\\MSBuild\\15.0\\Bin\\MSBuild.exe',
-        path:
-          'C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community',
-        sdk: '10.0.17763.0',
-        toolset: 'v141',
-        version: '15.9.28307.665',
-        versionMajor: 15,
-        versionMinor: 9,
-        versionYear: 2017
-      })
-    })
-
-    poison(finder, 'regSearchKeys')
-    finder.findVisualStudio2017OrNewer = (cb) => {
-      const file = path.join(__dirname, 'fixtures',
-        'VS_2017_Community_workload.txt')
-      const data = fs.readFileSync(file)
-      finder.parseData(null, data, '', cb)
-    }
-    finder.findVisualStudio()
-  })
-
-  it('VS2017 Express', function () {
-    const finder = new TestVisualStudioFinder(semverV1, null, (err, info) => {
-      assert.strictEqual(err, null)
-      assert.deepStrictEqual(info, {
-        msBuild: 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\' +
-          'WDExpress\\MSBuild\\15.0\\Bin\\MSBuild.exe',
-        path:
-          'C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\WDExpress',
-        sdk: '10.0.17763.0',
-        toolset: 'v141',
-        version: '15.9.28307.858',
-        versionMajor: 15,
-        versionMinor: 9,
-        versionYear: 2017
-      })
-    })
-
-    poison(finder, 'regSearchKeys')
-    finder.findVisualStudio2017OrNewer = (cb) => {
-      const file = path.join(__dirname, 'fixtures', 'VS_2017_Express.txt')
-      const data = fs.readFileSync(file)
-      finder.parseData(null, data, '', cb)
-    }
-    finder.findVisualStudio()
-  })
-
-  it('VS2019 Preview with C++ workload', function () {
-    const finder = new TestVisualStudioFinder(semverV1, null, (err, info) => {
-      assert.strictEqual(err, null)
-      assert.deepStrictEqual(info, {
-        msBuild: 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\' +
-          'Preview\\MSBuild\\Current\\Bin\\MSBuild.exe',
-        path:
-          'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Preview',
-        sdk: '10.0.17763.0',
-        toolset: 'v142',
-        version: '16.0.28608.199',
-        versionMajor: 16,
-        versionMinor: 0,
-        versionYear: 2019
-      })
-    })
-
-    poison(finder, 'regSearchKeys')
-    finder.findVisualStudio2017OrNewer = (cb) => {
-      const file = path.join(__dirname, 'fixtures',
-        'VS_2019_Preview.txt')
-      const data = fs.readFileSync(file)
-      finder.parseData(null, data, '', cb)
-    }
-    finder.findVisualStudio()
-  })
-
-  it('minimal VS2019 Build Tools', function () {
-    const finder = new TestVisualStudioFinder(semverV1, null, (err, info) => {
-      assert.strictEqual(err, null)
-      assert.deepStrictEqual(info, {
-        msBuild: 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\' +
-          'BuildTools\\MSBuild\\Current\\Bin\\MSBuild.exe',
-        path:
-          'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools',
-        sdk: '10.0.17134.0',
-        toolset: 'v142',
-        version: '16.1.28922.388',
-        versionMajor: 16,
-        versionMinor: 1,
-        versionYear: 2019
-      })
-    })
-
-    poison(finder, 'regSearchKeys')
-    finder.findVisualStudio2017OrNewer = (cb) => {
-      const file = path.join(__dirname, 'fixtures',
-        'VS_2019_BuildTools_minimal.txt')
-      const data = fs.readFileSync(file)
-      finder.parseData(null, data, '', cb)
-    }
-    finder.findVisualStudio()
-  })
-
-  it('VS2019 Community with C++ workload', function () {
-    const finder = new TestVisualStudioFinder(semverV1, null, (err, info) => {
-      assert.strictEqual(err, null)
-      assert.deepStrictEqual(info, {
-        msBuild: 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\' +
-          'Community\\MSBuild\\Current\\Bin\\MSBuild.exe',
-        path:
-          'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community',
-        sdk: '10.0.17763.0',
-        toolset: 'v142',
-        version: '16.1.28922.388',
-        versionMajor: 16,
-        versionMinor: 1,
-        versionYear: 2019
-      })
-    })
-
-    poison(finder, 'regSearchKeys')
-    finder.findVisualStudio2017OrNewer = (cb) => {
-      const file = path.join(__dirname, 'fixtures',
-        'VS_2019_Community_workload.txt')
-      const data = fs.readFileSync(file)
-      finder.parseData(null, data, '', cb)
-    }
-    finder.findVisualStudio()
-  })
-
-  it('VS2022 Preview with C++ workload', function () {
-    const msBuildPath = process.arch === 'arm64'
-      ? 'C:\\Program Files\\Microsoft Visual Studio\\2022\\' +
-        'Community\\MSBuild\\Current\\Bin\\arm64\\MSBuild.exe'
-      : 'C:\\Program Files\\Microsoft Visual Studio\\2022\\' +
-        'Community\\MSBuild\\Current\\Bin\\MSBuild.exe'
-
-    const finder = new TestVisualStudioFinder(semverV1, null, (err, info) => {
-      assert.strictEqual(err, null)
-      assert.deepStrictEqual(info, {
-        msBuild: msBuildPath,
-        path:
-          'C:\\Program Files\\Microsoft Visual Studio\\2022\\Community',
-        sdk: '10.0.22621.0',
-        toolset: 'v143',
-        version: '17.4.33213.308',
-        versionMajor: 17,
-        versionMinor: 4,
-        versionYear: 2022
-      })
-    })
-
-    poison(finder, 'regSearchKeys')
-    finder.msBuildPathExists = (path) => {
-      return true
-    }
-    finder.findVisualStudio2017OrNewer = (cb) => {
-      const file = path.join(__dirname, 'fixtures',
-        'VS_2022_Community_workload.txt')
-      const data = fs.readFileSync(file)
-      finder.parseData(null, data, '', cb)
-    }
-    finder.findVisualStudio()
-  })
-
-  function allVsVersions (finder) {
-    finder.findVisualStudio2017OrNewer = (cb) => {
-      const data0 = JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures',
-        'VS_2017_Unusable.txt')))
-      const data1 = JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures',
-        'VS_2017_BuildTools_minimal.txt')))
-      const data2 = JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures',
-        'VS_2017_Community_workload.txt')))
-      const data3 = JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures',
-        'VS_2017_Express.txt')))
-      const data4 = JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures',
-        'VS_2019_Preview.txt')))
-      const data5 = JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures',
-        'VS_2019_BuildTools_minimal.txt')))
-      const data6 = JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures',
-        'VS_2019_Community_workload.txt')))
-      const data7 = JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures',
-        'VS_2022_Community_workload.txt')))
-      const data = JSON.stringify(data0.concat(data1, data2, data3, data4,
-        data5, data6, data7))
-      finder.parseData(null, data, '', cb)
-    }
-    finder.regSearchKeys = (keys, value, addOpts, cb) => {
-      for (var i = 0; i < keys.length; ++i) {
-        const fullName = `${keys[i]}\\${value}`
-        switch (fullName) {
-          case 'HKLM\\Software\\Microsoft\\VisualStudio\\SxS\\VC7\\14.0':
-          case 'HKLM\\Software\\Microsoft\\VisualStudio\\SxS\\VC7\\12.0':
-            continue
-          case 'HKLM\\Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7\\12.0':
-            return cb(null, 'C:\\VS2013\\VC\\')
-          case 'HKLM\\Software\\Microsoft\\MSBuild\\ToolsVersions\\12.0\\MSBuildToolsPath':
-            return cb(null, 'C:\\MSBuild12\\')
-          case 'HKLM\\Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7\\14.0':
-            return cb(null, 'C:\\VS2015\\VC\\')
-          case 'HKLM\\Software\\Microsoft\\MSBuild\\ToolsVersions\\14.0\\MSBuildToolsPath':
-            return cb(null, 'C:\\MSBuild14\\')
-          default:
-            assert.fail(`unexpected search for registry value ${fullName}`)
-        }
-      }
-      return cb(new Error())
-    }
-  }
-
-  it('fail when looking for invalid path', function () {
-    const finder = new TestVisualStudioFinder(semverV1, 'AABB', (err, info) => {
-      assert.ok(/find .* Visual Studio/i.test(err), 'expect error')
-      assert.ok(!info, 'no data')
-    })
-
-    allVsVersions(finder)
-    finder.findVisualStudio()
-  })
-
-  it('look for VS2013 by version number', function () {
-    const finder = new TestVisualStudioFinder(semverV1, '2013', (err, info) => {
-      assert.strictEqual(err, null)
-      assert.deepStrictEqual(info.versionYear, 2013)
-    })
-
-    allVsVersions(finder)
-    finder.findVisualStudio()
-  })
-
-  it('look for VS2013 by installation path', function () {
-    const finder = new TestVisualStudioFinder(semverV1, 'C:\\VS2013',
-      (err, info) => {
-        assert.strictEqual(err, null)
-        assert.deepStrictEqual(info.path, 'C:\\VS2013')
-      })
-
-    allVsVersions(finder)
-    finder.findVisualStudio()
-  })
-
-  it('look for VS2015 by version number', function () {
-    const finder = new TestVisualStudioFinder(semverV1, '2015', (err, info) => {
-      assert.strictEqual(err, null)
-      assert.deepStrictEqual(info.versionYear, 2015)
-    })
-
-    allVsVersions(finder)
-    finder.findVisualStudio()
-  })
-
-  it('look for VS2015 by installation path', function () {
-    const finder = new TestVisualStudioFinder(semverV1, 'C:\\VS2015',
-      (err, info) => {
-        assert.strictEqual(err, null)
-        assert.deepStrictEqual(info.path, 'C:\\VS2015')
-      })
-
-    allVsVersions(finder)
-    finder.findVisualStudio()
-  })
-
-  it('look for VS2017 by version number', function () {
-    const finder = new TestVisualStudioFinder(semverV1, '2017', (err, info) => {
-      assert.strictEqual(err, null)
-      assert.deepStrictEqual(info.versionYear, 2017)
-    })
-
-    allVsVersions(finder)
-    finder.findVisualStudio()
-  })
-
-  it('look for VS2017 by installation path', function () {
-    const finder = new TestVisualStudioFinder(semverV1,
-      'C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community',
-      (err, info) => {
-        assert.strictEqual(err, null)
-        assert.deepStrictEqual(info.path,
-          'C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community')
-      })
-
-    allVsVersions(finder)
-    finder.findVisualStudio()
-  })
-
-  it('look for VS2019 by version number', function () {
-    const finder = new TestVisualStudioFinder(semverV1, '2019', (err, info) => {
-      assert.strictEqual(err, null)
-      assert.deepStrictEqual(info.versionYear, 2019)
-    })
-
-    allVsVersions(finder)
-    finder.findVisualStudio()
-  })
-
-  it('look for VS2019 by installation path', function () {
-    const finder = new TestVisualStudioFinder(semverV1,
-      'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools',
-      (err, info) => {
-        assert.strictEqual(err, null)
-        assert.deepStrictEqual(info.path,
-          'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools')
-      })
-
-    allVsVersions(finder)
-    finder.findVisualStudio()
-  })
-
-  it('look for VS2022 by version number', function () {
-    const finder = new TestVisualStudioFinder(semverV1, '2022', (err, info) => {
-      assert.strictEqual(err, null)
-      assert.deepStrictEqual(info.versionYear, 2022)
-    })
-
-    finder.msBuildPathExists = (path) => {
-      return true
-    }
-
-    allVsVersions(finder)
-    finder.findVisualStudio()
-  })
-
-  it('msvs_version match should be case insensitive', function () {
-    const finder = new TestVisualStudioFinder(semverV1,
-      'c:\\program files (x86)\\microsoft visual studio\\2019\\BUILDTOOLS',
-      (err, info) => {
-        assert.strictEqual(err, null)
-        assert.deepStrictEqual(info.path,
-          'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools')
-      })
-
-    allVsVersions(finder)
-    finder.findVisualStudio()
-  })
-
-  it('latest version should be found by default', function () {
-    const finder = new TestVisualStudioFinder(semverV1, null, (err, info) => {
-      assert.strictEqual(err, null)
-      assert.deepStrictEqual(info.versionYear, 2022)
-    })
-
-    finder.msBuildPathExists = (path) => {
-      return true
-    }
-
-    allVsVersions(finder)
-    finder.findVisualStudio()
-  })
-
-  it('run on a usable VS Command Prompt', function () {
-    process.env.VCINSTALLDIR = 'C:\\VS2015\\VC'
-    // VSINSTALLDIR is not defined on Visual C++ Build Tools 2015
-    delete process.env.VSINSTALLDIR
-
-    const finder = new TestVisualStudioFinder(semverV1, null, (err, info) => {
-      assert.strictEqual(err, null)
-      assert.deepStrictEqual(info.path, 'C:\\VS2015')
-    })
-
-    allVsVersions(finder)
-    finder.findVisualStudio()
-  })
-
-  it('VCINSTALLDIR match should be case insensitive', function () {
-    process.env.VCINSTALLDIR =
-      'c:\\program files (x86)\\microsoft visual studio\\2019\\BUILDTOOLS\\VC'
-
-    const finder = new TestVisualStudioFinder(semverV1, null, (err, info) => {
-      assert.strictEqual(err, null)
-      assert.deepStrictEqual(info.path,
-        'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools')
-    })
-
-    allVsVersions(finder)
-    finder.findVisualStudio()
-  })
-
-  it('run on a unusable VS Command Prompt', function () {
-    process.env.VCINSTALLDIR =
-      'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildToolsUnusable\\VC'
-
-    const finder = new TestVisualStudioFinder(semverV1, null, (err, info) => {
-      assert.ok(/find .* Visual Studio/i.test(err), 'expect error')
-      assert.ok(!info, 'no data')
-    })
-
-    allVsVersions(finder)
-    finder.findVisualStudio()
-  })
-
-  it('run on a VS Command Prompt with matching msvs_version', function () {
-    process.env.VCINSTALLDIR = 'C:\\VS2015\\VC'
-
-    const finder = new TestVisualStudioFinder(semverV1, 'C:\\VS2015',
-      (err, info) => {
-        assert.strictEqual(err, null)
-        assert.deepStrictEqual(info.path, 'C:\\VS2015')
-      })
-
-    allVsVersions(finder)
-    finder.findVisualStudio()
-  })
-
-  it('run on a VS Command Prompt with mismatched msvs_version', function () {
-    process.env.VCINSTALLDIR =
-      'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC'
-
-    const finder = new TestVisualStudioFinder(semverV1, 'C:\\VS2015',
-      (err, info) => {
-        assert.ok(/find .* Visual Studio/i.test(err), 'expect error')
-        assert.ok(!info, 'no data')
-      })
-
-    allVsVersions(finder)
-    finder.findVisualStudio()
-  })
-})
diff --git a/deps/npm/node_modules/node-gyp/test/test-install.js b/deps/npm/node_modules/node-gyp/test/test-install.js
deleted file mode 100644
index 235acf52313969..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/test-install.js
+++ /dev/null
@@ -1,137 +0,0 @@
-'use strict'
-
-const { describe, it, after } = require('mocha')
-const assert = require('assert')
-const path = require('path')
-const os = require('os')
-const util = require('util')
-const { test: { download, install } } = require('../lib/install')
-const rimraf = require('rimraf')
-const gyp = require('../lib/node-gyp')
-const log = require('npmlog')
-const semver = require('semver')
-const stream = require('stream')
-const streamPipeline = util.promisify(stream.pipeline)
-
-log.level = 'error' // we expect a warning
-
-describe('install', function () {
-  it('EACCES retry once', async () => {
-    const fs = {
-      promises: {
-        stat (_) {
-          const err = new Error()
-          err.code = 'EACCES'
-          assert.ok(true)
-          throw err
-        }
-      }
-    }
-
-    const Gyp = {
-      devDir: __dirname,
-      opts: {
-        ensure: true
-      },
-      commands: {
-        install (argv, cb) {
-          install(fs, Gyp, argv).then(cb, cb)
-        },
-        remove (_, cb) {
-          cb()
-        }
-      }
-    }
-
-    try {
-      await install(fs, Gyp, [])
-    } catch (err) {
-      assert.ok(true)
-      if (/"pre" versions of node cannot be installed/.test(err.message)) {
-        assert.ok(true)
-      }
-    }
-  })
-
-  // only run these tests if we are running a version of Node with predictable version path behavior
-  const skipParallelInstallTests = process.env.FAST_TEST ||
-    process.release.name !== 'node' ||
-    semver.prerelease(process.version) !== null ||
-    semver.satisfies(process.version, '<10')
-
-  async function parallelInstallsTest (test, fs, devDir, prog) {
-    if (skipParallelInstallTests) {
-      return test.skip('Skipping parallel installs test due to test environment configuration')
-    }
-
-    after(async () => {
-      await util.promisify(rimraf)(devDir)
-    })
-
-    const expectedDir = path.join(devDir, process.version.replace(/^v/, ''))
-    await util.promisify(rimraf)(expectedDir)
-
-    await Promise.all([
-      install(fs, prog, []),
-      install(fs, prog, []),
-      install(fs, prog, []),
-      install(fs, prog, []),
-      install(fs, prog, []),
-      install(fs, prog, []),
-      install(fs, prog, []),
-      install(fs, prog, []),
-      install(fs, prog, []),
-      install(fs, prog, [])
-    ])
-  }
-
-  it('parallel installs (ensure=true)', async function () {
-    this.timeout(600000)
-
-    const fs = require('graceful-fs')
-    const devDir = await util.promisify(fs.mkdtemp)(path.join(os.tmpdir(), 'node-gyp-test-'))
-
-    const prog = gyp()
-    prog.parseArgv([])
-    prog.devDir = devDir
-    prog.opts.ensure = true
-    log.level = 'warn'
-
-    await parallelInstallsTest(this, fs, devDir, prog)
-  })
-
-  it('parallel installs (ensure=false)', async function () {
-    this.timeout(600000)
-
-    const fs = require('graceful-fs')
-    const devDir = await util.promisify(fs.mkdtemp)(path.join(os.tmpdir(), 'node-gyp-test-'))
-
-    const prog = gyp()
-    prog.parseArgv([])
-    prog.devDir = devDir
-    prog.opts.ensure = false
-    log.level = 'warn'
-
-    await parallelInstallsTest(this, fs, devDir, prog)
-  })
-
-  it('parallel installs (tarball)', async function () {
-    this.timeout(600000)
-
-    const fs = require('graceful-fs')
-    const devDir = await util.promisify(fs.mkdtemp)(path.join(os.tmpdir(), 'node-gyp-test-'))
-
-    const prog = gyp()
-    prog.parseArgv([])
-    prog.devDir = devDir
-    prog.opts.tarball = path.join(devDir, 'node-headers.tar.gz')
-    log.level = 'warn'
-
-    await streamPipeline(
-      (await download(prog, `https://nodejs.org/dist/${process.version}/node-${process.version}.tar.gz`)).body,
-      fs.createWriteStream(prog.opts.tarball)
-    )
-
-    await parallelInstallsTest(this, fs, devDir, prog)
-  })
-})
diff --git a/deps/npm/node_modules/node-gyp/test/test-options.js b/deps/npm/node_modules/node-gyp/test/test-options.js
deleted file mode 100644
index 24e79c80a18432..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/test-options.js
+++ /dev/null
@@ -1,41 +0,0 @@
-'use strict'
-
-const { describe, it } = require('mocha')
-const assert = require('assert')
-const gyp = require('../lib/node-gyp')
-
-describe('options', function () {
-  it('options in environment', () => {
-    // `npm test` dumps a ton of npm_config_* variables in the environment.
-    Object.keys(process.env)
-      .filter((key) => /^npm_config_/.test(key))
-      .forEach((key) => { delete process.env[key] })
-
-    // in some platforms, certain keys are stubborn and cannot be removed
-    const keys = Object.keys(process.env)
-      .filter((key) => /^npm_config_/.test(key))
-      .map((key) => key.substring('npm_config_'.length))
-      .concat('argv', 'x')
-
-    // Zero-length keys should get filtered out.
-    process.env.npm_config_ = '42'
-    // Other keys should get added.
-    process.env.npm_config_x = '42'
-    // Except loglevel.
-    process.env.npm_config_loglevel = 'debug'
-
-    const g = gyp()
-    g.parseArgv(['rebuild']) // Also sets opts.argv.
-
-    assert.deepStrictEqual(Object.keys(g.opts).sort(), keys.sort())
-  })
-
-  it('options with spaces in environment', () => {
-    process.env.npm_config_force_process_config = 'true'
-
-    const g = gyp()
-    g.parseArgv(['rebuild']) // Also sets opts.argv.
-
-    assert.strictEqual(g.opts['force-process-config'], 'true')
-  })
-})
diff --git a/deps/npm/node_modules/node-gyp/test/test-process-release.js b/deps/npm/node_modules/node-gyp/test/test-process-release.js
deleted file mode 100644
index 0f40666473028c..00000000000000
--- a/deps/npm/node_modules/node-gyp/test/test-process-release.js
+++ /dev/null
@@ -1,401 +0,0 @@
-'use strict'
-
-const { describe, it } = require('mocha')
-const assert = require('assert')
-const processRelease = require('../lib/process-release')
-
-describe('process-release', function () {
-  it('test process release - process.version = 0.8.20', function () {
-    var release = processRelease([], { opts: {} }, 'v0.8.20', null)
-
-    assert.strictEqual(release.semver.version, '0.8.20')
-    delete release.semver
-
-    assert.deepStrictEqual(release, {
-      version: '0.8.20',
-      name: 'node',
-      baseUrl: 'https://nodejs.org/dist/v0.8.20/',
-      tarballUrl: 'https://nodejs.org/dist/v0.8.20/node-v0.8.20.tar.gz',
-      shasumsUrl: 'https://nodejs.org/dist/v0.8.20/SHASUMS256.txt',
-      versionDir: '0.8.20',
-      ia32: { libUrl: 'https://nodejs.org/dist/v0.8.20/node.lib', libPath: 'node.lib' },
-      x64: { libUrl: 'https://nodejs.org/dist/v0.8.20/x64/node.lib', libPath: 'x64/node.lib' },
-      arm64: { libUrl: 'https://nodejs.org/dist/v0.8.20/arm64/node.lib', libPath: 'arm64/node.lib' }
-    })
-  })
-
-  it('test process release - process.version = 0.10.21', function () {
-    var release = processRelease([], { opts: {} }, 'v0.10.21', null)
-
-    assert.strictEqual(release.semver.version, '0.10.21')
-    delete release.semver
-
-    assert.deepStrictEqual(release, {
-      version: '0.10.21',
-      name: 'node',
-      baseUrl: 'https://nodejs.org/dist/v0.10.21/',
-      tarballUrl: 'https://nodejs.org/dist/v0.10.21/node-v0.10.21.tar.gz',
-      shasumsUrl: 'https://nodejs.org/dist/v0.10.21/SHASUMS256.txt',
-      versionDir: '0.10.21',
-      ia32: { libUrl: 'https://nodejs.org/dist/v0.10.21/node.lib', libPath: 'node.lib' },
-      x64: { libUrl: 'https://nodejs.org/dist/v0.10.21/x64/node.lib', libPath: 'x64/node.lib' },
-      arm64: { libUrl: 'https://nodejs.org/dist/v0.10.21/arm64/node.lib', libPath: 'arm64/node.lib' }
-    })
-  })
-
-  // prior to -headers.tar.gz
-  it('test process release - process.version = 0.12.9', function () {
-    var release = processRelease([], { opts: {} }, 'v0.12.9', null)
-
-    assert.strictEqual(release.semver.version, '0.12.9')
-    delete release.semver
-
-    assert.deepStrictEqual(release, {
-      version: '0.12.9',
-      name: 'node',
-      baseUrl: 'https://nodejs.org/dist/v0.12.9/',
-      tarballUrl: 'https://nodejs.org/dist/v0.12.9/node-v0.12.9.tar.gz',
-      shasumsUrl: 'https://nodejs.org/dist/v0.12.9/SHASUMS256.txt',
-      versionDir: '0.12.9',
-      ia32: { libUrl: 'https://nodejs.org/dist/v0.12.9/node.lib', libPath: 'node.lib' },
-      x64: { libUrl: 'https://nodejs.org/dist/v0.12.9/x64/node.lib', libPath: 'x64/node.lib' },
-      arm64: { libUrl: 'https://nodejs.org/dist/v0.12.9/arm64/node.lib', libPath: 'arm64/node.lib' }
-    })
-  })
-
-  // prior to -headers.tar.gz
-  it('test process release - process.version = 0.10.41', function () {
-    var release = processRelease([], { opts: {} }, 'v0.10.41', null)
-
-    assert.strictEqual(release.semver.version, '0.10.41')
-    delete release.semver
-
-    assert.deepStrictEqual(release, {
-      version: '0.10.41',
-      name: 'node',
-      baseUrl: 'https://nodejs.org/dist/v0.10.41/',
-      tarballUrl: 'https://nodejs.org/dist/v0.10.41/node-v0.10.41.tar.gz',
-      shasumsUrl: 'https://nodejs.org/dist/v0.10.41/SHASUMS256.txt',
-      versionDir: '0.10.41',
-      ia32: { libUrl: 'https://nodejs.org/dist/v0.10.41/node.lib', libPath: 'node.lib' },
-      x64: { libUrl: 'https://nodejs.org/dist/v0.10.41/x64/node.lib', libPath: 'x64/node.lib' },
-      arm64: { libUrl: 'https://nodejs.org/dist/v0.10.41/arm64/node.lib', libPath: 'arm64/node.lib' }
-    })
-  })
-
-  // has -headers.tar.gz
-  it('test process release - process.release ~ node@0.10.42', function () {
-    var release = processRelease([], { opts: {} }, 'v0.10.42', null)
-
-    assert.strictEqual(release.semver.version, '0.10.42')
-    delete release.semver
-
-    assert.deepStrictEqual(release, {
-      version: '0.10.42',
-      name: 'node',
-      baseUrl: 'https://nodejs.org/dist/v0.10.42/',
-      tarballUrl: 'https://nodejs.org/dist/v0.10.42/node-v0.10.42-headers.tar.gz',
-      shasumsUrl: 'https://nodejs.org/dist/v0.10.42/SHASUMS256.txt',
-      versionDir: '0.10.42',
-      ia32: { libUrl: 'https://nodejs.org/dist/v0.10.42/node.lib', libPath: 'node.lib' },
-      x64: { libUrl: 'https://nodejs.org/dist/v0.10.42/x64/node.lib', libPath: 'x64/node.lib' },
-      arm64: { libUrl: 'https://nodejs.org/dist/v0.10.42/arm64/node.lib', libPath: 'arm64/node.lib' }
-    })
-  })
-
-  // has -headers.tar.gz
-  it('test process release - process.release ~ node@0.12.10', function () {
-    var release = processRelease([], { opts: {} }, 'v0.12.10', null)
-
-    assert.strictEqual(release.semver.version, '0.12.10')
-    delete release.semver
-
-    assert.deepStrictEqual(release, {
-      version: '0.12.10',
-      name: 'node',
-      baseUrl: 'https://nodejs.org/dist/v0.12.10/',
-      tarballUrl: 'https://nodejs.org/dist/v0.12.10/node-v0.12.10-headers.tar.gz',
-      shasumsUrl: 'https://nodejs.org/dist/v0.12.10/SHASUMS256.txt',
-      versionDir: '0.12.10',
-      ia32: { libUrl: 'https://nodejs.org/dist/v0.12.10/node.lib', libPath: 'node.lib' },
-      x64: { libUrl: 'https://nodejs.org/dist/v0.12.10/x64/node.lib', libPath: 'x64/node.lib' },
-      arm64: { libUrl: 'https://nodejs.org/dist/v0.12.10/arm64/node.lib', libPath: 'arm64/node.lib' }
-    })
-  })
-
-  it('test process release - process.release ~ node@4.1.23', function () {
-    var release = processRelease([], { opts: {} }, 'v4.1.23', {
-      name: 'node',
-      headersUrl: 'https://nodejs.org/dist/v4.1.23/node-v4.1.23-headers.tar.gz'
-    })
-
-    assert.strictEqual(release.semver.version, '4.1.23')
-    delete release.semver
-
-    assert.deepStrictEqual(release, {
-      version: '4.1.23',
-      name: 'node',
-      baseUrl: 'https://nodejs.org/dist/v4.1.23/',
-      tarballUrl: 'https://nodejs.org/dist/v4.1.23/node-v4.1.23-headers.tar.gz',
-      shasumsUrl: 'https://nodejs.org/dist/v4.1.23/SHASUMS256.txt',
-      versionDir: '4.1.23',
-      ia32: { libUrl: 'https://nodejs.org/dist/v4.1.23/win-x86/node.lib', libPath: 'win-x86/node.lib' },
-      x64: { libUrl: 'https://nodejs.org/dist/v4.1.23/win-x64/node.lib', libPath: 'win-x64/node.lib' },
-      arm64: { libUrl: 'https://nodejs.org/dist/v4.1.23/win-arm64/node.lib', libPath: 'win-arm64/node.lib' }
-    })
-  })
-
-  it('test process release - process.release ~ node@4.1.23 / corp build', function () {
-    var release = processRelease([], { opts: {} }, 'v4.1.23', {
-      name: 'node',
-      headersUrl: 'https://some.custom.location/node-v4.1.23-headers.tar.gz'
-    })
-
-    assert.strictEqual(release.semver.version, '4.1.23')
-    delete release.semver
-
-    assert.deepStrictEqual(release, {
-      version: '4.1.23',
-      name: 'node',
-      baseUrl: 'https://some.custom.location/',
-      tarballUrl: 'https://some.custom.location/node-v4.1.23-headers.tar.gz',
-      shasumsUrl: 'https://some.custom.location/SHASUMS256.txt',
-      versionDir: '4.1.23',
-      ia32: { libUrl: 'https://some.custom.location/win-x86/node.lib', libPath: 'win-x86/node.lib' },
-      x64: { libUrl: 'https://some.custom.location/win-x64/node.lib', libPath: 'win-x64/node.lib' },
-      arm64: { libUrl: 'https://some.custom.location/win-arm64/node.lib', libPath: 'win-arm64/node.lib' }
-    })
-  })
-
-  it('test process release - process.release ~ node@12.8.0 Windows', function () {
-    var release = processRelease([], { opts: {} }, 'v12.8.0', {
-      name: 'node',
-      sourceUrl: 'https://nodejs.org/download/release/v12.8.0/node-v12.8.0.tar.gz',
-      headersUrl: 'https://nodejs.org/download/release/v12.8.0/node-v12.8.0-headers.tar.gz',
-      libUrl: 'https://nodejs.org/download/release/v12.8.0/win-x64/node.lib'
-    })
-
-    assert.strictEqual(release.semver.version, '12.8.0')
-    delete release.semver
-
-    assert.deepStrictEqual(release, {
-      version: '12.8.0',
-      name: 'node',
-      baseUrl: 'https://nodejs.org/download/release/v12.8.0/',
-      tarballUrl: 'https://nodejs.org/download/release/v12.8.0/node-v12.8.0-headers.tar.gz',
-      shasumsUrl: 'https://nodejs.org/download/release/v12.8.0/SHASUMS256.txt',
-      versionDir: '12.8.0',
-      ia32: { libUrl: 'https://nodejs.org/download/release/v12.8.0/win-x86/node.lib', libPath: 'win-x86/node.lib' },
-      x64: { libUrl: 'https://nodejs.org/download/release/v12.8.0/win-x64/node.lib', libPath: 'win-x64/node.lib' },
-      arm64: { libUrl: 'https://nodejs.org/download/release/v12.8.0/win-arm64/node.lib', libPath: 'win-arm64/node.lib' }
-    })
-  })
-
-  it('test process release - process.release ~ node@12.8.0 Windows ARM64', function () {
-    var release = processRelease([], { opts: {} }, 'v12.8.0', {
-      name: 'node',
-      sourceUrl: 'https://unofficial-builds.nodejs.org/download/release/v12.8.0/node-v12.8.0.tar.gz',
-      headersUrl: 'https://unofficial-builds.nodejs.org/download/release/v12.8.0/node-v12.8.0-headers.tar.gz',
-      libUrl: 'https://unofficial-builds.nodejs.org/download/release/v12.8.0/win-arm64/node.lib'
-    })
-
-    assert.strictEqual(release.semver.version, '12.8.0')
-    delete release.semver
-
-    assert.deepStrictEqual(release, {
-      version: '12.8.0',
-      name: 'node',
-      baseUrl: 'https://unofficial-builds.nodejs.org/download/release/v12.8.0/',
-      tarballUrl: 'https://unofficial-builds.nodejs.org/download/release/v12.8.0/node-v12.8.0-headers.tar.gz',
-      shasumsUrl: 'https://unofficial-builds.nodejs.org/download/release/v12.8.0/SHASUMS256.txt',
-      versionDir: '12.8.0',
-      ia32: { libUrl: 'https://unofficial-builds.nodejs.org/download/release/v12.8.0/win-x86/node.lib', libPath: 'win-x86/node.lib' },
-      x64: { libUrl: 'https://unofficial-builds.nodejs.org/download/release/v12.8.0/win-x64/node.lib', libPath: 'win-x64/node.lib' },
-      arm64: { libUrl: 'https://unofficial-builds.nodejs.org/download/release/v12.8.0/win-arm64/node.lib', libPath: 'win-arm64/node.lib' }
-    })
-  })
-
-  it('test process release - process.release ~ node@4.1.23 --target=0.10.40', function () {
-    var release = processRelease([], { opts: { target: '0.10.40' } }, 'v4.1.23', {
-      name: 'node',
-      headersUrl: 'https://nodejs.org/dist/v4.1.23/node-v4.1.23-headers.tar.gz'
-    })
-
-    assert.strictEqual(release.semver.version, '0.10.40')
-    delete release.semver
-
-    assert.deepStrictEqual(release, {
-      version: '0.10.40',
-      name: 'node',
-      baseUrl: 'https://nodejs.org/dist/v0.10.40/',
-      tarballUrl: 'https://nodejs.org/dist/v0.10.40/node-v0.10.40.tar.gz',
-      shasumsUrl: 'https://nodejs.org/dist/v0.10.40/SHASUMS256.txt',
-      versionDir: '0.10.40',
-      ia32: { libUrl: 'https://nodejs.org/dist/v0.10.40/node.lib', libPath: 'node.lib' },
-      x64: { libUrl: 'https://nodejs.org/dist/v0.10.40/x64/node.lib', libPath: 'x64/node.lib' },
-      arm64: { libUrl: 'https://nodejs.org/dist/v0.10.40/arm64/node.lib', libPath: 'arm64/node.lib' }
-    })
-  })
-
-  it('test process release - process.release ~ node@4.1.23 --dist-url=https://foo.bar/baz', function () {
-    var release = processRelease([], { opts: { 'dist-url': 'https://foo.bar/baz' } }, 'v4.1.23', {
-      name: 'node',
-      headersUrl: 'https://nodejs.org/dist/v4.1.23/node-v4.1.23-headers.tar.gz'
-    })
-
-    assert.strictEqual(release.semver.version, '4.1.23')
-    delete release.semver
-
-    assert.deepStrictEqual(release, {
-      version: '4.1.23',
-      name: 'node',
-      baseUrl: 'https://foo.bar/baz/v4.1.23/',
-      tarballUrl: 'https://foo.bar/baz/v4.1.23/node-v4.1.23-headers.tar.gz',
-      shasumsUrl: 'https://foo.bar/baz/v4.1.23/SHASUMS256.txt',
-      versionDir: '4.1.23',
-      ia32: { libUrl: 'https://foo.bar/baz/v4.1.23/win-x86/node.lib', libPath: 'win-x86/node.lib' },
-      x64: { libUrl: 'https://foo.bar/baz/v4.1.23/win-x64/node.lib', libPath: 'win-x64/node.lib' },
-      arm64: { libUrl: 'https://foo.bar/baz/v4.1.23/win-arm64/node.lib', libPath: 'win-arm64/node.lib' }
-    })
-  })
-
-  it('test process release - process.release ~ frankenstein@4.1.23', function () {
-    var release = processRelease([], { opts: {} }, 'v4.1.23', {
-      name: 'frankenstein',
-      headersUrl: 'https://frankensteinjs.org/dist/v4.1.23/frankenstein-v4.1.23-headers.tar.gz'
-    })
-
-    assert.strictEqual(release.semver.version, '4.1.23')
-    delete release.semver
-
-    assert.deepStrictEqual(release, {
-      version: '4.1.23',
-      name: 'frankenstein',
-      baseUrl: 'https://frankensteinjs.org/dist/v4.1.23/',
-      tarballUrl: 'https://frankensteinjs.org/dist/v4.1.23/frankenstein-v4.1.23-headers.tar.gz',
-      shasumsUrl: 'https://frankensteinjs.org/dist/v4.1.23/SHASUMS256.txt',
-      versionDir: 'frankenstein-4.1.23',
-      ia32: { libUrl: 'https://frankensteinjs.org/dist/v4.1.23/win-x86/frankenstein.lib', libPath: 'win-x86/frankenstein.lib' },
-      x64: { libUrl: 'https://frankensteinjs.org/dist/v4.1.23/win-x64/frankenstein.lib', libPath: 'win-x64/frankenstein.lib' },
-      arm64: { libUrl: 'https://frankensteinjs.org/dist/v4.1.23/win-arm64/frankenstein.lib', libPath: 'win-arm64/frankenstein.lib' }
-    })
-  })
-
-  it('test process release - process.release ~ frankenstein@4.1.23 --dist-url=http://foo.bar/baz/', function () {
-    var release = processRelease([], { opts: { 'dist-url': 'http://foo.bar/baz/' } }, 'v4.1.23', {
-      name: 'frankenstein',
-      headersUrl: 'https://frankensteinjs.org/dist/v4.1.23/frankenstein-v4.1.23.tar.gz'
-    })
-
-    assert.strictEqual(release.semver.version, '4.1.23')
-    delete release.semver
-
-    assert.deepStrictEqual(release, {
-      version: '4.1.23',
-      name: 'frankenstein',
-      baseUrl: 'http://foo.bar/baz/v4.1.23/',
-      tarballUrl: 'http://foo.bar/baz/v4.1.23/frankenstein-v4.1.23-headers.tar.gz',
-      shasumsUrl: 'http://foo.bar/baz/v4.1.23/SHASUMS256.txt',
-      versionDir: 'frankenstein-4.1.23',
-      ia32: { libUrl: 'http://foo.bar/baz/v4.1.23/win-x86/frankenstein.lib', libPath: 'win-x86/frankenstein.lib' },
-      x64: { libUrl: 'http://foo.bar/baz/v4.1.23/win-x64/frankenstein.lib', libPath: 'win-x64/frankenstein.lib' },
-      arm64: { libUrl: 'http://foo.bar/baz/v4.1.23/win-arm64/frankenstein.lib', libPath: 'win-arm64/frankenstein.lib' }
-    })
-  })
-
-  it('test process release - process.release ~ node@4.0.0-rc.4', function () {
-    var release = processRelease([], { opts: {} }, 'v4.0.0-rc.4', {
-      name: 'node',
-      headersUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/node-v4.0.0-rc.4-headers.tar.gz'
-    })
-
-    assert.strictEqual(release.semver.version, '4.0.0-rc.4')
-    delete release.semver
-
-    assert.deepStrictEqual(release, {
-      version: '4.0.0-rc.4',
-      name: 'node',
-      baseUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/',
-      tarballUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/node-v4.0.0-rc.4-headers.tar.gz',
-      shasumsUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/SHASUMS256.txt',
-      versionDir: '4.0.0-rc.4',
-      ia32: { libUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/win-x86/node.lib', libPath: 'win-x86/node.lib' },
-      x64: { libUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/win-x64/node.lib', libPath: 'win-x64/node.lib' },
-      arm64: { libUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/win-arm64/node.lib', libPath: 'win-arm64/node.lib' }
-    })
-  })
-
-  it('test process release - process.release ~ node@4.0.0-rc.4 passed as argv[0]', function () {
-  // note the missing 'v' on the arg, it should normalise when checking
-    // whether we're on the default or not
-    var release = processRelease(['4.0.0-rc.4'], { opts: {} }, 'v4.0.0-rc.4', {
-      name: 'node',
-      headersUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/node-v4.0.0-rc.4-headers.tar.gz'
-    })
-
-    assert.strictEqual(release.semver.version, '4.0.0-rc.4')
-    delete release.semver
-
-    assert.deepStrictEqual(release, {
-      version: '4.0.0-rc.4',
-      name: 'node',
-      baseUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/',
-      tarballUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/node-v4.0.0-rc.4-headers.tar.gz',
-      shasumsUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/SHASUMS256.txt',
-      versionDir: '4.0.0-rc.4',
-      ia32: { libUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/win-x86/node.lib', libPath: 'win-x86/node.lib' },
-      x64: { libUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/win-x64/node.lib', libPath: 'win-x64/node.lib' },
-      arm64: { libUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/win-arm64/node.lib', libPath: 'win-arm64/node.lib' }
-    })
-  })
-
-  it('test process release - process.release ~ node@4.0.0-rc.4 - bogus string passed as argv[0]', function () {
-  // additional arguments can be passed in on the commandline that should be ignored if they
-    // are not specifying a valid version @ position 0
-    var release = processRelease(['this is no version!'], { opts: {} }, 'v4.0.0-rc.4', {
-      name: 'node',
-      headersUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/node-v4.0.0-rc.4-headers.tar.gz'
-    })
-
-    assert.strictEqual(release.semver.version, '4.0.0-rc.4')
-    delete release.semver
-
-    assert.deepStrictEqual(release, {
-      version: '4.0.0-rc.4',
-      name: 'node',
-      baseUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/',
-      tarballUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/node-v4.0.0-rc.4-headers.tar.gz',
-      shasumsUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/SHASUMS256.txt',
-      versionDir: '4.0.0-rc.4',
-      ia32: { libUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/win-x86/node.lib', libPath: 'win-x86/node.lib' },
-      x64: { libUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/win-x64/node.lib', libPath: 'win-x64/node.lib' },
-      arm64: { libUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/win-arm64/node.lib', libPath: 'win-arm64/node.lib' }
-    })
-  })
-
-  it('test process release - NODEJS_ORG_MIRROR', function () {
-    process.env.NODEJS_ORG_MIRROR = 'http://foo.bar'
-
-    var release = processRelease([], { opts: {} }, 'v4.1.23', {
-      name: 'node',
-      headersUrl: 'https://nodejs.org/dist/v4.1.23/node-v4.1.23-headers.tar.gz'
-    })
-
-    assert.strictEqual(release.semver.version, '4.1.23')
-    delete release.semver
-
-    assert.deepStrictEqual(release, {
-      version: '4.1.23',
-      name: 'node',
-      baseUrl: 'http://foo.bar/v4.1.23/',
-      tarballUrl: 'http://foo.bar/v4.1.23/node-v4.1.23-headers.tar.gz',
-      shasumsUrl: 'http://foo.bar/v4.1.23/SHASUMS256.txt',
-      versionDir: '4.1.23',
-      ia32: { libUrl: 'http://foo.bar/v4.1.23/win-x86/node.lib', libPath: 'win-x86/node.lib' },
-      x64: { libUrl: 'http://foo.bar/v4.1.23/win-x64/node.lib', libPath: 'win-x64/node.lib' },
-      arm64: { libUrl: 'http://foo.bar/v4.1.23/win-arm64/node.lib', libPath: 'win-arm64/node.lib' }
-    })
-
-    delete process.env.NODEJS_ORG_MIRROR
-  })
-})
diff --git a/deps/npm/node_modules/node-gyp/update-gyp.py b/deps/npm/node_modules/node-gyp/update-gyp.py
deleted file mode 100755
index 70e2d100288ec6..00000000000000
--- a/deps/npm/node_modules/node-gyp/update-gyp.py
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/env python3
-
-import argparse
-import os
-import shutil
-import subprocess
-import tarfile
-import tempfile
-import urllib.request
-
-BASE_URL = "https://github.com/nodejs/gyp-next/archive/"
-CHECKOUT_PATH = os.path.dirname(os.path.realpath(__file__))
-CHECKOUT_GYP_PATH = os.path.join(CHECKOUT_PATH, "gyp")
-
-parser = argparse.ArgumentParser()
-parser.add_argument("tag", help="gyp tag to update to")
-args = parser.parse_args()
-
-tar_url = BASE_URL + args.tag + ".tar.gz"
-
-changed_files = subprocess.check_output(["git", "diff", "--name-only"]).strip()
-if changed_files:
-    raise Exception("Can't update gyp while you have uncommitted changes in node-gyp")
-
-with tempfile.TemporaryDirectory() as tmp_dir:
-    tar_file = os.path.join(tmp_dir, "gyp.tar.gz")
-    unzip_target = os.path.join(tmp_dir, "gyp")
-    with open(tar_file, "wb") as f:
-        print("Downloading gyp-next@" + args.tag + " into temporary directory...")
-        print("From: " + tar_url)
-        with urllib.request.urlopen(tar_url) as in_file:
-            f.write(in_file.read())
-
-        print("Unzipping...")
-        with tarfile.open(tar_file, "r:gz") as tar_ref:
-            def is_within_directory(directory, target):
-
-                abs_directory = os.path.abspath(directory)
-                abs_target = os.path.abspath(target)
-
-                prefix = os.path.commonprefix([abs_directory, abs_target])
-
-                return prefix == abs_directory
-
-            def safe_extract(tar, path=".", members=None, *, numeric_owner=False):
-
-                for member in tar.getmembers():
-                    member_path = os.path.join(path, member.name)
-                    if not is_within_directory(path, member_path):
-                        raise Exception("Attempted Path Traversal in Tar File")
-
-                tar.extractall(path, members, numeric_owner=numeric_owner)
-
-            safe_extract(tar_ref, unzip_target)
-
-        print("Moving to current checkout (" + CHECKOUT_PATH + ")...")
-        if os.path.exists(CHECKOUT_GYP_PATH):
-            shutil.rmtree(CHECKOUT_GYP_PATH)
-        shutil.move(
-            os.path.join(unzip_target, os.listdir(unzip_target)[0]), CHECKOUT_GYP_PATH
-        )
-
-subprocess.check_output(["git", "add", "gyp"], cwd=CHECKOUT_PATH)
-subprocess.check_output(["git", "commit", "-m", "feat(gyp): update gyp to " + args.tag])
diff --git a/deps/npm/node_modules/normalize-package-data/package.json b/deps/npm/node_modules/normalize-package-data/package.json
index ec2773bfbe6bf8..48d2371d4a66b5 100644
--- a/deps/npm/node_modules/normalize-package-data/package.json
+++ b/deps/npm/node_modules/normalize-package-data/package.json
@@ -1,6 +1,6 @@
 {
   "name": "normalize-package-data",
-  "version": "5.0.0",
+  "version": "6.0.0",
   "author": "GitHub Inc.",
   "description": "Normalizes data that can be found in package.json files.",
   "license": "BSD-2-Clause",
@@ -21,14 +21,14 @@
     "template-oss-apply": "template-oss-apply --force"
   },
   "dependencies": {
-    "hosted-git-info": "^6.0.0",
+    "hosted-git-info": "^7.0.0",
     "is-core-module": "^2.8.1",
     "semver": "^7.3.5",
     "validate-npm-package-license": "^3.0.4"
   },
   "devDependencies": {
-    "@npmcli/eslint-config": "^3.0.1",
-    "@npmcli/template-oss": "4.5.1",
+    "@npmcli/eslint-config": "^4.0.0",
+    "@npmcli/template-oss": "4.18.0",
     "tap": "^16.0.1"
   },
   "files": [
@@ -36,11 +36,18 @@
     "lib/"
   ],
   "engines": {
-    "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+    "node": "^16.14.0 || >=18.0.0"
   },
   "templateOSS": {
     "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
-    "version": "4.5.1"
+    "version": "4.18.0",
+    "publish": "true",
+    "ciVersions": [
+      "16.14.0",
+      "16.x",
+      "18.0.0",
+      "18.x"
+    ]
   },
   "tap": {
     "branches": 86,
diff --git a/deps/npm/node_modules/npm-install-checks/lib/index.js b/deps/npm/node_modules/npm-install-checks/lib/index.js
index fa5f593aaac647..545472b61dc604 100644
--- a/deps/npm/node_modules/npm-install-checks/lib/index.js
+++ b/deps/npm/node_modules/npm-install-checks/lib/index.js
@@ -22,13 +22,13 @@ const checkEngine = (target, npmVer, nodeVer, force = false) => {
 
 const isMusl = (file) => file.includes('libc.musl-') || file.includes('ld-musl-')
 
-const checkPlatform = (target, force = false) => {
+const checkPlatform = (target, force = false, environment = {}) => {
   if (force) {
     return
   }
 
-  const platform = process.platform
-  const arch = process.arch
+  const platform = environment.os || process.platform
+  const arch = environment.cpu || process.arch
   const osOk = target.os ? checkList(platform, target.os) : true
   const cpuOk = target.cpu ? checkList(arch, target.cpu) : true
 
@@ -36,7 +36,9 @@ const checkPlatform = (target, force = false) => {
   let libcFamily = null
   if (target.libc) {
     // libc checks only work in linux, any value is a failure if we aren't
-    if (platform !== 'linux') {
+    if (environment.libc) {
+      libcOk = checkList(environment.libc, target.libc)
+    } else if (platform !== 'linux') {
       libcOk = false
     } else {
       const report = process.report.getReport()
diff --git a/deps/npm/node_modules/npm-install-checks/package.json b/deps/npm/node_modules/npm-install-checks/package.json
index 192cf68837146f..11a3b87750e25a 100644
--- a/deps/npm/node_modules/npm-install-checks/package.json
+++ b/deps/npm/node_modules/npm-install-checks/package.json
@@ -1,6 +1,6 @@
 {
   "name": "npm-install-checks",
-  "version": "6.1.1",
+  "version": "6.3.0",
   "description": "Check the engines and platform fields in package.json",
   "main": "lib/index.js",
   "dependencies": {
@@ -8,7 +8,7 @@
   },
   "devDependencies": {
     "@npmcli/eslint-config": "^4.0.0",
-    "@npmcli/template-oss": "4.13.0",
+    "@npmcli/template-oss": "4.19.0",
     "tap": "^16.0.1"
   },
   "scripts": {
@@ -39,7 +39,7 @@
   "author": "GitHub Inc.",
   "templateOSS": {
     "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
-    "version": "4.13.0",
+    "version": "4.19.0",
     "publish": "true"
   },
   "tap": {
diff --git a/deps/npm/node_modules/npm-package-arg/lib/npa.js b/deps/npm/node_modules/npm-package-arg/lib/npa.js
index 36bd18cd9f9a6e..23bf68d2e04a39 100644
--- a/deps/npm/node_modules/npm-package-arg/lib/npa.js
+++ b/deps/npm/node_modules/npm-package-arg/lib/npa.js
@@ -4,7 +4,7 @@ module.exports.resolve = resolve
 module.exports.toPurl = toPurl
 module.exports.Result = Result
 
-const url = require('url')
+const { URL } = require('url')
 const HostedGit = require('hosted-git-info')
 const semver = require('semver')
 const path = global.FAKE_WINDOWS ? require('path').win32 : require('path')
@@ -183,10 +183,11 @@ Result.prototype.toJSON = function () {
   return result
 }
 
-function setGitCommittish (res, committish) {
+// sets res.gitCommittish, res.gitRange, and res.gitSubdir
+function setGitAttrs (res, committish) {
   if (!committish) {
     res.gitCommittish = null
-    return res
+    return
   }
 
   // for each :: separated item:
@@ -224,8 +225,6 @@ function setGitCommittish (res, committish) {
     }
     log.warn('npm-package-arg', `ignoring unknown key "${name}"`)
   }
-
-  return res
 }
 
 function fromFile (res, where) {
@@ -245,10 +244,10 @@ function fromFile (res, where) {
   const rawWithPrefix = prefix + res.rawSpec
   let rawNoPrefix = rawWithPrefix.replace(/^file:/, '')
   try {
-    resolvedUrl = new url.URL(rawWithPrefix, `file://${path.resolve(where)}/`)
-    specUrl = new url.URL(rawWithPrefix)
+    resolvedUrl = new URL(rawWithPrefix, `file://${path.resolve(where)}/`)
+    specUrl = new URL(rawWithPrefix)
   } catch (originalError) {
-    const er = new Error('Invalid file: URL, must comply with RFC 8909')
+    const er = new Error('Invalid file: URL, must comply with RFC 8089')
     throw Object.assign(er, {
       raw: res.rawSpec,
       spec: res,
@@ -257,40 +256,23 @@ function fromFile (res, where) {
     })
   }
 
-  // environment switch for testing
-  if (process.env.NPM_PACKAGE_ARG_8909_STRICT !== '1') {
-    // XXX backwards compatibility lack of compliance with 8909
-    // Remove when we want a breaking change to come into RFC compliance.
-    if (resolvedUrl.host && resolvedUrl.host !== 'localhost') {
-      const rawSpec = res.rawSpec.replace(/^file:\/\//, 'file:///')
-      resolvedUrl = new url.URL(rawSpec, `file://${path.resolve(where)}/`)
-      specUrl = new url.URL(rawSpec)
-      rawNoPrefix = rawSpec.replace(/^file:/, '')
-    }
-    // turn file:/../foo into file:../foo
-    // for 1, 2 or 3 leading slashes since we attempted
-    // in the previous step to make it a file protocol url with a leading slash
-    if (/^\/{1,3}\.\.?(\/|$)/.test(rawNoPrefix)) {
-      const rawSpec = res.rawSpec.replace(/^file:\/{1,3}/, 'file:')
-      resolvedUrl = new url.URL(rawSpec, `file://${path.resolve(where)}/`)
-      specUrl = new url.URL(rawSpec)
-      rawNoPrefix = rawSpec.replace(/^file:/, '')
-    }
-    // XXX end 8909 violation backwards compatibility section
-  }
-
-  // file:foo - relative url to ./foo
-  // file:/foo - absolute path /foo
-  // file:///foo - absolute path to /foo, no authority host
-  // file://localhost/foo - absolute path to /foo, on localhost
-  // file://foo - absolute path to / on foo host (error!)
+  // XXX backwards compatibility lack of compliance with RFC 8089
   if (resolvedUrl.host && resolvedUrl.host !== 'localhost') {
-    const msg = `Invalid file: URL, must be absolute if // present`
-    throw Object.assign(new Error(msg), {
-      raw: res.rawSpec,
-      parsed: resolvedUrl,
-    })
+    const rawSpec = res.rawSpec.replace(/^file:\/\//, 'file:///')
+    resolvedUrl = new URL(rawSpec, `file://${path.resolve(where)}/`)
+    specUrl = new URL(rawSpec)
+    rawNoPrefix = rawSpec.replace(/^file:/, '')
+  }
+  // turn file:/../foo into file:../foo
+  // for 1, 2 or 3 leading slashes since we attempted
+  // in the previous step to make it a file protocol url with a leading slash
+  if (/^\/{1,3}\.\.?(\/|$)/.test(rawNoPrefix)) {
+    const rawSpec = res.rawSpec.replace(/^file:\/{1,3}/, 'file:')
+    resolvedUrl = new URL(rawSpec, `file://${path.resolve(where)}/`)
+    specUrl = new URL(rawSpec)
+    rawNoPrefix = rawSpec.replace(/^file:/, '')
   }
+  // XXX end RFC 8089 violation backwards compatibility section
 
   // turn /C:/blah into just C:/blah on windows
   let specPath = decodeURIComponent(specUrl.pathname)
@@ -320,7 +302,8 @@ function fromHostedGit (res, hosted) {
   res.hosted = hosted
   res.saveSpec = hosted.toString({ noGitPlus: false, noCommittish: false })
   res.fetchSpec = hosted.getDefaultRepresentation() === 'shortcut' ? null : hosted.toString()
-  return setGitCommittish(res, hosted.committish)
+  setGitAttrs(res, hosted.committish)
+  return res
 }
 
 function unsupportedURLType (protocol, spec) {
@@ -329,54 +312,51 @@ function unsupportedURLType (protocol, spec) {
   return err
 }
 
-function matchGitScp (spec) {
-  // git ssh specifiers are overloaded to also use scp-style git
-  // specifiers, so we have to parse those out and treat them special.
-  // They are NOT true URIs, so we can't hand them to `url.parse`.
-  //
-  // This regex looks for things that look like:
-  // git+ssh://git@my.custom.git.com:username/project.git#deadbeef
-  //
-  // ...and various combinations. The username in the beginning is *required*.
-  const matched = spec.match(/^git\+ssh:\/\/([^:#]+:[^#]+(?:\.git)?)(?:#(.*))?$/i)
-  return matched && !matched[1].match(/:[0-9]+\/?.*$/i) && {
-    fetchSpec: matched[1],
-    gitCommittish: matched[2] == null ? null : matched[2],
-  }
-}
-
 function fromURL (res) {
-  // eslint-disable-next-line node/no-deprecated-api
-  const urlparse = url.parse(res.rawSpec)
-  res.saveSpec = res.rawSpec
+  let rawSpec = res.rawSpec
+  res.saveSpec = rawSpec
+  if (rawSpec.startsWith('git+ssh:')) {
+    // git ssh specifiers are overloaded to also use scp-style git
+    // specifiers, so we have to parse those out and treat them special.
+    // They are NOT true URIs, so we can't hand them to URL.
+
+    // This regex looks for things that look like:
+    // git+ssh://git@my.custom.git.com:username/project.git#deadbeef
+    // ...and various combinations. The username in the beginning is *required*.
+    const matched = rawSpec.match(/^git\+ssh:\/\/([^:#]+:[^#]+(?:\.git)?)(?:#(.*))?$/i)
+    if (matched && !matched[1].match(/:[0-9]+\/?.*$/i)) {
+      res.type = 'git'
+      setGitAttrs(res, matched[2])
+      res.fetchSpec = matched[1]
+      return res
+    }
+  } else if (rawSpec.startsWith('git+file://')) {
+    // URL can't handle windows paths
+    rawSpec = rawSpec.replace(/\\/g, '/')
+  }
+  const parsedUrl = new URL(rawSpec)
   // check the protocol, and then see if it's git or not
-  switch (urlparse.protocol) {
+  switch (parsedUrl.protocol) {
     case 'git:':
     case 'git+http:':
     case 'git+https:':
     case 'git+rsync:':
     case 'git+ftp:':
     case 'git+file:':
-    case 'git+ssh:': {
+    case 'git+ssh:':
       res.type = 'git'
-      const match = urlparse.protocol === 'git+ssh:' ? matchGitScp(res.rawSpec)
-        : null
-      if (match) {
-        setGitCommittish(res, match.gitCommittish)
-        res.fetchSpec = match.fetchSpec
+      setGitAttrs(res, parsedUrl.hash.slice(1))
+      if (parsedUrl.protocol === 'git+file:' && /^git\+file:\/\/[a-z]:/i.test(rawSpec)) {
+        // URL can't handle drive letters on windows file paths, the host can't contain a :
+        res.fetchSpec = `git+file://${parsedUrl.host.toLowerCase()}:${parsedUrl.pathname}`
       } else {
-        setGitCommittish(res, urlparse.hash != null ? urlparse.hash.slice(1) : '')
-        urlparse.protocol = urlparse.protocol.replace(/^git[+]/, '')
-        if (urlparse.protocol === 'file:' && /^git\+file:\/\/[a-z]:/i.test(res.rawSpec)) {
-          // keep the drive letter : on windows file paths
-          urlparse.host += ':'
-          urlparse.hostname += ':'
-        }
-        delete urlparse.hash
-        res.fetchSpec = url.format(urlparse)
+        parsedUrl.hash = ''
+        res.fetchSpec = parsedUrl.toString()
+      }
+      if (res.fetchSpec.startsWith('git+')) {
+        res.fetchSpec = res.fetchSpec.slice(4)
       }
       break
-    }
     case 'http:':
     case 'https:':
       res.type = 'remote'
@@ -384,7 +364,7 @@ function fromURL (res) {
       break
 
     default:
-      throw unsupportedURLType(urlparse.protocol, res.rawSpec)
+      throw unsupportedURLType(parsedUrl.protocol, rawSpec)
   }
 
   return res
diff --git a/deps/npm/node_modules/npm-package-arg/package.json b/deps/npm/node_modules/npm-package-arg/package.json
index bb9e71b258a939..f7965d5a007c9d 100644
--- a/deps/npm/node_modules/npm-package-arg/package.json
+++ b/deps/npm/node_modules/npm-package-arg/package.json
@@ -1,6 +1,6 @@
 {
   "name": "npm-package-arg",
-  "version": "10.1.0",
+  "version": "11.0.1",
   "description": "Parse the things that can be arguments to `npm install`",
   "main": "./lib/npa.js",
   "directories": {
@@ -11,14 +11,14 @@
     "lib/"
   ],
   "dependencies": {
-    "hosted-git-info": "^6.0.0",
+    "hosted-git-info": "^7.0.0",
     "proc-log": "^3.0.0",
     "semver": "^7.3.5",
     "validate-npm-package-name": "^5.0.0"
   },
   "devDependencies": {
     "@npmcli/eslint-config": "^4.0.0",
-    "@npmcli/template-oss": "4.10.0",
+    "@npmcli/template-oss": "4.18.0",
     "tap": "^16.0.1"
   },
   "scripts": {
@@ -43,7 +43,7 @@
   },
   "homepage": "https://github.com/npm/npm-package-arg",
   "engines": {
-    "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+    "node": "^16.14.0 || >=18.0.0"
   },
   "tap": {
     "branches": 97,
@@ -54,6 +54,14 @@
   },
   "templateOSS": {
     "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
-    "version": "4.10.0"
+    "version": "4.18.0",
+    "publish": true,
+    "ciVersions": [
+      "16.14.0",
+      "16.x",
+      "18.0.0",
+      "18.x"
+    ],
+    "npmSpec": "next-9"
   }
 }
diff --git a/deps/npm/node_modules/npm-packlist/lib/index.js b/deps/npm/node_modules/npm-packlist/lib/index.js
index 887018bd7d424c..7577cba0b865d4 100644
--- a/deps/npm/node_modules/npm-packlist/lib/index.js
+++ b/deps/npm/node_modules/npm-packlist/lib/index.js
@@ -38,13 +38,22 @@ const defaults = [
 ]
 
 const strictDefaults = [
-  // these are forcibly included at all levels
+  // these are forcibly excluded
+  '/.git',
+]
+
+const allLevels = [
+  // these are included by default but can be excluded by package.json files array
   '!/readme{,.*[^~$]}',
   '!/copying{,.*[^~$]}',
   '!/license{,.*[^~$]}',
   '!/licence{,.*[^~$]}',
-  // these are forcibly excluded
-  '/.git',
+]
+
+const rootOnly = [
+  /^!.*readme/i,
+  /^!.*copying/i,
+  /^!.*licen[sc]e/i,
 ]
 
 const normalizePath = (path) => path.split('\\').join('/')
@@ -132,6 +141,7 @@ class PackWalker extends IgnoreWalker {
       // known required files for this directory
       this.injectRules(strictRules, [
         ...strictDefaults,
+        ...allLevels,
         ...this.requiredFiles.map((file) => `!${file}`),
       ])
     }
@@ -284,6 +294,7 @@ class PackWalker extends IgnoreWalker {
     const ignores = []
     const strict = [
       ...strictDefaults,
+      ...allLevels,
       '!/package.json',
       '/.git',
       '/node_modules',
@@ -304,6 +315,9 @@ class PackWalker extends IgnoreWalker {
           file = file.slice(0, -2)
         }
         const inverse = `!${file}`
+
+        this.excludeNonRoot(file)
+
         try {
           // if an entry in the files array is a specific file, then we need to include it as a
           // strict requirement for this package. if it's a directory or a pattern, it's a default
@@ -352,6 +366,20 @@ class PackWalker extends IgnoreWalker {
     this.injectRules(strictRules, strict, callback)
   }
 
+  // excludes non root files by checking if elements from the files array in
+  // package.json contain an ! and readme/license/licence/copying, and then
+  // removing readme/license/licence/copying accordingly from strict defaults
+  excludeNonRoot (file) {
+    // Find the pattern
+    const matchingPattern = rootOnly.find(regex => regex.test(file))
+
+    if (matchingPattern) {
+      // Find which index matches the pattern and remove it from allLevels
+      const indexToRemove = allLevels.findIndex(element => matchingPattern.test(element))
+      allLevels.splice(indexToRemove, 1)
+    }
+  }
+
   // custom method: after we've finished gathering the files for the root package, we call this
   // before emitting the 'done' event in order to gather all of the files for bundled deps
   async gatherBundles () {
diff --git a/deps/npm/node_modules/npm-packlist/package.json b/deps/npm/node_modules/npm-packlist/package.json
index 6023ad34df3b42..460ca7e30ad23f 100644
--- a/deps/npm/node_modules/npm-packlist/package.json
+++ b/deps/npm/node_modules/npm-packlist/package.json
@@ -1,6 +1,6 @@
 {
   "name": "npm-packlist",
-  "version": "7.0.4",
+  "version": "8.0.0",
   "description": "Get a list of the files to add from a folder into an npm package",
   "directories": {
     "test": "test"
@@ -18,7 +18,7 @@
   "devDependencies": {
     "@npmcli/arborist": "^6.0.0 || ^6.0.0-pre.0",
     "@npmcli/eslint-config": "^4.0.0",
-    "@npmcli/template-oss": "4.10.0",
+    "@npmcli/template-oss": "4.18.0",
     "mutate-fs": "^2.1.1",
     "tap": "^16.0.1"
   },
@@ -55,6 +55,7 @@
   },
   "templateOSS": {
     "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
-    "version": "4.10.0"
+    "version": "4.18.0",
+    "publish": true
   }
 }
diff --git a/deps/npm/node_modules/npm-pick-manifest/lib/index.js b/deps/npm/node_modules/npm-pick-manifest/lib/index.js
index f2934e9ca1822a..8dbd2721c89963 100644
--- a/deps/npm/node_modules/npm-pick-manifest/lib/index.js
+++ b/deps/npm/node_modules/npm-pick-manifest/lib/index.js
@@ -210,7 +210,7 @@ module.exports = (packument, wanted, opts = {}) => {
     code,
     type: npa.resolve(packument.name, wanted).type,
     wanted,
-    versions: Object.keys(packument.versions),
+    versions: Object.keys(packument.versions ?? {}),
     name,
     distTags: packument['dist-tags'],
     defaultTag,
diff --git a/deps/npm/node_modules/npm-pick-manifest/package.json b/deps/npm/node_modules/npm-pick-manifest/package.json
index 89ff8966f1a39b..e30c2cfe341fc6 100644
--- a/deps/npm/node_modules/npm-pick-manifest/package.json
+++ b/deps/npm/node_modules/npm-pick-manifest/package.json
@@ -1,6 +1,6 @@
 {
   "name": "npm-pick-manifest",
-  "version": "8.0.1",
+  "version": "9.0.0",
   "description": "Resolves a matching manifest from a package metadata document according to standard npm semver resolution rules.",
   "main": "./lib",
   "files": [
@@ -31,12 +31,12 @@
   "dependencies": {
     "npm-install-checks": "^6.0.0",
     "npm-normalize-package-bin": "^3.0.0",
-    "npm-package-arg": "^10.0.0",
+    "npm-package-arg": "^11.0.0",
     "semver": "^7.3.5"
   },
   "devDependencies": {
     "@npmcli/eslint-config": "^4.0.0",
-    "@npmcli/template-oss": "4.6.1",
+    "@npmcli/template-oss": "4.18.0",
     "tap": "^16.0.1"
   },
   "tap": {
@@ -47,10 +47,17 @@
     ]
   },
   "engines": {
-    "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+    "node": "^16.14.0 || >=18.0.0"
   },
   "templateOSS": {
     "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
-    "version": "4.6.1"
+    "version": "4.18.0",
+    "publish": true,
+    "ciVersions": [
+      "16.14.0",
+      "16.x",
+      "18.0.0",
+      "18.x"
+    ]
   }
 }
diff --git a/deps/npm/node_modules/npm-profile/package.json b/deps/npm/node_modules/npm-profile/package.json
index 9c0b77b8a6dd5d..af57e9e73509c3 100644
--- a/deps/npm/node_modules/npm-profile/package.json
+++ b/deps/npm/node_modules/npm-profile/package.json
@@ -1,12 +1,12 @@
 {
   "name": "npm-profile",
-  "version": "7.0.1",
+  "version": "9.0.0",
   "description": "Library for updating an npmjs.com profile",
   "keywords": [],
   "author": "GitHub Inc.",
   "license": "ISC",
   "dependencies": {
-    "npm-registry-fetch": "^14.0.0",
+    "npm-registry-fetch": "^16.0.0",
     "proc-log": "^3.0.0"
   },
   "main": "./lib/index.js",
@@ -20,7 +20,7 @@
   ],
   "devDependencies": {
     "@npmcli/eslint-config": "^4.0.0",
-    "@npmcli/template-oss": "4.5.1",
+    "@npmcli/template-oss": "4.18.0",
     "nock": "^13.2.4",
     "tap": "^16.0.1"
   },
@@ -41,10 +41,17 @@
     ]
   },
   "engines": {
-    "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+    "node": "^16.14.0 || >=18.0.0"
   },
   "templateOSS": {
     "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
-    "version": "4.5.1"
+    "version": "4.18.0",
+    "ciVersions": [
+      "16.14.0",
+      "16.x",
+      "18.0.0",
+      "18.x"
+    ],
+    "publish": true
   }
 }
diff --git a/deps/npm/node_modules/npm-registry-fetch/lib/auth.js b/deps/npm/node_modules/npm-registry-fetch/lib/auth.js
index 870ce0d923cd0f..9270025fa8d902 100644
--- a/deps/npm/node_modules/npm-registry-fetch/lib/auth.js
+++ b/deps/npm/node_modules/npm-registry-fetch/lib/auth.js
@@ -4,8 +4,8 @@ const npa = require('npm-package-arg')
 const { URL } = require('url')
 
 // Find the longest registry key that is used for some kind of auth
-// in the options.
-const regKeyFromURI = (uri, opts) => {
+// in the options.  Returns the registry key and the auth config.
+const regFromURI = (uri, opts) => {
   const parsed = new URL(uri)
   // try to find a config key indicating we have auth for this registry
   // can be one of :_authToken, :_auth, :_password and :username, or
@@ -14,23 +14,40 @@ const regKeyFromURI = (uri, opts) => {
   // stopping when we reach '//'.
   let regKey = `//${parsed.host}${parsed.pathname}`
   while (regKey.length > '//'.length) {
+    const authKey = hasAuth(regKey, opts)
     // got some auth for this URI
-    if (hasAuth(regKey, opts)) {
-      return regKey
+    if (authKey) {
+      return { regKey, authKey }
     }
 
     // can be either //host/some/path/:_auth or //host/some/path:_auth
     // walk up by removing EITHER what's after the slash OR the slash itself
     regKey = regKey.replace(/([^/]+|\/)$/, '')
   }
+  return { regKey: false, authKey: null }
 }
 
-const hasAuth = (regKey, opts) => (
-  opts[`${regKey}:_authToken`] ||
-  opts[`${regKey}:_auth`] ||
-  opts[`${regKey}:username`] && opts[`${regKey}:_password`] ||
-  opts[`${regKey}:certfile`] && opts[`${regKey}:keyfile`]
-)
+// Not only do we want to know if there is auth, but if we are calling `npm
+// logout` we want to know what config value specifically provided it.  This is
+// so we can look up where the config came from to delete it (i.e. user vs
+// project)
+const hasAuth = (regKey, opts) => {
+  if (opts[`${regKey}:_authToken`]) {
+    return '_authToken'
+  }
+  if (opts[`${regKey}:_auth`]) {
+    return '_auth'
+  }
+  if (opts[`${regKey}:username`] && opts[`${regKey}:_password`]) {
+    // 'password' can be inferred to also be present
+    return 'username'
+  }
+  if (opts[`${regKey}:certfile`] && opts[`${regKey}:keyfile`]) {
+    // 'keyfile' can be inferred to also be present
+    return 'certfile'
+  }
+  return false
+}
 
 const sameHost = (a, b) => {
   const parsedA = new URL(a)
@@ -63,11 +80,14 @@ const getAuth = (uri, opts = {}) => {
   if (!uri) {
     throw new Error('URI is required')
   }
-  const regKey = regKeyFromURI(uri, forceAuth || opts)
+  const { regKey, authKey } = regFromURI(uri, forceAuth || opts)
 
   // we are only allowed to use what's in forceAuth if specified
   if (forceAuth && !regKey) {
     return new Auth({
+      // if we force auth we don't want to refer back to anything in config
+      regKey: false,
+      authKey: null,
       scopeAuthKey: null,
       token: forceAuth._authToken || forceAuth.token,
       username: forceAuth.username,
@@ -88,8 +108,8 @@ const getAuth = (uri, opts = {}) => {
       // registry where we logged in, but the same auth SHOULD be sent
       // to that artifact host, then we track where it was coming in from,
       // and warn the user if we get a 4xx error on it.
-      const scopeAuthKey = regKeyFromURI(registry, opts)
-      return new Auth({ scopeAuthKey })
+      const { regKey: scopeAuthKey, authKey: _authKey } = regFromURI(registry, opts)
+      return new Auth({ scopeAuthKey, regKey: scopeAuthKey, authKey: _authKey })
     }
   }
 
@@ -104,6 +124,8 @@ const getAuth = (uri, opts = {}) => {
 
   return new Auth({
     scopeAuthKey: null,
+    regKey,
+    authKey,
     token,
     auth,
     username,
@@ -114,8 +136,22 @@ const getAuth = (uri, opts = {}) => {
 }
 
 class Auth {
-  constructor ({ token, auth, username, password, scopeAuthKey, certfile, keyfile }) {
+  constructor ({
+    token,
+    auth,
+    username,
+    password,
+    scopeAuthKey,
+    certfile,
+    keyfile,
+    regKey,
+    authKey,
+  }) {
+    // same as regKey but only present for scoped auth. Should have been named scopeRegKey
     this.scopeAuthKey = scopeAuthKey
+    // `${regKey}:${authKey}` will get you back to the auth config that gave us auth
+    this.regKey = regKey
+    this.authKey = authKey
     this.token = null
     this.auth = null
     this.isBasicAuth = false
diff --git a/deps/npm/node_modules/npm-registry-fetch/lib/index.js b/deps/npm/node_modules/npm-registry-fetch/lib/index.js
index 23e349c5c5b96d..bb413f862d92d0 100644
--- a/deps/npm/node_modules/npm-registry-fetch/lib/index.js
+++ b/deps/npm/node_modules/npm-registry-fetch/lib/index.js
@@ -166,6 +166,8 @@ function regFetch (uri, /* istanbul ignore next */ opts_ = {}) {
   return Promise.resolve(body).then(doFetch)
 }
 
+module.exports.getAuth = getAuth
+
 module.exports.json = fetchJSON
 function fetchJSON (uri, opts) {
   return regFetch(uri, opts).then(res => res.json())
diff --git a/deps/npm/node_modules/npm-registry-fetch/package.json b/deps/npm/node_modules/npm-registry-fetch/package.json
index 63a44725886ccf..b715d52391a933 100644
--- a/deps/npm/node_modules/npm-registry-fetch/package.json
+++ b/deps/npm/node_modules/npm-registry-fetch/package.json
@@ -1,6 +1,6 @@
 {
   "name": "npm-registry-fetch",
-  "version": "14.0.5",
+  "version": "16.1.0",
   "description": "Fetch-based http client for use with npm registry APIs",
   "main": "lib",
   "files": [
@@ -31,18 +31,18 @@
   "author": "GitHub Inc.",
   "license": "ISC",
   "dependencies": {
-    "make-fetch-happen": "^11.0.0",
-    "minipass": "^5.0.0",
+    "make-fetch-happen": "^13.0.0",
+    "minipass": "^7.0.2",
     "minipass-fetch": "^3.0.0",
     "minipass-json-stream": "^1.0.1",
     "minizlib": "^2.1.2",
-    "npm-package-arg": "^10.0.0",
+    "npm-package-arg": "^11.0.0",
     "proc-log": "^3.0.0"
   },
   "devDependencies": {
     "@npmcli/eslint-config": "^4.0.0",
-    "@npmcli/template-oss": "4.14.1",
-    "cacache": "^17.0.0",
+    "@npmcli/template-oss": "4.19.0",
+    "cacache": "^18.0.0",
     "nock": "^13.2.4",
     "require-inject": "^1.4.4",
     "ssri": "^10.0.0",
@@ -57,11 +57,11 @@
     ]
   },
   "engines": {
-    "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+    "node": "^16.14.0 || >=18.0.0"
   },
   "templateOSS": {
     "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
-    "version": "4.14.1",
+    "version": "4.19.0",
     "publish": "true"
   }
 }
diff --git a/deps/npm/node_modules/once/LICENSE b/deps/npm/node_modules/once/LICENSE
deleted file mode 100644
index 19129e315fe593..00000000000000
--- a/deps/npm/node_modules/once/LICENSE
+++ /dev/null
@@ -1,15 +0,0 @@
-The ISC License
-
-Copyright (c) Isaac Z. Schlueter and Contributors
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/deps/npm/node_modules/once/once.js b/deps/npm/node_modules/once/once.js
deleted file mode 100644
index 235406736d9d94..00000000000000
--- a/deps/npm/node_modules/once/once.js
+++ /dev/null
@@ -1,42 +0,0 @@
-var wrappy = require('wrappy')
-module.exports = wrappy(once)
-module.exports.strict = wrappy(onceStrict)
-
-once.proto = once(function () {
-  Object.defineProperty(Function.prototype, 'once', {
-    value: function () {
-      return once(this)
-    },
-    configurable: true
-  })
-
-  Object.defineProperty(Function.prototype, 'onceStrict', {
-    value: function () {
-      return onceStrict(this)
-    },
-    configurable: true
-  })
-})
-
-function once (fn) {
-  var f = function () {
-    if (f.called) return f.value
-    f.called = true
-    return f.value = fn.apply(this, arguments)
-  }
-  f.called = false
-  return f
-}
-
-function onceStrict (fn) {
-  var f = function () {
-    if (f.called)
-      throw new Error(f.onceError)
-    f.called = true
-    return f.value = fn.apply(this, arguments)
-  }
-  var name = fn.name || 'Function wrapped with `once`'
-  f.onceError = name + " shouldn't be called more than once"
-  f.called = false
-  return f
-}
diff --git a/deps/npm/node_modules/once/package.json b/deps/npm/node_modules/once/package.json
deleted file mode 100644
index 16815b2fa11193..00000000000000
--- a/deps/npm/node_modules/once/package.json
+++ /dev/null
@@ -1,33 +0,0 @@
-{
-  "name": "once",
-  "version": "1.4.0",
-  "description": "Run a function exactly one time",
-  "main": "once.js",
-  "directories": {
-    "test": "test"
-  },
-  "dependencies": {
-    "wrappy": "1"
-  },
-  "devDependencies": {
-    "tap": "^7.0.1"
-  },
-  "scripts": {
-    "test": "tap test/*.js"
-  },
-  "files": [
-    "once.js"
-  ],
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/once"
-  },
-  "keywords": [
-    "once",
-    "function",
-    "one",
-    "single"
-  ],
-  "author": "Isaac Z. Schlueter  (http://blog.izs.me/)",
-  "license": "ISC"
-}
diff --git a/deps/npm/node_modules/pacote/lib/registry.js b/deps/npm/node_modules/pacote/lib/registry.js
index 34d9b2b87f3f3d..993fd3f08a6d91 100644
--- a/deps/npm/node_modules/pacote/lib/registry.js
+++ b/deps/npm/node_modules/pacote/lib/registry.js
@@ -8,7 +8,7 @@ const pickManifest = require('npm-pick-manifest')
 const ssri = require('ssri')
 const crypto = require('crypto')
 const npa = require('npm-package-arg')
-const { sigstore } = require('sigstore')
+const sigstore = require('sigstore')
 
 // Corgis are cute. 🐕🐶
 const corgiDoc = 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*'
@@ -299,7 +299,7 @@ class RegistryFetcher extends Fetcher {
                 tufCachePath: this.tufCache,
                 keySelector: publicKey ? () => publicKey.pemkey : undefined,
               }
-              await sigstore.verify(bundle, null, options)
+              await sigstore.verify(bundle, options)
             } catch (e) {
               throw Object.assign(new Error(
                 `${mani._id} failed to verify attestation: ${e.message}`
diff --git a/deps/npm/node_modules/pacote/package.json b/deps/npm/node_modules/pacote/package.json
index bc8d984704af5b..4654b03d988c32 100644
--- a/deps/npm/node_modules/pacote/package.json
+++ b/deps/npm/node_modules/pacote/package.json
@@ -1,6 +1,6 @@
 {
   "name": "pacote",
-  "version": "15.2.0",
+  "version": "17.0.4",
   "description": "JavaScript package downloader",
   "author": "GitHub Inc.",
   "bin": {
@@ -27,8 +27,8 @@
   "devDependencies": {
     "@npmcli/arborist": "^6.0.0 || ^6.0.0-pre.0",
     "@npmcli/eslint-config": "^4.0.0",
-    "@npmcli/template-oss": "4.14.1",
-    "hosted-git-info": "^6.0.0",
+    "@npmcli/template-oss": "4.18.0",
+    "hosted-git-info": "^7.0.0",
     "mutate-fs": "^2.1.1",
     "nock": "^13.2.4",
     "npm-registry-mock": "^1.3.2",
@@ -44,27 +44,27 @@
     "git"
   ],
   "dependencies": {
-    "@npmcli/git": "^4.0.0",
+    "@npmcli/git": "^5.0.0",
     "@npmcli/installed-package-contents": "^2.0.1",
-    "@npmcli/promise-spawn": "^6.0.1",
-    "@npmcli/run-script": "^6.0.0",
-    "cacache": "^17.0.0",
+    "@npmcli/promise-spawn": "^7.0.0",
+    "@npmcli/run-script": "^7.0.0",
+    "cacache": "^18.0.0",
     "fs-minipass": "^3.0.0",
-    "minipass": "^5.0.0",
-    "npm-package-arg": "^10.0.0",
-    "npm-packlist": "^7.0.0",
-    "npm-pick-manifest": "^8.0.0",
-    "npm-registry-fetch": "^14.0.0",
+    "minipass": "^7.0.2",
+    "npm-package-arg": "^11.0.0",
+    "npm-packlist": "^8.0.0",
+    "npm-pick-manifest": "^9.0.0",
+    "npm-registry-fetch": "^16.0.0",
     "proc-log": "^3.0.0",
     "promise-retry": "^2.0.1",
-    "read-package-json": "^6.0.0",
+    "read-package-json": "^7.0.0",
     "read-package-json-fast": "^3.0.0",
-    "sigstore": "^1.3.0",
+    "sigstore": "^2.0.0",
     "ssri": "^10.0.0",
     "tar": "^6.1.11"
   },
   "engines": {
-    "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+    "node": "^16.14.0 || >=18.0.0"
   },
   "repository": {
     "type": "git",
@@ -72,7 +72,13 @@
   },
   "templateOSS": {
     "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
-    "version": "4.14.1",
+    "ciVersions": [
+      "16.14.0",
+      "16.x",
+      "18.0.0",
+      "18.x"
+    ],
+    "version": "4.18.0",
     "windowsCI": false,
     "publish": "true"
   }
diff --git a/deps/npm/node_modules/path-is-absolute/index.js b/deps/npm/node_modules/path-is-absolute/index.js
deleted file mode 100644
index 22aa6c35607997..00000000000000
--- a/deps/npm/node_modules/path-is-absolute/index.js
+++ /dev/null
@@ -1,20 +0,0 @@
-'use strict';
-
-function posix(path) {
-	return path.charAt(0) === '/';
-}
-
-function win32(path) {
-	// https://github.com/nodejs/node/blob/b3fcc245fb25539909ef1d5eaa01dbf92e168633/lib/path.js#L56
-	var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/;
-	var result = splitDeviceRe.exec(path);
-	var device = result[1] || '';
-	var isUnc = Boolean(device && device.charAt(1) !== ':');
-
-	// UNC paths are always absolute
-	return Boolean(result[2] || isUnc);
-}
-
-module.exports = process.platform === 'win32' ? win32 : posix;
-module.exports.posix = posix;
-module.exports.win32 = win32;
diff --git a/deps/npm/node_modules/path-is-absolute/package.json b/deps/npm/node_modules/path-is-absolute/package.json
deleted file mode 100644
index 91196d5e9c1336..00000000000000
--- a/deps/npm/node_modules/path-is-absolute/package.json
+++ /dev/null
@@ -1,43 +0,0 @@
-{
-  "name": "path-is-absolute",
-  "version": "1.0.1",
-  "description": "Node.js 0.12 path.isAbsolute() ponyfill",
-  "license": "MIT",
-  "repository": "sindresorhus/path-is-absolute",
-  "author": {
-    "name": "Sindre Sorhus",
-    "email": "sindresorhus@gmail.com",
-    "url": "sindresorhus.com"
-  },
-  "engines": {
-    "node": ">=0.10.0"
-  },
-  "scripts": {
-    "test": "xo && node test.js"
-  },
-  "files": [
-    "index.js"
-  ],
-  "keywords": [
-    "path",
-    "paths",
-    "file",
-    "dir",
-    "absolute",
-    "isabsolute",
-    "is-absolute",
-    "built-in",
-    "util",
-    "utils",
-    "core",
-    "ponyfill",
-    "polyfill",
-    "shim",
-    "is",
-    "detect",
-    "check"
-  ],
-  "devDependencies": {
-    "xo": "^0.16.0"
-  }
-}
diff --git a/deps/npm/node_modules/path-scurry/dist/cjs/index.js b/deps/npm/node_modules/path-scurry/dist/cjs/index.js
index 8044c7e581d2e4..23eb5b0853ff28 100644
--- a/deps/npm/node_modules/path-scurry/dist/cjs/index.js
+++ b/deps/npm/node_modules/path-scurry/dist/cjs/index.js
@@ -521,6 +521,29 @@ class PathBase {
     isUnknown() {
         return (this.#type & IFMT) === UNKNOWN;
     }
+    isType(type) {
+        return this[`is${type}`]();
+    }
+    getType() {
+        return this.isUnknown()
+            ? 'Unknown'
+            : this.isDirectory()
+                ? 'Directory'
+                : this.isFile()
+                    ? 'File'
+                    : this.isSymbolicLink()
+                        ? 'SymbolicLink'
+                        : this.isFIFO()
+                            ? 'FIFO'
+                            : this.isCharacterDevice()
+                                ? 'CharacterDevice'
+                                : this.isBlockDevice()
+                                    ? 'BlockDevice'
+                                    : /* c8 ignore start */ this.isSocket()
+                                        ? 'Socket'
+                                        : 'Unknown';
+        /* c8 ignore stop */
+    }
     /**
      * Is the Path a regular file?
      */
diff --git a/deps/npm/node_modules/path-scurry/dist/mjs/index.js b/deps/npm/node_modules/path-scurry/dist/mjs/index.js
index 957f087c865147..079253a6aee967 100644
--- a/deps/npm/node_modules/path-scurry/dist/mjs/index.js
+++ b/deps/npm/node_modules/path-scurry/dist/mjs/index.js
@@ -493,6 +493,29 @@ export class PathBase {
     isUnknown() {
         return (this.#type & IFMT) === UNKNOWN;
     }
+    isType(type) {
+        return this[`is${type}`]();
+    }
+    getType() {
+        return this.isUnknown()
+            ? 'Unknown'
+            : this.isDirectory()
+                ? 'Directory'
+                : this.isFile()
+                    ? 'File'
+                    : this.isSymbolicLink()
+                        ? 'SymbolicLink'
+                        : this.isFIFO()
+                            ? 'FIFO'
+                            : this.isCharacterDevice()
+                                ? 'CharacterDevice'
+                                : this.isBlockDevice()
+                                    ? 'BlockDevice'
+                                    : /* c8 ignore start */ this.isSocket()
+                                        ? 'Socket'
+                                        : 'Unknown';
+        /* c8 ignore stop */
+    }
     /**
      * Is the Path a regular file?
      */
diff --git a/deps/npm/node_modules/path-scurry/node_modules/lru-cache/LICENSE b/deps/npm/node_modules/path-scurry/node_modules/lru-cache/LICENSE
deleted file mode 100644
index f785757cd63f86..00000000000000
--- a/deps/npm/node_modules/path-scurry/node_modules/lru-cache/LICENSE
+++ /dev/null
@@ -1,15 +0,0 @@
-The ISC License
-
-Copyright (c) 2010-2023 Isaac Z. Schlueter and Contributors
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/deps/npm/node_modules/path-scurry/node_modules/lru-cache/dist/cjs/index.js b/deps/npm/node_modules/path-scurry/node_modules/lru-cache/dist/cjs/index.js
deleted file mode 100644
index e6c4f909292b3f..00000000000000
--- a/deps/npm/node_modules/path-scurry/node_modules/lru-cache/dist/cjs/index.js
+++ /dev/null
@@ -1,1395 +0,0 @@
-"use strict";
-/**
- * @module LRUCache
- */
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.LRUCache = void 0;
-const perf = typeof performance === 'object' &&
-    performance &&
-    typeof performance.now === 'function'
-    ? performance
-    : Date;
-const warned = new Set();
-/* c8 ignore start */
-const PROCESS = (typeof process === 'object' && !!process ? process : {});
-/* c8 ignore start */
-const emitWarning = (msg, type, code, fn) => {
-    typeof PROCESS.emitWarning === 'function'
-        ? PROCESS.emitWarning(msg, type, code, fn)
-        : console.error(`[${code}] ${type}: ${msg}`);
-};
-let AC = globalThis.AbortController;
-let AS = globalThis.AbortSignal;
-/* c8 ignore start */
-if (typeof AC === 'undefined') {
-    //@ts-ignore
-    AS = class AbortSignal {
-        onabort;
-        _onabort = [];
-        reason;
-        aborted = false;
-        addEventListener(_, fn) {
-            this._onabort.push(fn);
-        }
-    };
-    //@ts-ignore
-    AC = class AbortController {
-        constructor() {
-            warnACPolyfill();
-        }
-        signal = new AS();
-        abort(reason) {
-            if (this.signal.aborted)
-                return;
-            //@ts-ignore
-            this.signal.reason = reason;
-            //@ts-ignore
-            this.signal.aborted = true;
-            //@ts-ignore
-            for (const fn of this.signal._onabort) {
-                fn(reason);
-            }
-            this.signal.onabort?.(reason);
-        }
-    };
-    let printACPolyfillWarning = PROCESS.env?.LRU_CACHE_IGNORE_AC_WARNING !== '1';
-    const warnACPolyfill = () => {
-        if (!printACPolyfillWarning)
-            return;
-        printACPolyfillWarning = false;
-        emitWarning('AbortController is not defined. If using lru-cache in ' +
-            'node 14, load an AbortController polyfill from the ' +
-            '`node-abort-controller` package. A minimal polyfill is ' +
-            'provided for use by LRUCache.fetch(), but it should not be ' +
-            'relied upon in other contexts (eg, passing it to other APIs that ' +
-            'use AbortController/AbortSignal might have undesirable effects). ' +
-            'You may disable this with LRU_CACHE_IGNORE_AC_WARNING=1 in the env.', 'NO_ABORT_CONTROLLER', 'ENOTSUP', warnACPolyfill);
-    };
-}
-/* c8 ignore stop */
-const shouldWarn = (code) => !warned.has(code);
-const TYPE = Symbol('type');
-const isPosInt = (n) => n && n === Math.floor(n) && n > 0 && isFinite(n);
-/* c8 ignore start */
-// This is a little bit ridiculous, tbh.
-// The maximum array length is 2^32-1 or thereabouts on most JS impls.
-// And well before that point, you're caching the entire world, I mean,
-// that's ~32GB of just integers for the next/prev links, plus whatever
-// else to hold that many keys and values.  Just filling the memory with
-// zeroes at init time is brutal when you get that big.
-// But why not be complete?
-// Maybe in the future, these limits will have expanded.
-const getUintArray = (max) => !isPosInt(max)
-    ? null
-    : max <= Math.pow(2, 8)
-        ? Uint8Array
-        : max <= Math.pow(2, 16)
-            ? Uint16Array
-            : max <= Math.pow(2, 32)
-                ? Uint32Array
-                : max <= Number.MAX_SAFE_INTEGER
-                    ? ZeroArray
-                    : null;
-/* c8 ignore stop */
-class ZeroArray extends Array {
-    constructor(size) {
-        super(size);
-        this.fill(0);
-    }
-}
-class Stack {
-    heap;
-    length;
-    // private constructor
-    static #constructing = false;
-    static create(max) {
-        const HeapCls = getUintArray(max);
-        if (!HeapCls)
-            return [];
-        Stack.#constructing = true;
-        const s = new Stack(max, HeapCls);
-        Stack.#constructing = false;
-        return s;
-    }
-    constructor(max, HeapCls) {
-        /* c8 ignore start */
-        if (!Stack.#constructing) {
-            throw new TypeError('instantiate Stack using Stack.create(n)');
-        }
-        /* c8 ignore stop */
-        this.heap = new HeapCls(max);
-        this.length = 0;
-    }
-    push(n) {
-        this.heap[this.length++] = n;
-    }
-    pop() {
-        return this.heap[--this.length];
-    }
-}
-/**
- * Default export, the thing you're using this module to get.
- *
- * All properties from the options object (with the exception of
- * {@link OptionsBase.max} and {@link OptionsBase.maxSize}) are added as
- * normal public members. (`max` and `maxBase` are read-only getters.)
- * Changing any of these will alter the defaults for subsequent method calls,
- * but is otherwise safe.
- */
-class LRUCache {
-    // properties coming in from the options of these, only max and maxSize
-    // really *need* to be protected. The rest can be modified, as they just
-    // set defaults for various methods.
-    #max;
-    #maxSize;
-    #dispose;
-    #disposeAfter;
-    #fetchMethod;
-    /**
-     * {@link LRUCache.OptionsBase.ttl}
-     */
-    ttl;
-    /**
-     * {@link LRUCache.OptionsBase.ttlResolution}
-     */
-    ttlResolution;
-    /**
-     * {@link LRUCache.OptionsBase.ttlAutopurge}
-     */
-    ttlAutopurge;
-    /**
-     * {@link LRUCache.OptionsBase.updateAgeOnGet}
-     */
-    updateAgeOnGet;
-    /**
-     * {@link LRUCache.OptionsBase.updateAgeOnHas}
-     */
-    updateAgeOnHas;
-    /**
-     * {@link LRUCache.OptionsBase.allowStale}
-     */
-    allowStale;
-    /**
-     * {@link LRUCache.OptionsBase.noDisposeOnSet}
-     */
-    noDisposeOnSet;
-    /**
-     * {@link LRUCache.OptionsBase.noUpdateTTL}
-     */
-    noUpdateTTL;
-    /**
-     * {@link LRUCache.OptionsBase.maxEntrySize}
-     */
-    maxEntrySize;
-    /**
-     * {@link LRUCache.OptionsBase.sizeCalculation}
-     */
-    sizeCalculation;
-    /**
-     * {@link LRUCache.OptionsBase.noDeleteOnFetchRejection}
-     */
-    noDeleteOnFetchRejection;
-    /**
-     * {@link LRUCache.OptionsBase.noDeleteOnStaleGet}
-     */
-    noDeleteOnStaleGet;
-    /**
-     * {@link LRUCache.OptionsBase.allowStaleOnFetchAbort}
-     */
-    allowStaleOnFetchAbort;
-    /**
-     * {@link LRUCache.OptionsBase.allowStaleOnFetchRejection}
-     */
-    allowStaleOnFetchRejection;
-    /**
-     * {@link LRUCache.OptionsBase.ignoreFetchAbort}
-     */
-    ignoreFetchAbort;
-    // computed properties
-    #size;
-    #calculatedSize;
-    #keyMap;
-    #keyList;
-    #valList;
-    #next;
-    #prev;
-    #head;
-    #tail;
-    #free;
-    #disposed;
-    #sizes;
-    #starts;
-    #ttls;
-    #hasDispose;
-    #hasFetchMethod;
-    #hasDisposeAfter;
-    /**
-     * Do not call this method unless you need to inspect the
-     * inner workings of the cache.  If anything returned by this
-     * object is modified in any way, strange breakage may occur.
-     *
-     * These fields are private for a reason!
-     *
-     * @internal
-     */
-    static unsafeExposeInternals(c) {
-        return {
-            // properties
-            starts: c.#starts,
-            ttls: c.#ttls,
-            sizes: c.#sizes,
-            keyMap: c.#keyMap,
-            keyList: c.#keyList,
-            valList: c.#valList,
-            next: c.#next,
-            prev: c.#prev,
-            get head() {
-                return c.#head;
-            },
-            get tail() {
-                return c.#tail;
-            },
-            free: c.#free,
-            // methods
-            isBackgroundFetch: (p) => c.#isBackgroundFetch(p),
-            backgroundFetch: (k, index, options, context) => c.#backgroundFetch(k, index, options, context),
-            moveToTail: (index) => c.#moveToTail(index),
-            indexes: (options) => c.#indexes(options),
-            rindexes: (options) => c.#rindexes(options),
-            isStale: (index) => c.#isStale(index),
-        };
-    }
-    // Protected read-only members
-    /**
-     * {@link LRUCache.OptionsBase.max} (read-only)
-     */
-    get max() {
-        return this.#max;
-    }
-    /**
-     * {@link LRUCache.OptionsBase.maxSize} (read-only)
-     */
-    get maxSize() {
-        return this.#maxSize;
-    }
-    /**
-     * The total computed size of items in the cache (read-only)
-     */
-    get calculatedSize() {
-        return this.#calculatedSize;
-    }
-    /**
-     * The number of items stored in the cache (read-only)
-     */
-    get size() {
-        return this.#size;
-    }
-    /**
-     * {@link LRUCache.OptionsBase.fetchMethod} (read-only)
-     */
-    get fetchMethod() {
-        return this.#fetchMethod;
-    }
-    /**
-     * {@link LRUCache.OptionsBase.dispose} (read-only)
-     */
-    get dispose() {
-        return this.#dispose;
-    }
-    /**
-     * {@link LRUCache.OptionsBase.disposeAfter} (read-only)
-     */
-    get disposeAfter() {
-        return this.#disposeAfter;
-    }
-    constructor(options) {
-        const { max = 0, ttl, ttlResolution = 1, ttlAutopurge, updateAgeOnGet, updateAgeOnHas, allowStale, dispose, disposeAfter, noDisposeOnSet, noUpdateTTL, maxSize = 0, maxEntrySize = 0, sizeCalculation, fetchMethod, noDeleteOnFetchRejection, noDeleteOnStaleGet, allowStaleOnFetchRejection, allowStaleOnFetchAbort, ignoreFetchAbort, } = options;
-        if (max !== 0 && !isPosInt(max)) {
-            throw new TypeError('max option must be a nonnegative integer');
-        }
-        const UintArray = max ? getUintArray(max) : Array;
-        if (!UintArray) {
-            throw new Error('invalid max value: ' + max);
-        }
-        this.#max = max;
-        this.#maxSize = maxSize;
-        this.maxEntrySize = maxEntrySize || this.#maxSize;
-        this.sizeCalculation = sizeCalculation;
-        if (this.sizeCalculation) {
-            if (!this.#maxSize && !this.maxEntrySize) {
-                throw new TypeError('cannot set sizeCalculation without setting maxSize or maxEntrySize');
-            }
-            if (typeof this.sizeCalculation !== 'function') {
-                throw new TypeError('sizeCalculation set to non-function');
-            }
-        }
-        if (fetchMethod !== undefined &&
-            typeof fetchMethod !== 'function') {
-            throw new TypeError('fetchMethod must be a function if specified');
-        }
-        this.#fetchMethod = fetchMethod;
-        this.#hasFetchMethod = !!fetchMethod;
-        this.#keyMap = new Map();
-        this.#keyList = new Array(max).fill(undefined);
-        this.#valList = new Array(max).fill(undefined);
-        this.#next = new UintArray(max);
-        this.#prev = new UintArray(max);
-        this.#head = 0;
-        this.#tail = 0;
-        this.#free = Stack.create(max);
-        this.#size = 0;
-        this.#calculatedSize = 0;
-        if (typeof dispose === 'function') {
-            this.#dispose = dispose;
-        }
-        if (typeof disposeAfter === 'function') {
-            this.#disposeAfter = disposeAfter;
-            this.#disposed = [];
-        }
-        else {
-            this.#disposeAfter = undefined;
-            this.#disposed = undefined;
-        }
-        this.#hasDispose = !!this.#dispose;
-        this.#hasDisposeAfter = !!this.#disposeAfter;
-        this.noDisposeOnSet = !!noDisposeOnSet;
-        this.noUpdateTTL = !!noUpdateTTL;
-        this.noDeleteOnFetchRejection = !!noDeleteOnFetchRejection;
-        this.allowStaleOnFetchRejection = !!allowStaleOnFetchRejection;
-        this.allowStaleOnFetchAbort = !!allowStaleOnFetchAbort;
-        this.ignoreFetchAbort = !!ignoreFetchAbort;
-        // NB: maxEntrySize is set to maxSize if it's set
-        if (this.maxEntrySize !== 0) {
-            if (this.#maxSize !== 0) {
-                if (!isPosInt(this.#maxSize)) {
-                    throw new TypeError('maxSize must be a positive integer if specified');
-                }
-            }
-            if (!isPosInt(this.maxEntrySize)) {
-                throw new TypeError('maxEntrySize must be a positive integer if specified');
-            }
-            this.#initializeSizeTracking();
-        }
-        this.allowStale = !!allowStale;
-        this.noDeleteOnStaleGet = !!noDeleteOnStaleGet;
-        this.updateAgeOnGet = !!updateAgeOnGet;
-        this.updateAgeOnHas = !!updateAgeOnHas;
-        this.ttlResolution =
-            isPosInt(ttlResolution) || ttlResolution === 0
-                ? ttlResolution
-                : 1;
-        this.ttlAutopurge = !!ttlAutopurge;
-        this.ttl = ttl || 0;
-        if (this.ttl) {
-            if (!isPosInt(this.ttl)) {
-                throw new TypeError('ttl must be a positive integer if specified');
-            }
-            this.#initializeTTLTracking();
-        }
-        // do not allow completely unbounded caches
-        if (this.#max === 0 && this.ttl === 0 && this.#maxSize === 0) {
-            throw new TypeError('At least one of max, maxSize, or ttl is required');
-        }
-        if (!this.ttlAutopurge && !this.#max && !this.#maxSize) {
-            const code = 'LRU_CACHE_UNBOUNDED';
-            if (shouldWarn(code)) {
-                warned.add(code);
-                const msg = 'TTL caching without ttlAutopurge, max, or maxSize can ' +
-                    'result in unbounded memory consumption.';
-                emitWarning(msg, 'UnboundedCacheWarning', code, LRUCache);
-            }
-        }
-    }
-    /**
-     * Return the remaining TTL time for a given entry key
-     */
-    getRemainingTTL(key) {
-        return this.#keyMap.has(key) ? Infinity : 0;
-    }
-    #initializeTTLTracking() {
-        const ttls = new ZeroArray(this.#max);
-        const starts = new ZeroArray(this.#max);
-        this.#ttls = ttls;
-        this.#starts = starts;
-        this.#setItemTTL = (index, ttl, start = perf.now()) => {
-            starts[index] = ttl !== 0 ? start : 0;
-            ttls[index] = ttl;
-            if (ttl !== 0 && this.ttlAutopurge) {
-                const t = setTimeout(() => {
-                    if (this.#isStale(index)) {
-                        this.delete(this.#keyList[index]);
-                    }
-                }, ttl + 1);
-                // unref() not supported on all platforms
-                /* c8 ignore start */
-                if (t.unref) {
-                    t.unref();
-                }
-                /* c8 ignore stop */
-            }
-        };
-        this.#updateItemAge = index => {
-            starts[index] = ttls[index] !== 0 ? perf.now() : 0;
-        };
-        this.#statusTTL = (status, index) => {
-            if (ttls[index]) {
-                const ttl = ttls[index];
-                const start = starts[index];
-                status.ttl = ttl;
-                status.start = start;
-                status.now = cachedNow || getNow();
-                const age = status.now - start;
-                status.remainingTTL = ttl - age;
-            }
-        };
-        // debounce calls to perf.now() to 1s so we're not hitting
-        // that costly call repeatedly.
-        let cachedNow = 0;
-        const getNow = () => {
-            const n = perf.now();
-            if (this.ttlResolution > 0) {
-                cachedNow = n;
-                const t = setTimeout(() => (cachedNow = 0), this.ttlResolution);
-                // not available on all platforms
-                /* c8 ignore start */
-                if (t.unref) {
-                    t.unref();
-                }
-                /* c8 ignore stop */
-            }
-            return n;
-        };
-        this.getRemainingTTL = key => {
-            const index = this.#keyMap.get(key);
-            if (index === undefined) {
-                return 0;
-            }
-            const ttl = ttls[index];
-            const start = starts[index];
-            if (ttl === 0 || start === 0) {
-                return Infinity;
-            }
-            const age = (cachedNow || getNow()) - start;
-            return ttl - age;
-        };
-        this.#isStale = index => {
-            return (ttls[index] !== 0 &&
-                starts[index] !== 0 &&
-                (cachedNow || getNow()) - starts[index] > ttls[index]);
-        };
-    }
-    // conditionally set private methods related to TTL
-    #updateItemAge = () => { };
-    #statusTTL = () => { };
-    #setItemTTL = () => { };
-    /* c8 ignore stop */
-    #isStale = () => false;
-    #initializeSizeTracking() {
-        const sizes = new ZeroArray(this.#max);
-        this.#calculatedSize = 0;
-        this.#sizes = sizes;
-        this.#removeItemSize = index => {
-            this.#calculatedSize -= sizes[index];
-            sizes[index] = 0;
-        };
-        this.#requireSize = (k, v, size, sizeCalculation) => {
-            // provisionally accept background fetches.
-            // actual value size will be checked when they return.
-            if (this.#isBackgroundFetch(v)) {
-                return 0;
-            }
-            if (!isPosInt(size)) {
-                if (sizeCalculation) {
-                    if (typeof sizeCalculation !== 'function') {
-                        throw new TypeError('sizeCalculation must be a function');
-                    }
-                    size = sizeCalculation(v, k);
-                    if (!isPosInt(size)) {
-                        throw new TypeError('sizeCalculation return invalid (expect positive integer)');
-                    }
-                }
-                else {
-                    throw new TypeError('invalid size value (must be positive integer). ' +
-                        'When maxSize or maxEntrySize is used, sizeCalculation ' +
-                        'or size must be set.');
-                }
-            }
-            return size;
-        };
-        this.#addItemSize = (index, size, status) => {
-            sizes[index] = size;
-            if (this.#maxSize) {
-                const maxSize = this.#maxSize - sizes[index];
-                while (this.#calculatedSize > maxSize) {
-                    this.#evict(true);
-                }
-            }
-            this.#calculatedSize += sizes[index];
-            if (status) {
-                status.entrySize = size;
-                status.totalCalculatedSize = this.#calculatedSize;
-            }
-        };
-    }
-    #removeItemSize = _i => { };
-    #addItemSize = (_i, _s, _st) => { };
-    #requireSize = (_k, _v, size, sizeCalculation) => {
-        if (size || sizeCalculation) {
-            throw new TypeError('cannot set size without setting maxSize or maxEntrySize on cache');
-        }
-        return 0;
-    };
-    *#indexes({ allowStale = this.allowStale } = {}) {
-        if (this.#size) {
-            for (let i = this.#tail; true;) {
-                if (!this.#isValidIndex(i)) {
-                    break;
-                }
-                if (allowStale || !this.#isStale(i)) {
-                    yield i;
-                }
-                if (i === this.#head) {
-                    break;
-                }
-                else {
-                    i = this.#prev[i];
-                }
-            }
-        }
-    }
-    *#rindexes({ allowStale = this.allowStale } = {}) {
-        if (this.#size) {
-            for (let i = this.#head; true;) {
-                if (!this.#isValidIndex(i)) {
-                    break;
-                }
-                if (allowStale || !this.#isStale(i)) {
-                    yield i;
-                }
-                if (i === this.#tail) {
-                    break;
-                }
-                else {
-                    i = this.#next[i];
-                }
-            }
-        }
-    }
-    #isValidIndex(index) {
-        return (index !== undefined &&
-            this.#keyMap.get(this.#keyList[index]) === index);
-    }
-    /**
-     * Return a generator yielding `[key, value]` pairs,
-     * in order from most recently used to least recently used.
-     */
-    *entries() {
-        for (const i of this.#indexes()) {
-            if (this.#valList[i] !== undefined &&
-                this.#keyList[i] !== undefined &&
-                !this.#isBackgroundFetch(this.#valList[i])) {
-                yield [this.#keyList[i], this.#valList[i]];
-            }
-        }
-    }
-    /**
-     * Inverse order version of {@link LRUCache.entries}
-     *
-     * Return a generator yielding `[key, value]` pairs,
-     * in order from least recently used to most recently used.
-     */
-    *rentries() {
-        for (const i of this.#rindexes()) {
-            if (this.#valList[i] !== undefined &&
-                this.#keyList[i] !== undefined &&
-                !this.#isBackgroundFetch(this.#valList[i])) {
-                yield [this.#keyList[i], this.#valList[i]];
-            }
-        }
-    }
-    /**
-     * Return a generator yielding the keys in the cache,
-     * in order from most recently used to least recently used.
-     */
-    *keys() {
-        for (const i of this.#indexes()) {
-            const k = this.#keyList[i];
-            if (k !== undefined &&
-                !this.#isBackgroundFetch(this.#valList[i])) {
-                yield k;
-            }
-        }
-    }
-    /**
-     * Inverse order version of {@link LRUCache.keys}
-     *
-     * Return a generator yielding the keys in the cache,
-     * in order from least recently used to most recently used.
-     */
-    *rkeys() {
-        for (const i of this.#rindexes()) {
-            const k = this.#keyList[i];
-            if (k !== undefined &&
-                !this.#isBackgroundFetch(this.#valList[i])) {
-                yield k;
-            }
-        }
-    }
-    /**
-     * Return a generator yielding the values in the cache,
-     * in order from most recently used to least recently used.
-     */
-    *values() {
-        for (const i of this.#indexes()) {
-            const v = this.#valList[i];
-            if (v !== undefined &&
-                !this.#isBackgroundFetch(this.#valList[i])) {
-                yield this.#valList[i];
-            }
-        }
-    }
-    /**
-     * Inverse order version of {@link LRUCache.values}
-     *
-     * Return a generator yielding the values in the cache,
-     * in order from least recently used to most recently used.
-     */
-    *rvalues() {
-        for (const i of this.#rindexes()) {
-            const v = this.#valList[i];
-            if (v !== undefined &&
-                !this.#isBackgroundFetch(this.#valList[i])) {
-                yield this.#valList[i];
-            }
-        }
-    }
-    /**
-     * Iterating over the cache itself yields the same results as
-     * {@link LRUCache.entries}
-     */
-    [Symbol.iterator]() {
-        return this.entries();
-    }
-    /**
-     * Find a value for which the supplied fn method returns a truthy value,
-     * similar to Array.find().  fn is called as fn(value, key, cache).
-     */
-    find(fn, getOptions = {}) {
-        for (const i of this.#indexes()) {
-            const v = this.#valList[i];
-            const value = this.#isBackgroundFetch(v)
-                ? v.__staleWhileFetching
-                : v;
-            if (value === undefined)
-                continue;
-            if (fn(value, this.#keyList[i], this)) {
-                return this.get(this.#keyList[i], getOptions);
-            }
-        }
-    }
-    /**
-     * Call the supplied function on each item in the cache, in order from
-     * most recently used to least recently used.  fn is called as
-     * fn(value, key, cache).  Does not update age or recenty of use.
-     * Does not iterate over stale values.
-     */
-    forEach(fn, thisp = this) {
-        for (const i of this.#indexes()) {
-            const v = this.#valList[i];
-            const value = this.#isBackgroundFetch(v)
-                ? v.__staleWhileFetching
-                : v;
-            if (value === undefined)
-                continue;
-            fn.call(thisp, value, this.#keyList[i], this);
-        }
-    }
-    /**
-     * The same as {@link LRUCache.forEach} but items are iterated over in
-     * reverse order.  (ie, less recently used items are iterated over first.)
-     */
-    rforEach(fn, thisp = this) {
-        for (const i of this.#rindexes()) {
-            const v = this.#valList[i];
-            const value = this.#isBackgroundFetch(v)
-                ? v.__staleWhileFetching
-                : v;
-            if (value === undefined)
-                continue;
-            fn.call(thisp, value, this.#keyList[i], this);
-        }
-    }
-    /**
-     * Delete any stale entries. Returns true if anything was removed,
-     * false otherwise.
-     */
-    purgeStale() {
-        let deleted = false;
-        for (const i of this.#rindexes({ allowStale: true })) {
-            if (this.#isStale(i)) {
-                this.delete(this.#keyList[i]);
-                deleted = true;
-            }
-        }
-        return deleted;
-    }
-    /**
-     * Return an array of [key, {@link LRUCache.Entry}] tuples which can be
-     * passed to cache.load()
-     */
-    dump() {
-        const arr = [];
-        for (const i of this.#indexes({ allowStale: true })) {
-            const key = this.#keyList[i];
-            const v = this.#valList[i];
-            const value = this.#isBackgroundFetch(v)
-                ? v.__staleWhileFetching
-                : v;
-            if (value === undefined || key === undefined)
-                continue;
-            const entry = { value };
-            if (this.#ttls && this.#starts) {
-                entry.ttl = this.#ttls[i];
-                // always dump the start relative to a portable timestamp
-                // it's ok for this to be a bit slow, it's a rare operation.
-                const age = perf.now() - this.#starts[i];
-                entry.start = Math.floor(Date.now() - age);
-            }
-            if (this.#sizes) {
-                entry.size = this.#sizes[i];
-            }
-            arr.unshift([key, entry]);
-        }
-        return arr;
-    }
-    /**
-     * Reset the cache and load in the items in entries in the order listed.
-     * Note that the shape of the resulting cache may be different if the
-     * same options are not used in both caches.
-     */
-    load(arr) {
-        this.clear();
-        for (const [key, entry] of arr) {
-            if (entry.start) {
-                // entry.start is a portable timestamp, but we may be using
-                // node's performance.now(), so calculate the offset, so that
-                // we get the intended remaining TTL, no matter how long it's
-                // been on ice.
-                //
-                // it's ok for this to be a bit slow, it's a rare operation.
-                const age = Date.now() - entry.start;
-                entry.start = perf.now() - age;
-            }
-            this.set(key, entry.value, entry);
-        }
-    }
-    /**
-     * Add a value to the cache.
-     *
-     * Note: if `undefined` is specified as a value, this is an alias for
-     * {@link LRUCache#delete}
-     */
-    set(k, v, setOptions = {}) {
-        if (v === undefined) {
-            this.delete(k);
-            return this;
-        }
-        const { ttl = this.ttl, start, noDisposeOnSet = this.noDisposeOnSet, sizeCalculation = this.sizeCalculation, status, } = setOptions;
-        let { noUpdateTTL = this.noUpdateTTL } = setOptions;
-        const size = this.#requireSize(k, v, setOptions.size || 0, sizeCalculation);
-        // if the item doesn't fit, don't do anything
-        // NB: maxEntrySize set to maxSize by default
-        if (this.maxEntrySize && size > this.maxEntrySize) {
-            if (status) {
-                status.set = 'miss';
-                status.maxEntrySizeExceeded = true;
-            }
-            // have to delete, in case something is there already.
-            this.delete(k);
-            return this;
-        }
-        let index = this.#size === 0 ? undefined : this.#keyMap.get(k);
-        if (index === undefined) {
-            // addition
-            index = (this.#size === 0
-                ? this.#tail
-                : this.#free.length !== 0
-                    ? this.#free.pop()
-                    : this.#size === this.#max
-                        ? this.#evict(false)
-                        : this.#size);
-            this.#keyList[index] = k;
-            this.#valList[index] = v;
-            this.#keyMap.set(k, index);
-            this.#next[this.#tail] = index;
-            this.#prev[index] = this.#tail;
-            this.#tail = index;
-            this.#size++;
-            this.#addItemSize(index, size, status);
-            if (status)
-                status.set = 'add';
-            noUpdateTTL = false;
-        }
-        else {
-            // update
-            this.#moveToTail(index);
-            const oldVal = this.#valList[index];
-            if (v !== oldVal) {
-                if (this.#hasFetchMethod && this.#isBackgroundFetch(oldVal)) {
-                    oldVal.__abortController.abort(new Error('replaced'));
-                }
-                else if (!noDisposeOnSet) {
-                    if (this.#hasDispose) {
-                        this.#dispose?.(oldVal, k, 'set');
-                    }
-                    if (this.#hasDisposeAfter) {
-                        this.#disposed?.push([oldVal, k, 'set']);
-                    }
-                }
-                this.#removeItemSize(index);
-                this.#addItemSize(index, size, status);
-                this.#valList[index] = v;
-                if (status) {
-                    status.set = 'replace';
-                    const oldValue = oldVal && this.#isBackgroundFetch(oldVal)
-                        ? oldVal.__staleWhileFetching
-                        : oldVal;
-                    if (oldValue !== undefined)
-                        status.oldValue = oldValue;
-                }
-            }
-            else if (status) {
-                status.set = 'update';
-            }
-        }
-        if (ttl !== 0 && !this.#ttls) {
-            this.#initializeTTLTracking();
-        }
-        if (this.#ttls) {
-            if (!noUpdateTTL) {
-                this.#setItemTTL(index, ttl, start);
-            }
-            if (status)
-                this.#statusTTL(status, index);
-        }
-        if (!noDisposeOnSet && this.#hasDisposeAfter && this.#disposed) {
-            const dt = this.#disposed;
-            let task;
-            while ((task = dt?.shift())) {
-                this.#disposeAfter?.(...task);
-            }
-        }
-        return this;
-    }
-    /**
-     * Evict the least recently used item, returning its value or
-     * `undefined` if cache is empty.
-     */
-    pop() {
-        try {
-            while (this.#size) {
-                const val = this.#valList[this.#head];
-                this.#evict(true);
-                if (this.#isBackgroundFetch(val)) {
-                    if (val.__staleWhileFetching) {
-                        return val.__staleWhileFetching;
-                    }
-                }
-                else if (val !== undefined) {
-                    return val;
-                }
-            }
-        }
-        finally {
-            if (this.#hasDisposeAfter && this.#disposed) {
-                const dt = this.#disposed;
-                let task;
-                while ((task = dt?.shift())) {
-                    this.#disposeAfter?.(...task);
-                }
-            }
-        }
-    }
-    #evict(free) {
-        const head = this.#head;
-        const k = this.#keyList[head];
-        const v = this.#valList[head];
-        if (this.#hasFetchMethod && this.#isBackgroundFetch(v)) {
-            v.__abortController.abort(new Error('evicted'));
-        }
-        else if (this.#hasDispose || this.#hasDisposeAfter) {
-            if (this.#hasDispose) {
-                this.#dispose?.(v, k, 'evict');
-            }
-            if (this.#hasDisposeAfter) {
-                this.#disposed?.push([v, k, 'evict']);
-            }
-        }
-        this.#removeItemSize(head);
-        // if we aren't about to use the index, then null these out
-        if (free) {
-            this.#keyList[head] = undefined;
-            this.#valList[head] = undefined;
-            this.#free.push(head);
-        }
-        if (this.#size === 1) {
-            this.#head = this.#tail = 0;
-            this.#free.length = 0;
-        }
-        else {
-            this.#head = this.#next[head];
-        }
-        this.#keyMap.delete(k);
-        this.#size--;
-        return head;
-    }
-    /**
-     * Check if a key is in the cache, without updating the recency of use.
-     * Will return false if the item is stale, even though it is technically
-     * in the cache.
-     *
-     * Will not update item age unless
-     * {@link LRUCache.OptionsBase.updateAgeOnHas} is set.
-     */
-    has(k, hasOptions = {}) {
-        const { updateAgeOnHas = this.updateAgeOnHas, status } = hasOptions;
-        const index = this.#keyMap.get(k);
-        if (index !== undefined) {
-            const v = this.#valList[index];
-            if (this.#isBackgroundFetch(v) &&
-                v.__staleWhileFetching === undefined) {
-                return false;
-            }
-            if (!this.#isStale(index)) {
-                if (updateAgeOnHas) {
-                    this.#updateItemAge(index);
-                }
-                if (status) {
-                    status.has = 'hit';
-                    this.#statusTTL(status, index);
-                }
-                return true;
-            }
-            else if (status) {
-                status.has = 'stale';
-                this.#statusTTL(status, index);
-            }
-        }
-        else if (status) {
-            status.has = 'miss';
-        }
-        return false;
-    }
-    /**
-     * Like {@link LRUCache#get} but doesn't update recency or delete stale
-     * items.
-     *
-     * Returns `undefined` if the item is stale, unless
-     * {@link LRUCache.OptionsBase.allowStale} is set.
-     */
-    peek(k, peekOptions = {}) {
-        const { allowStale = this.allowStale } = peekOptions;
-        const index = this.#keyMap.get(k);
-        if (index !== undefined &&
-            (allowStale || !this.#isStale(index))) {
-            const v = this.#valList[index];
-            // either stale and allowed, or forcing a refresh of non-stale value
-            return this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
-        }
-    }
-    #backgroundFetch(k, index, options, context) {
-        const v = index === undefined ? undefined : this.#valList[index];
-        if (this.#isBackgroundFetch(v)) {
-            return v;
-        }
-        const ac = new AC();
-        const { signal } = options;
-        // when/if our AC signals, then stop listening to theirs.
-        signal?.addEventListener('abort', () => ac.abort(signal.reason), {
-            signal: ac.signal,
-        });
-        const fetchOpts = {
-            signal: ac.signal,
-            options,
-            context,
-        };
-        const cb = (v, updateCache = false) => {
-            const { aborted } = ac.signal;
-            const ignoreAbort = options.ignoreFetchAbort && v !== undefined;
-            if (options.status) {
-                if (aborted && !updateCache) {
-                    options.status.fetchAborted = true;
-                    options.status.fetchError = ac.signal.reason;
-                    if (ignoreAbort)
-                        options.status.fetchAbortIgnored = true;
-                }
-                else {
-                    options.status.fetchResolved = true;
-                }
-            }
-            if (aborted && !ignoreAbort && !updateCache) {
-                return fetchFail(ac.signal.reason);
-            }
-            // either we didn't abort, and are still here, or we did, and ignored
-            const bf = p;
-            if (this.#valList[index] === p) {
-                if (v === undefined) {
-                    if (bf.__staleWhileFetching) {
-                        this.#valList[index] = bf.__staleWhileFetching;
-                    }
-                    else {
-                        this.delete(k);
-                    }
-                }
-                else {
-                    if (options.status)
-                        options.status.fetchUpdated = true;
-                    this.set(k, v, fetchOpts.options);
-                }
-            }
-            return v;
-        };
-        const eb = (er) => {
-            if (options.status) {
-                options.status.fetchRejected = true;
-                options.status.fetchError = er;
-            }
-            return fetchFail(er);
-        };
-        const fetchFail = (er) => {
-            const { aborted } = ac.signal;
-            const allowStaleAborted = aborted && options.allowStaleOnFetchAbort;
-            const allowStale = allowStaleAborted || options.allowStaleOnFetchRejection;
-            const noDelete = allowStale || options.noDeleteOnFetchRejection;
-            const bf = p;
-            if (this.#valList[index] === p) {
-                // if we allow stale on fetch rejections, then we need to ensure that
-                // the stale value is not removed from the cache when the fetch fails.
-                const del = !noDelete || bf.__staleWhileFetching === undefined;
-                if (del) {
-                    this.delete(k);
-                }
-                else if (!allowStaleAborted) {
-                    // still replace the *promise* with the stale value,
-                    // since we are done with the promise at this point.
-                    // leave it untouched if we're still waiting for an
-                    // aborted background fetch that hasn't yet returned.
-                    this.#valList[index] = bf.__staleWhileFetching;
-                }
-            }
-            if (allowStale) {
-                if (options.status && bf.__staleWhileFetching !== undefined) {
-                    options.status.returnedStale = true;
-                }
-                return bf.__staleWhileFetching;
-            }
-            else if (bf.__returned === bf) {
-                throw er;
-            }
-        };
-        const pcall = (res, rej) => {
-            const fmp = this.#fetchMethod?.(k, v, fetchOpts);
-            if (fmp && fmp instanceof Promise) {
-                fmp.then(v => res(v), rej);
-            }
-            // ignored, we go until we finish, regardless.
-            // defer check until we are actually aborting,
-            // so fetchMethod can override.
-            ac.signal.addEventListener('abort', () => {
-                if (!options.ignoreFetchAbort ||
-                    options.allowStaleOnFetchAbort) {
-                    res();
-                    // when it eventually resolves, update the cache.
-                    if (options.allowStaleOnFetchAbort) {
-                        res = v => cb(v, true);
-                    }
-                }
-            });
-        };
-        if (options.status)
-            options.status.fetchDispatched = true;
-        const p = new Promise(pcall).then(cb, eb);
-        const bf = Object.assign(p, {
-            __abortController: ac,
-            __staleWhileFetching: v,
-            __returned: undefined,
-        });
-        if (index === undefined) {
-            // internal, don't expose status.
-            this.set(k, bf, { ...fetchOpts.options, status: undefined });
-            index = this.#keyMap.get(k);
-        }
-        else {
-            this.#valList[index] = bf;
-        }
-        return bf;
-    }
-    #isBackgroundFetch(p) {
-        if (!this.#hasFetchMethod)
-            return false;
-        const b = p;
-        return (!!b &&
-            b instanceof Promise &&
-            b.hasOwnProperty('__staleWhileFetching') &&
-            b.__abortController instanceof AC);
-    }
-    async fetch(k, fetchOptions = {}) {
-        const {
-        // get options
-        allowStale = this.allowStale, updateAgeOnGet = this.updateAgeOnGet, noDeleteOnStaleGet = this.noDeleteOnStaleGet,
-        // set options
-        ttl = this.ttl, noDisposeOnSet = this.noDisposeOnSet, size = 0, sizeCalculation = this.sizeCalculation, noUpdateTTL = this.noUpdateTTL,
-        // fetch exclusive options
-        noDeleteOnFetchRejection = this.noDeleteOnFetchRejection, allowStaleOnFetchRejection = this.allowStaleOnFetchRejection, ignoreFetchAbort = this.ignoreFetchAbort, allowStaleOnFetchAbort = this.allowStaleOnFetchAbort, context, forceRefresh = false, status, signal, } = fetchOptions;
-        if (!this.#hasFetchMethod) {
-            if (status)
-                status.fetch = 'get';
-            return this.get(k, {
-                allowStale,
-                updateAgeOnGet,
-                noDeleteOnStaleGet,
-                status,
-            });
-        }
-        const options = {
-            allowStale,
-            updateAgeOnGet,
-            noDeleteOnStaleGet,
-            ttl,
-            noDisposeOnSet,
-            size,
-            sizeCalculation,
-            noUpdateTTL,
-            noDeleteOnFetchRejection,
-            allowStaleOnFetchRejection,
-            allowStaleOnFetchAbort,
-            ignoreFetchAbort,
-            status,
-            signal,
-        };
-        let index = this.#keyMap.get(k);
-        if (index === undefined) {
-            if (status)
-                status.fetch = 'miss';
-            const p = this.#backgroundFetch(k, index, options, context);
-            return (p.__returned = p);
-        }
-        else {
-            // in cache, maybe already fetching
-            const v = this.#valList[index];
-            if (this.#isBackgroundFetch(v)) {
-                const stale = allowStale && v.__staleWhileFetching !== undefined;
-                if (status) {
-                    status.fetch = 'inflight';
-                    if (stale)
-                        status.returnedStale = true;
-                }
-                return stale ? v.__staleWhileFetching : (v.__returned = v);
-            }
-            // if we force a refresh, that means do NOT serve the cached value,
-            // unless we are already in the process of refreshing the cache.
-            const isStale = this.#isStale(index);
-            if (!forceRefresh && !isStale) {
-                if (status)
-                    status.fetch = 'hit';
-                this.#moveToTail(index);
-                if (updateAgeOnGet) {
-                    this.#updateItemAge(index);
-                }
-                if (status)
-                    this.#statusTTL(status, index);
-                return v;
-            }
-            // ok, it is stale or a forced refresh, and not already fetching.
-            // refresh the cache.
-            const p = this.#backgroundFetch(k, index, options, context);
-            const hasStale = p.__staleWhileFetching !== undefined;
-            const staleVal = hasStale && allowStale;
-            if (status) {
-                status.fetch = isStale ? 'stale' : 'refresh';
-                if (staleVal && isStale)
-                    status.returnedStale = true;
-            }
-            return staleVal ? p.__staleWhileFetching : (p.__returned = p);
-        }
-    }
-    /**
-     * Return a value from the cache. Will update the recency of the cache
-     * entry found.
-     *
-     * If the key is not found, get() will return `undefined`.
-     */
-    get(k, getOptions = {}) {
-        const { allowStale = this.allowStale, updateAgeOnGet = this.updateAgeOnGet, noDeleteOnStaleGet = this.noDeleteOnStaleGet, status, } = getOptions;
-        const index = this.#keyMap.get(k);
-        if (index !== undefined) {
-            const value = this.#valList[index];
-            const fetching = this.#isBackgroundFetch(value);
-            if (status)
-                this.#statusTTL(status, index);
-            if (this.#isStale(index)) {
-                if (status)
-                    status.get = 'stale';
-                // delete only if not an in-flight background fetch
-                if (!fetching) {
-                    if (!noDeleteOnStaleGet) {
-                        this.delete(k);
-                    }
-                    if (status && allowStale)
-                        status.returnedStale = true;
-                    return allowStale ? value : undefined;
-                }
-                else {
-                    if (status &&
-                        allowStale &&
-                        value.__staleWhileFetching !== undefined) {
-                        status.returnedStale = true;
-                    }
-                    return allowStale ? value.__staleWhileFetching : undefined;
-                }
-            }
-            else {
-                if (status)
-                    status.get = 'hit';
-                // if we're currently fetching it, we don't actually have it yet
-                // it's not stale, which means this isn't a staleWhileRefetching.
-                // If it's not stale, and fetching, AND has a __staleWhileFetching
-                // value, then that means the user fetched with {forceRefresh:true},
-                // so it's safe to return that value.
-                if (fetching) {
-                    return value.__staleWhileFetching;
-                }
-                this.#moveToTail(index);
-                if (updateAgeOnGet) {
-                    this.#updateItemAge(index);
-                }
-                return value;
-            }
-        }
-        else if (status) {
-            status.get = 'miss';
-        }
-    }
-    #connect(p, n) {
-        this.#prev[n] = p;
-        this.#next[p] = n;
-    }
-    #moveToTail(index) {
-        // if tail already, nothing to do
-        // if head, move head to next[index]
-        // else
-        //   move next[prev[index]] to next[index] (head has no prev)
-        //   move prev[next[index]] to prev[index]
-        // prev[index] = tail
-        // next[tail] = index
-        // tail = index
-        if (index !== this.#tail) {
-            if (index === this.#head) {
-                this.#head = this.#next[index];
-            }
-            else {
-                this.#connect(this.#prev[index], this.#next[index]);
-            }
-            this.#connect(this.#tail, index);
-            this.#tail = index;
-        }
-    }
-    /**
-     * Deletes a key out of the cache.
-     * Returns true if the key was deleted, false otherwise.
-     */
-    delete(k) {
-        let deleted = false;
-        if (this.#size !== 0) {
-            const index = this.#keyMap.get(k);
-            if (index !== undefined) {
-                deleted = true;
-                if (this.#size === 1) {
-                    this.clear();
-                }
-                else {
-                    this.#removeItemSize(index);
-                    const v = this.#valList[index];
-                    if (this.#isBackgroundFetch(v)) {
-                        v.__abortController.abort(new Error('deleted'));
-                    }
-                    else if (this.#hasDispose || this.#hasDisposeAfter) {
-                        if (this.#hasDispose) {
-                            this.#dispose?.(v, k, 'delete');
-                        }
-                        if (this.#hasDisposeAfter) {
-                            this.#disposed?.push([v, k, 'delete']);
-                        }
-                    }
-                    this.#keyMap.delete(k);
-                    this.#keyList[index] = undefined;
-                    this.#valList[index] = undefined;
-                    if (index === this.#tail) {
-                        this.#tail = this.#prev[index];
-                    }
-                    else if (index === this.#head) {
-                        this.#head = this.#next[index];
-                    }
-                    else {
-                        this.#next[this.#prev[index]] = this.#next[index];
-                        this.#prev[this.#next[index]] = this.#prev[index];
-                    }
-                    this.#size--;
-                    this.#free.push(index);
-                }
-            }
-        }
-        if (this.#hasDisposeAfter && this.#disposed?.length) {
-            const dt = this.#disposed;
-            let task;
-            while ((task = dt?.shift())) {
-                this.#disposeAfter?.(...task);
-            }
-        }
-        return deleted;
-    }
-    /**
-     * Clear the cache entirely, throwing away all values.
-     */
-    clear() {
-        for (const index of this.#rindexes({ allowStale: true })) {
-            const v = this.#valList[index];
-            if (this.#isBackgroundFetch(v)) {
-                v.__abortController.abort(new Error('deleted'));
-            }
-            else {
-                const k = this.#keyList[index];
-                if (this.#hasDispose) {
-                    this.#dispose?.(v, k, 'delete');
-                }
-                if (this.#hasDisposeAfter) {
-                    this.#disposed?.push([v, k, 'delete']);
-                }
-            }
-        }
-        this.#keyMap.clear();
-        this.#valList.fill(undefined);
-        this.#keyList.fill(undefined);
-        if (this.#ttls && this.#starts) {
-            this.#ttls.fill(0);
-            this.#starts.fill(0);
-        }
-        if (this.#sizes) {
-            this.#sizes.fill(0);
-        }
-        this.#head = 0;
-        this.#tail = 0;
-        this.#free.length = 0;
-        this.#calculatedSize = 0;
-        this.#size = 0;
-        if (this.#hasDisposeAfter && this.#disposed) {
-            const dt = this.#disposed;
-            let task;
-            while ((task = dt?.shift())) {
-                this.#disposeAfter?.(...task);
-            }
-        }
-    }
-}
-exports.LRUCache = LRUCache;
-//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/deps/npm/node_modules/path-scurry/node_modules/lru-cache/dist/cjs/index.min.js b/deps/npm/node_modules/path-scurry/node_modules/lru-cache/dist/cjs/index.min.js
deleted file mode 100644
index d854bf570d346c..00000000000000
--- a/deps/npm/node_modules/path-scurry/node_modules/lru-cache/dist/cjs/index.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-"use strict";var x=(o,t,e)=>{if(!t.has(o))throw TypeError("Cannot "+e)};var j=(o,t,e)=>(x(o,t,"read from private field"),e?e.call(o):t.get(o)),I=(o,t,e)=>{if(t.has(o))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(o):t.set(o,e)},D=(o,t,e,i)=>(x(o,t,"write to private field"),i?i.call(o,e):t.set(o,e),e);Object.defineProperty(exports,"__esModule",{value:!0});exports.LRUCache=void 0;var v=typeof performance=="object"&&performance&&typeof performance.now=="function"?performance:Date,N=new Set,L=typeof process=="object"&&process?process:{},P=(o,t,e,i)=>{typeof L.emitWarning=="function"?L.emitWarning(o,t,e,i):console.error(`[${e}] ${t}: ${o}`)},W=globalThis.AbortController,M=globalThis.AbortSignal;if(typeof W>"u"){M=class{onabort;_onabort=[];reason;aborted=!1;addEventListener(i,s){this._onabort.push(s)}},W=class{constructor(){t()}signal=new M;abort(i){if(!this.signal.aborted){this.signal.reason=i,this.signal.aborted=!0;for(let s of this.signal._onabort)s(i);this.signal.onabort?.(i)}}};let o=L.env?.LRU_CACHE_IGNORE_AC_WARNING!=="1",t=()=>{o&&(o=!1,P("AbortController is not defined. If using lru-cache in node 14, load an AbortController polyfill from the `node-abort-controller` package. A minimal polyfill is provided for use by LRUCache.fetch(), but it should not be relied upon in other contexts (eg, passing it to other APIs that use AbortController/AbortSignal might have undesirable effects). You may disable this with LRU_CACHE_IGNORE_AC_WARNING=1 in the env.","NO_ABORT_CONTROLLER","ENOTSUP",t))}}var V=o=>!N.has(o),Y=Symbol("type"),m=o=>o&&o===Math.floor(o)&&o>0&&isFinite(o),k=o=>m(o)?o<=Math.pow(2,8)?Uint8Array:o<=Math.pow(2,16)?Uint16Array:o<=Math.pow(2,32)?Uint32Array:o<=Number.MAX_SAFE_INTEGER?z:null:null,z=class extends Array{constructor(t){super(t),this.fill(0)}},E,T=class{heap;length;static create(t){let e=k(t);if(!e)return[];D(T,E,!0);let i=new T(t,e);return D(T,E,!1),i}constructor(t,e){if(!j(T,E))throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new e(t),this.length=0}push(t){this.heap[this.length++]=t}pop(){return this.heap[--this.length]}},R=T;E=new WeakMap,I(R,E,!1);var C=class{#d;#f;#_;#g;#C;ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;#s;#p;#n;#i;#t;#l;#c;#o;#h;#w;#r;#m;#F;#S;#b;#T;#a;static unsafeExposeInternals(t){return{starts:t.#F,ttls:t.#S,sizes:t.#m,keyMap:t.#n,keyList:t.#i,valList:t.#t,next:t.#l,prev:t.#c,get head(){return t.#o},get tail(){return t.#h},free:t.#w,isBackgroundFetch:e=>t.#e(e),backgroundFetch:(e,i,s,n)=>t.#D(e,i,s,n),moveToTail:e=>t.#v(e),indexes:e=>t.#y(e),rindexes:e=>t.#A(e),isStale:e=>t.#u(e)}}get max(){return this.#d}get maxSize(){return this.#f}get calculatedSize(){return this.#p}get size(){return this.#s}get fetchMethod(){return this.#C}get dispose(){return this.#_}get disposeAfter(){return this.#g}constructor(t){let{max:e=0,ttl:i,ttlResolution:s=1,ttlAutopurge:n,updateAgeOnGet:h,updateAgeOnHas:a,allowStale:r,dispose:u,disposeAfter:b,noDisposeOnSet:f,noUpdateTTL:d,maxSize:p=0,maxEntrySize:F=0,sizeCalculation:c,fetchMethod:w,noDeleteOnFetchRejection:l,noDeleteOnStaleGet:S,allowStaleOnFetchRejection:y,allowStaleOnFetchAbort:g,ignoreFetchAbort:_}=t;if(e!==0&&!m(e))throw new TypeError("max option must be a nonnegative integer");let O=e?k(e):Array;if(!O)throw new Error("invalid max value: "+e);if(this.#d=e,this.#f=p,this.maxEntrySize=F||this.#f,this.sizeCalculation=c,this.sizeCalculation){if(!this.#f&&!this.maxEntrySize)throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if(typeof this.sizeCalculation!="function")throw new TypeError("sizeCalculation set to non-function")}if(w!==void 0&&typeof w!="function")throw new TypeError("fetchMethod must be a function if specified");if(this.#C=w,this.#T=!!w,this.#n=new Map,this.#i=new Array(e).fill(void 0),this.#t=new Array(e).fill(void 0),this.#l=new O(e),this.#c=new O(e),this.#o=0,this.#h=0,this.#w=R.create(e),this.#s=0,this.#p=0,typeof u=="function"&&(this.#_=u),typeof b=="function"?(this.#g=b,this.#r=[]):(this.#g=void 0,this.#r=void 0),this.#b=!!this.#_,this.#a=!!this.#g,this.noDisposeOnSet=!!f,this.noUpdateTTL=!!d,this.noDeleteOnFetchRejection=!!l,this.allowStaleOnFetchRejection=!!y,this.allowStaleOnFetchAbort=!!g,this.ignoreFetchAbort=!!_,this.maxEntrySize!==0){if(this.#f!==0&&!m(this.#f))throw new TypeError("maxSize must be a positive integer if specified");if(!m(this.maxEntrySize))throw new TypeError("maxEntrySize must be a positive integer if specified");this.#I()}if(this.allowStale=!!r,this.noDeleteOnStaleGet=!!S,this.updateAgeOnGet=!!h,this.updateAgeOnHas=!!a,this.ttlResolution=m(s)||s===0?s:1,this.ttlAutopurge=!!n,this.ttl=i||0,this.ttl){if(!m(this.ttl))throw new TypeError("ttl must be a positive integer if specified");this.#L()}if(this.#d===0&&this.ttl===0&&this.#f===0)throw new TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#d&&!this.#f){let A="LRU_CACHE_UNBOUNDED";V(A)&&(N.add(A),P("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning",A,C))}}getRemainingTTL(t){return this.#n.has(t)?1/0:0}#L(){let t=new z(this.#d),e=new z(this.#d);this.#S=t,this.#F=e,this.#U=(n,h,a=v.now())=>{if(e[n]=h!==0?a:0,t[n]=h,h!==0&&this.ttlAutopurge){let r=setTimeout(()=>{this.#u(n)&&this.delete(this.#i[n])},h+1);r.unref&&r.unref()}},this.#z=n=>{e[n]=t[n]!==0?v.now():0},this.#O=(n,h)=>{if(t[h]){let a=t[h],r=e[h];n.ttl=a,n.start=r,n.now=i||s();let u=n.now-r;n.remainingTTL=a-u}};let i=0,s=()=>{let n=v.now();if(this.ttlResolution>0){i=n;let h=setTimeout(()=>i=0,this.ttlResolution);h.unref&&h.unref()}return n};this.getRemainingTTL=n=>{let h=this.#n.get(n);if(h===void 0)return 0;let a=t[h],r=e[h];if(a===0||r===0)return 1/0;let u=(i||s())-r;return a-u},this.#u=n=>t[n]!==0&&e[n]!==0&&(i||s())-e[n]>t[n]}#z=()=>{};#O=()=>{};#U=()=>{};#u=()=>!1;#I(){let t=new z(this.#d);this.#p=0,this.#m=t,this.#E=e=>{this.#p-=t[e],t[e]=0},this.#G=(e,i,s,n)=>{if(this.#e(i))return 0;if(!m(s))if(n){if(typeof n!="function")throw new TypeError("sizeCalculation must be a function");if(s=n(i,e),!m(s))throw new TypeError("sizeCalculation return invalid (expect positive integer)")}else throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.");return s},this.#R=(e,i,s)=>{if(t[e]=i,this.#f){let n=this.#f-t[e];for(;this.#p>n;)this.#W(!0)}this.#p+=t[e],s&&(s.entrySize=i,s.totalCalculatedSize=this.#p)}}#E=t=>{};#R=(t,e,i)=>{};#G=(t,e,i,s)=>{if(i||s)throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#y({allowStale:t=this.allowStale}={}){if(this.#s)for(let e=this.#h;!(!this.#x(e)||((t||!this.#u(e))&&(yield e),e===this.#o));)e=this.#c[e]}*#A({allowStale:t=this.allowStale}={}){if(this.#s)for(let e=this.#o;!(!this.#x(e)||((t||!this.#u(e))&&(yield e),e===this.#h));)e=this.#l[e]}#x(t){return t!==void 0&&this.#n.get(this.#i[t])===t}*entries(){for(let t of this.#y())this.#t[t]!==void 0&&this.#i[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#i[t],this.#t[t]])}*rentries(){for(let t of this.#A())this.#t[t]!==void 0&&this.#i[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#i[t],this.#t[t]])}*keys(){for(let t of this.#y()){let e=this.#i[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*rkeys(){for(let t of this.#A()){let e=this.#i[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*values(){for(let t of this.#y())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}*rvalues(){for(let t of this.#A())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}[Symbol.iterator](){return this.entries()}find(t,e={}){for(let i of this.#y()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;if(n!==void 0&&t(n,this.#i[i],this))return this.get(this.#i[i],e)}}forEach(t,e=this){for(let i of this.#y()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&t.call(e,n,this.#i[i],this)}}rforEach(t,e=this){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&t.call(e,n,this.#i[i],this)}}purgeStale(){let t=!1;for(let e of this.#A({allowStale:!0}))this.#u(e)&&(this.delete(this.#i[e]),t=!0);return t}dump(){let t=[];for(let e of this.#y({allowStale:!0})){let i=this.#i[e],s=this.#t[e],n=this.#e(s)?s.__staleWhileFetching:s;if(n===void 0||i===void 0)continue;let h={value:n};if(this.#S&&this.#F){h.ttl=this.#S[e];let a=v.now()-this.#F[e];h.start=Math.floor(Date.now()-a)}this.#m&&(h.size=this.#m[e]),t.unshift([i,h])}return t}load(t){this.clear();for(let[e,i]of t){if(i.start){let s=Date.now()-i.start;i.start=v.now()-s}this.set(e,i.value,i)}}set(t,e,i={}){if(e===void 0)return this.delete(t),this;let{ttl:s=this.ttl,start:n,noDisposeOnSet:h=this.noDisposeOnSet,sizeCalculation:a=this.sizeCalculation,status:r}=i,{noUpdateTTL:u=this.noUpdateTTL}=i,b=this.#G(t,e,i.size||0,a);if(this.maxEntrySize&&b>this.maxEntrySize)return r&&(r.set="miss",r.maxEntrySizeExceeded=!0),this.delete(t),this;let f=this.#s===0?void 0:this.#n.get(t);if(f===void 0)f=this.#s===0?this.#h:this.#w.length!==0?this.#w.pop():this.#s===this.#d?this.#W(!1):this.#s,this.#i[f]=t,this.#t[f]=e,this.#n.set(t,f),this.#l[this.#h]=f,this.#c[f]=this.#h,this.#h=f,this.#s++,this.#R(f,b,r),r&&(r.set="add"),u=!1;else{this.#v(f);let d=this.#t[f];if(e!==d){if(this.#T&&this.#e(d)?d.__abortController.abort(new Error("replaced")):h||(this.#b&&this.#_?.(d,t,"set"),this.#a&&this.#r?.push([d,t,"set"])),this.#E(f),this.#R(f,b,r),this.#t[f]=e,r){r.set="replace";let p=d&&this.#e(d)?d.__staleWhileFetching:d;p!==void 0&&(r.oldValue=p)}}else r&&(r.set="update")}if(s!==0&&!this.#S&&this.#L(),this.#S&&(u||this.#U(f,s,n),r&&this.#O(r,f)),!h&&this.#a&&this.#r){let d=this.#r,p;for(;p=d?.shift();)this.#g?.(...p)}return this}pop(){try{for(;this.#s;){let t=this.#t[this.#o];if(this.#W(!0),this.#e(t)){if(t.__staleWhileFetching)return t.__staleWhileFetching}else if(t!==void 0)return t}}finally{if(this.#a&&this.#r){let t=this.#r,e;for(;e=t?.shift();)this.#g?.(...e)}}}#W(t){let e=this.#o,i=this.#i[e],s=this.#t[e];return this.#T&&this.#e(s)?s.__abortController.abort(new Error("evicted")):(this.#b||this.#a)&&(this.#b&&this.#_?.(s,i,"evict"),this.#a&&this.#r?.push([s,i,"evict"])),this.#E(e),t&&(this.#i[e]=void 0,this.#t[e]=void 0,this.#w.push(e)),this.#s===1?(this.#o=this.#h=0,this.#w.length=0):this.#o=this.#l[e],this.#n.delete(i),this.#s--,e}has(t,e={}){let{updateAgeOnHas:i=this.updateAgeOnHas,status:s}=e,n=this.#n.get(t);if(n!==void 0){let h=this.#t[n];if(this.#e(h)&&h.__staleWhileFetching===void 0)return!1;if(this.#u(n))s&&(s.has="stale",this.#O(s,n));else return i&&this.#z(n),s&&(s.has="hit",this.#O(s,n)),!0}else s&&(s.has="miss");return!1}peek(t,e={}){let{allowStale:i=this.allowStale}=e,s=this.#n.get(t);if(s!==void 0&&(i||!this.#u(s))){let n=this.#t[s];return this.#e(n)?n.__staleWhileFetching:n}}#D(t,e,i,s){let n=e===void 0?void 0:this.#t[e];if(this.#e(n))return n;let h=new W,{signal:a}=i;a?.addEventListener("abort",()=>h.abort(a.reason),{signal:h.signal});let r={signal:h.signal,options:i,context:s},u=(c,w=!1)=>{let{aborted:l}=h.signal,S=i.ignoreFetchAbort&&c!==void 0;if(i.status&&(l&&!w?(i.status.fetchAborted=!0,i.status.fetchError=h.signal.reason,S&&(i.status.fetchAbortIgnored=!0)):i.status.fetchResolved=!0),l&&!S&&!w)return f(h.signal.reason);let y=p;return this.#t[e]===p&&(c===void 0?y.__staleWhileFetching?this.#t[e]=y.__staleWhileFetching:this.delete(t):(i.status&&(i.status.fetchUpdated=!0),this.set(t,c,r.options))),c},b=c=>(i.status&&(i.status.fetchRejected=!0,i.status.fetchError=c),f(c)),f=c=>{let{aborted:w}=h.signal,l=w&&i.allowStaleOnFetchAbort,S=l||i.allowStaleOnFetchRejection,y=S||i.noDeleteOnFetchRejection,g=p;if(this.#t[e]===p&&(!y||g.__staleWhileFetching===void 0?this.delete(t):l||(this.#t[e]=g.__staleWhileFetching)),S)return i.status&&g.__staleWhileFetching!==void 0&&(i.status.returnedStale=!0),g.__staleWhileFetching;if(g.__returned===g)throw c},d=(c,w)=>{let l=this.#C?.(t,n,r);l&&l instanceof Promise&&l.then(S=>c(S),w),h.signal.addEventListener("abort",()=>{(!i.ignoreFetchAbort||i.allowStaleOnFetchAbort)&&(c(),i.allowStaleOnFetchAbort&&(c=S=>u(S,!0)))})};i.status&&(i.status.fetchDispatched=!0);let p=new Promise(d).then(u,b),F=Object.assign(p,{__abortController:h,__staleWhileFetching:n,__returned:void 0});return e===void 0?(this.set(t,F,{...r.options,status:void 0}),e=this.#n.get(t)):this.#t[e]=F,F}#e(t){if(!this.#T)return!1;let e=t;return!!e&&e instanceof Promise&&e.hasOwnProperty("__staleWhileFetching")&&e.__abortController instanceof W}async fetch(t,e={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,ttl:h=this.ttl,noDisposeOnSet:a=this.noDisposeOnSet,size:r=0,sizeCalculation:u=this.sizeCalculation,noUpdateTTL:b=this.noUpdateTTL,noDeleteOnFetchRejection:f=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:d=this.allowStaleOnFetchRejection,ignoreFetchAbort:p=this.ignoreFetchAbort,allowStaleOnFetchAbort:F=this.allowStaleOnFetchAbort,context:c,forceRefresh:w=!1,status:l,signal:S}=e;if(!this.#T)return l&&(l.fetch="get"),this.get(t,{allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,status:l});let y={allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,ttl:h,noDisposeOnSet:a,size:r,sizeCalculation:u,noUpdateTTL:b,noDeleteOnFetchRejection:f,allowStaleOnFetchRejection:d,allowStaleOnFetchAbort:F,ignoreFetchAbort:p,status:l,signal:S},g=this.#n.get(t);if(g===void 0){l&&(l.fetch="miss");let _=this.#D(t,g,y,c);return _.__returned=_}else{let _=this.#t[g];if(this.#e(_)){let G=i&&_.__staleWhileFetching!==void 0;return l&&(l.fetch="inflight",G&&(l.returnedStale=!0)),G?_.__staleWhileFetching:_.__returned=_}let O=this.#u(g);if(!w&&!O)return l&&(l.fetch="hit"),this.#v(g),s&&this.#z(g),l&&this.#O(l,g),_;let A=this.#D(t,g,y,c),U=A.__staleWhileFetching!==void 0&&i;return l&&(l.fetch=O?"stale":"refresh",U&&O&&(l.returnedStale=!0)),U?A.__staleWhileFetching:A.__returned=A}}get(t,e={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,status:h}=e,a=this.#n.get(t);if(a!==void 0){let r=this.#t[a],u=this.#e(r);return h&&this.#O(h,a),this.#u(a)?(h&&(h.get="stale"),u?(h&&i&&r.__staleWhileFetching!==void 0&&(h.returnedStale=!0),i?r.__staleWhileFetching:void 0):(n||this.delete(t),h&&i&&(h.returnedStale=!0),i?r:void 0)):(h&&(h.get="hit"),u?r.__staleWhileFetching:(this.#v(a),s&&this.#z(a),r))}else h&&(h.get="miss")}#j(t,e){this.#c[e]=t,this.#l[t]=e}#v(t){t!==this.#h&&(t===this.#o?this.#o=this.#l[t]:this.#j(this.#c[t],this.#l[t]),this.#j(this.#h,t),this.#h=t)}delete(t){let e=!1;if(this.#s!==0){let i=this.#n.get(t);if(i!==void 0)if(e=!0,this.#s===1)this.clear();else{this.#E(i);let s=this.#t[i];this.#e(s)?s.__abortController.abort(new Error("deleted")):(this.#b||this.#a)&&(this.#b&&this.#_?.(s,t,"delete"),this.#a&&this.#r?.push([s,t,"delete"])),this.#n.delete(t),this.#i[i]=void 0,this.#t[i]=void 0,i===this.#h?this.#h=this.#c[i]:i===this.#o?this.#o=this.#l[i]:(this.#l[this.#c[i]]=this.#l[i],this.#c[this.#l[i]]=this.#c[i]),this.#s--,this.#w.push(i)}}if(this.#a&&this.#r?.length){let i=this.#r,s;for(;s=i?.shift();)this.#g?.(...s)}return e}clear(){for(let t of this.#A({allowStale:!0})){let e=this.#t[t];if(this.#e(e))e.__abortController.abort(new Error("deleted"));else{let i=this.#i[t];this.#b&&this.#_?.(e,i,"delete"),this.#a&&this.#r?.push([e,i,"delete"])}}if(this.#n.clear(),this.#t.fill(void 0),this.#i.fill(void 0),this.#S&&this.#F&&(this.#S.fill(0),this.#F.fill(0)),this.#m&&this.#m.fill(0),this.#o=0,this.#h=0,this.#w.length=0,this.#p=0,this.#s=0,this.#a&&this.#r){let t=this.#r,e;for(;e=t?.shift();)this.#g?.(...e)}}};exports.LRUCache=C;
-//# sourceMappingURL=index.min.js.map
diff --git a/deps/npm/node_modules/path-scurry/node_modules/lru-cache/dist/mjs/index.js b/deps/npm/node_modules/path-scurry/node_modules/lru-cache/dist/mjs/index.js
deleted file mode 100644
index 1d8a36931a45a8..00000000000000
--- a/deps/npm/node_modules/path-scurry/node_modules/lru-cache/dist/mjs/index.js
+++ /dev/null
@@ -1,1391 +0,0 @@
-/**
- * @module LRUCache
- */
-const perf = typeof performance === 'object' &&
-    performance &&
-    typeof performance.now === 'function'
-    ? performance
-    : Date;
-const warned = new Set();
-/* c8 ignore start */
-const PROCESS = (typeof process === 'object' && !!process ? process : {});
-/* c8 ignore start */
-const emitWarning = (msg, type, code, fn) => {
-    typeof PROCESS.emitWarning === 'function'
-        ? PROCESS.emitWarning(msg, type, code, fn)
-        : console.error(`[${code}] ${type}: ${msg}`);
-};
-let AC = globalThis.AbortController;
-let AS = globalThis.AbortSignal;
-/* c8 ignore start */
-if (typeof AC === 'undefined') {
-    //@ts-ignore
-    AS = class AbortSignal {
-        onabort;
-        _onabort = [];
-        reason;
-        aborted = false;
-        addEventListener(_, fn) {
-            this._onabort.push(fn);
-        }
-    };
-    //@ts-ignore
-    AC = class AbortController {
-        constructor() {
-            warnACPolyfill();
-        }
-        signal = new AS();
-        abort(reason) {
-            if (this.signal.aborted)
-                return;
-            //@ts-ignore
-            this.signal.reason = reason;
-            //@ts-ignore
-            this.signal.aborted = true;
-            //@ts-ignore
-            for (const fn of this.signal._onabort) {
-                fn(reason);
-            }
-            this.signal.onabort?.(reason);
-        }
-    };
-    let printACPolyfillWarning = PROCESS.env?.LRU_CACHE_IGNORE_AC_WARNING !== '1';
-    const warnACPolyfill = () => {
-        if (!printACPolyfillWarning)
-            return;
-        printACPolyfillWarning = false;
-        emitWarning('AbortController is not defined. If using lru-cache in ' +
-            'node 14, load an AbortController polyfill from the ' +
-            '`node-abort-controller` package. A minimal polyfill is ' +
-            'provided for use by LRUCache.fetch(), but it should not be ' +
-            'relied upon in other contexts (eg, passing it to other APIs that ' +
-            'use AbortController/AbortSignal might have undesirable effects). ' +
-            'You may disable this with LRU_CACHE_IGNORE_AC_WARNING=1 in the env.', 'NO_ABORT_CONTROLLER', 'ENOTSUP', warnACPolyfill);
-    };
-}
-/* c8 ignore stop */
-const shouldWarn = (code) => !warned.has(code);
-const TYPE = Symbol('type');
-const isPosInt = (n) => n && n === Math.floor(n) && n > 0 && isFinite(n);
-/* c8 ignore start */
-// This is a little bit ridiculous, tbh.
-// The maximum array length is 2^32-1 or thereabouts on most JS impls.
-// And well before that point, you're caching the entire world, I mean,
-// that's ~32GB of just integers for the next/prev links, plus whatever
-// else to hold that many keys and values.  Just filling the memory with
-// zeroes at init time is brutal when you get that big.
-// But why not be complete?
-// Maybe in the future, these limits will have expanded.
-const getUintArray = (max) => !isPosInt(max)
-    ? null
-    : max <= Math.pow(2, 8)
-        ? Uint8Array
-        : max <= Math.pow(2, 16)
-            ? Uint16Array
-            : max <= Math.pow(2, 32)
-                ? Uint32Array
-                : max <= Number.MAX_SAFE_INTEGER
-                    ? ZeroArray
-                    : null;
-/* c8 ignore stop */
-class ZeroArray extends Array {
-    constructor(size) {
-        super(size);
-        this.fill(0);
-    }
-}
-class Stack {
-    heap;
-    length;
-    // private constructor
-    static #constructing = false;
-    static create(max) {
-        const HeapCls = getUintArray(max);
-        if (!HeapCls)
-            return [];
-        Stack.#constructing = true;
-        const s = new Stack(max, HeapCls);
-        Stack.#constructing = false;
-        return s;
-    }
-    constructor(max, HeapCls) {
-        /* c8 ignore start */
-        if (!Stack.#constructing) {
-            throw new TypeError('instantiate Stack using Stack.create(n)');
-        }
-        /* c8 ignore stop */
-        this.heap = new HeapCls(max);
-        this.length = 0;
-    }
-    push(n) {
-        this.heap[this.length++] = n;
-    }
-    pop() {
-        return this.heap[--this.length];
-    }
-}
-/**
- * Default export, the thing you're using this module to get.
- *
- * All properties from the options object (with the exception of
- * {@link OptionsBase.max} and {@link OptionsBase.maxSize}) are added as
- * normal public members. (`max` and `maxBase` are read-only getters.)
- * Changing any of these will alter the defaults for subsequent method calls,
- * but is otherwise safe.
- */
-export class LRUCache {
-    // properties coming in from the options of these, only max and maxSize
-    // really *need* to be protected. The rest can be modified, as they just
-    // set defaults for various methods.
-    #max;
-    #maxSize;
-    #dispose;
-    #disposeAfter;
-    #fetchMethod;
-    /**
-     * {@link LRUCache.OptionsBase.ttl}
-     */
-    ttl;
-    /**
-     * {@link LRUCache.OptionsBase.ttlResolution}
-     */
-    ttlResolution;
-    /**
-     * {@link LRUCache.OptionsBase.ttlAutopurge}
-     */
-    ttlAutopurge;
-    /**
-     * {@link LRUCache.OptionsBase.updateAgeOnGet}
-     */
-    updateAgeOnGet;
-    /**
-     * {@link LRUCache.OptionsBase.updateAgeOnHas}
-     */
-    updateAgeOnHas;
-    /**
-     * {@link LRUCache.OptionsBase.allowStale}
-     */
-    allowStale;
-    /**
-     * {@link LRUCache.OptionsBase.noDisposeOnSet}
-     */
-    noDisposeOnSet;
-    /**
-     * {@link LRUCache.OptionsBase.noUpdateTTL}
-     */
-    noUpdateTTL;
-    /**
-     * {@link LRUCache.OptionsBase.maxEntrySize}
-     */
-    maxEntrySize;
-    /**
-     * {@link LRUCache.OptionsBase.sizeCalculation}
-     */
-    sizeCalculation;
-    /**
-     * {@link LRUCache.OptionsBase.noDeleteOnFetchRejection}
-     */
-    noDeleteOnFetchRejection;
-    /**
-     * {@link LRUCache.OptionsBase.noDeleteOnStaleGet}
-     */
-    noDeleteOnStaleGet;
-    /**
-     * {@link LRUCache.OptionsBase.allowStaleOnFetchAbort}
-     */
-    allowStaleOnFetchAbort;
-    /**
-     * {@link LRUCache.OptionsBase.allowStaleOnFetchRejection}
-     */
-    allowStaleOnFetchRejection;
-    /**
-     * {@link LRUCache.OptionsBase.ignoreFetchAbort}
-     */
-    ignoreFetchAbort;
-    // computed properties
-    #size;
-    #calculatedSize;
-    #keyMap;
-    #keyList;
-    #valList;
-    #next;
-    #prev;
-    #head;
-    #tail;
-    #free;
-    #disposed;
-    #sizes;
-    #starts;
-    #ttls;
-    #hasDispose;
-    #hasFetchMethod;
-    #hasDisposeAfter;
-    /**
-     * Do not call this method unless you need to inspect the
-     * inner workings of the cache.  If anything returned by this
-     * object is modified in any way, strange breakage may occur.
-     *
-     * These fields are private for a reason!
-     *
-     * @internal
-     */
-    static unsafeExposeInternals(c) {
-        return {
-            // properties
-            starts: c.#starts,
-            ttls: c.#ttls,
-            sizes: c.#sizes,
-            keyMap: c.#keyMap,
-            keyList: c.#keyList,
-            valList: c.#valList,
-            next: c.#next,
-            prev: c.#prev,
-            get head() {
-                return c.#head;
-            },
-            get tail() {
-                return c.#tail;
-            },
-            free: c.#free,
-            // methods
-            isBackgroundFetch: (p) => c.#isBackgroundFetch(p),
-            backgroundFetch: (k, index, options, context) => c.#backgroundFetch(k, index, options, context),
-            moveToTail: (index) => c.#moveToTail(index),
-            indexes: (options) => c.#indexes(options),
-            rindexes: (options) => c.#rindexes(options),
-            isStale: (index) => c.#isStale(index),
-        };
-    }
-    // Protected read-only members
-    /**
-     * {@link LRUCache.OptionsBase.max} (read-only)
-     */
-    get max() {
-        return this.#max;
-    }
-    /**
-     * {@link LRUCache.OptionsBase.maxSize} (read-only)
-     */
-    get maxSize() {
-        return this.#maxSize;
-    }
-    /**
-     * The total computed size of items in the cache (read-only)
-     */
-    get calculatedSize() {
-        return this.#calculatedSize;
-    }
-    /**
-     * The number of items stored in the cache (read-only)
-     */
-    get size() {
-        return this.#size;
-    }
-    /**
-     * {@link LRUCache.OptionsBase.fetchMethod} (read-only)
-     */
-    get fetchMethod() {
-        return this.#fetchMethod;
-    }
-    /**
-     * {@link LRUCache.OptionsBase.dispose} (read-only)
-     */
-    get dispose() {
-        return this.#dispose;
-    }
-    /**
-     * {@link LRUCache.OptionsBase.disposeAfter} (read-only)
-     */
-    get disposeAfter() {
-        return this.#disposeAfter;
-    }
-    constructor(options) {
-        const { max = 0, ttl, ttlResolution = 1, ttlAutopurge, updateAgeOnGet, updateAgeOnHas, allowStale, dispose, disposeAfter, noDisposeOnSet, noUpdateTTL, maxSize = 0, maxEntrySize = 0, sizeCalculation, fetchMethod, noDeleteOnFetchRejection, noDeleteOnStaleGet, allowStaleOnFetchRejection, allowStaleOnFetchAbort, ignoreFetchAbort, } = options;
-        if (max !== 0 && !isPosInt(max)) {
-            throw new TypeError('max option must be a nonnegative integer');
-        }
-        const UintArray = max ? getUintArray(max) : Array;
-        if (!UintArray) {
-            throw new Error('invalid max value: ' + max);
-        }
-        this.#max = max;
-        this.#maxSize = maxSize;
-        this.maxEntrySize = maxEntrySize || this.#maxSize;
-        this.sizeCalculation = sizeCalculation;
-        if (this.sizeCalculation) {
-            if (!this.#maxSize && !this.maxEntrySize) {
-                throw new TypeError('cannot set sizeCalculation without setting maxSize or maxEntrySize');
-            }
-            if (typeof this.sizeCalculation !== 'function') {
-                throw new TypeError('sizeCalculation set to non-function');
-            }
-        }
-        if (fetchMethod !== undefined &&
-            typeof fetchMethod !== 'function') {
-            throw new TypeError('fetchMethod must be a function if specified');
-        }
-        this.#fetchMethod = fetchMethod;
-        this.#hasFetchMethod = !!fetchMethod;
-        this.#keyMap = new Map();
-        this.#keyList = new Array(max).fill(undefined);
-        this.#valList = new Array(max).fill(undefined);
-        this.#next = new UintArray(max);
-        this.#prev = new UintArray(max);
-        this.#head = 0;
-        this.#tail = 0;
-        this.#free = Stack.create(max);
-        this.#size = 0;
-        this.#calculatedSize = 0;
-        if (typeof dispose === 'function') {
-            this.#dispose = dispose;
-        }
-        if (typeof disposeAfter === 'function') {
-            this.#disposeAfter = disposeAfter;
-            this.#disposed = [];
-        }
-        else {
-            this.#disposeAfter = undefined;
-            this.#disposed = undefined;
-        }
-        this.#hasDispose = !!this.#dispose;
-        this.#hasDisposeAfter = !!this.#disposeAfter;
-        this.noDisposeOnSet = !!noDisposeOnSet;
-        this.noUpdateTTL = !!noUpdateTTL;
-        this.noDeleteOnFetchRejection = !!noDeleteOnFetchRejection;
-        this.allowStaleOnFetchRejection = !!allowStaleOnFetchRejection;
-        this.allowStaleOnFetchAbort = !!allowStaleOnFetchAbort;
-        this.ignoreFetchAbort = !!ignoreFetchAbort;
-        // NB: maxEntrySize is set to maxSize if it's set
-        if (this.maxEntrySize !== 0) {
-            if (this.#maxSize !== 0) {
-                if (!isPosInt(this.#maxSize)) {
-                    throw new TypeError('maxSize must be a positive integer if specified');
-                }
-            }
-            if (!isPosInt(this.maxEntrySize)) {
-                throw new TypeError('maxEntrySize must be a positive integer if specified');
-            }
-            this.#initializeSizeTracking();
-        }
-        this.allowStale = !!allowStale;
-        this.noDeleteOnStaleGet = !!noDeleteOnStaleGet;
-        this.updateAgeOnGet = !!updateAgeOnGet;
-        this.updateAgeOnHas = !!updateAgeOnHas;
-        this.ttlResolution =
-            isPosInt(ttlResolution) || ttlResolution === 0
-                ? ttlResolution
-                : 1;
-        this.ttlAutopurge = !!ttlAutopurge;
-        this.ttl = ttl || 0;
-        if (this.ttl) {
-            if (!isPosInt(this.ttl)) {
-                throw new TypeError('ttl must be a positive integer if specified');
-            }
-            this.#initializeTTLTracking();
-        }
-        // do not allow completely unbounded caches
-        if (this.#max === 0 && this.ttl === 0 && this.#maxSize === 0) {
-            throw new TypeError('At least one of max, maxSize, or ttl is required');
-        }
-        if (!this.ttlAutopurge && !this.#max && !this.#maxSize) {
-            const code = 'LRU_CACHE_UNBOUNDED';
-            if (shouldWarn(code)) {
-                warned.add(code);
-                const msg = 'TTL caching without ttlAutopurge, max, or maxSize can ' +
-                    'result in unbounded memory consumption.';
-                emitWarning(msg, 'UnboundedCacheWarning', code, LRUCache);
-            }
-        }
-    }
-    /**
-     * Return the remaining TTL time for a given entry key
-     */
-    getRemainingTTL(key) {
-        return this.#keyMap.has(key) ? Infinity : 0;
-    }
-    #initializeTTLTracking() {
-        const ttls = new ZeroArray(this.#max);
-        const starts = new ZeroArray(this.#max);
-        this.#ttls = ttls;
-        this.#starts = starts;
-        this.#setItemTTL = (index, ttl, start = perf.now()) => {
-            starts[index] = ttl !== 0 ? start : 0;
-            ttls[index] = ttl;
-            if (ttl !== 0 && this.ttlAutopurge) {
-                const t = setTimeout(() => {
-                    if (this.#isStale(index)) {
-                        this.delete(this.#keyList[index]);
-                    }
-                }, ttl + 1);
-                // unref() not supported on all platforms
-                /* c8 ignore start */
-                if (t.unref) {
-                    t.unref();
-                }
-                /* c8 ignore stop */
-            }
-        };
-        this.#updateItemAge = index => {
-            starts[index] = ttls[index] !== 0 ? perf.now() : 0;
-        };
-        this.#statusTTL = (status, index) => {
-            if (ttls[index]) {
-                const ttl = ttls[index];
-                const start = starts[index];
-                status.ttl = ttl;
-                status.start = start;
-                status.now = cachedNow || getNow();
-                const age = status.now - start;
-                status.remainingTTL = ttl - age;
-            }
-        };
-        // debounce calls to perf.now() to 1s so we're not hitting
-        // that costly call repeatedly.
-        let cachedNow = 0;
-        const getNow = () => {
-            const n = perf.now();
-            if (this.ttlResolution > 0) {
-                cachedNow = n;
-                const t = setTimeout(() => (cachedNow = 0), this.ttlResolution);
-                // not available on all platforms
-                /* c8 ignore start */
-                if (t.unref) {
-                    t.unref();
-                }
-                /* c8 ignore stop */
-            }
-            return n;
-        };
-        this.getRemainingTTL = key => {
-            const index = this.#keyMap.get(key);
-            if (index === undefined) {
-                return 0;
-            }
-            const ttl = ttls[index];
-            const start = starts[index];
-            if (ttl === 0 || start === 0) {
-                return Infinity;
-            }
-            const age = (cachedNow || getNow()) - start;
-            return ttl - age;
-        };
-        this.#isStale = index => {
-            return (ttls[index] !== 0 &&
-                starts[index] !== 0 &&
-                (cachedNow || getNow()) - starts[index] > ttls[index]);
-        };
-    }
-    // conditionally set private methods related to TTL
-    #updateItemAge = () => { };
-    #statusTTL = () => { };
-    #setItemTTL = () => { };
-    /* c8 ignore stop */
-    #isStale = () => false;
-    #initializeSizeTracking() {
-        const sizes = new ZeroArray(this.#max);
-        this.#calculatedSize = 0;
-        this.#sizes = sizes;
-        this.#removeItemSize = index => {
-            this.#calculatedSize -= sizes[index];
-            sizes[index] = 0;
-        };
-        this.#requireSize = (k, v, size, sizeCalculation) => {
-            // provisionally accept background fetches.
-            // actual value size will be checked when they return.
-            if (this.#isBackgroundFetch(v)) {
-                return 0;
-            }
-            if (!isPosInt(size)) {
-                if (sizeCalculation) {
-                    if (typeof sizeCalculation !== 'function') {
-                        throw new TypeError('sizeCalculation must be a function');
-                    }
-                    size = sizeCalculation(v, k);
-                    if (!isPosInt(size)) {
-                        throw new TypeError('sizeCalculation return invalid (expect positive integer)');
-                    }
-                }
-                else {
-                    throw new TypeError('invalid size value (must be positive integer). ' +
-                        'When maxSize or maxEntrySize is used, sizeCalculation ' +
-                        'or size must be set.');
-                }
-            }
-            return size;
-        };
-        this.#addItemSize = (index, size, status) => {
-            sizes[index] = size;
-            if (this.#maxSize) {
-                const maxSize = this.#maxSize - sizes[index];
-                while (this.#calculatedSize > maxSize) {
-                    this.#evict(true);
-                }
-            }
-            this.#calculatedSize += sizes[index];
-            if (status) {
-                status.entrySize = size;
-                status.totalCalculatedSize = this.#calculatedSize;
-            }
-        };
-    }
-    #removeItemSize = _i => { };
-    #addItemSize = (_i, _s, _st) => { };
-    #requireSize = (_k, _v, size, sizeCalculation) => {
-        if (size || sizeCalculation) {
-            throw new TypeError('cannot set size without setting maxSize or maxEntrySize on cache');
-        }
-        return 0;
-    };
-    *#indexes({ allowStale = this.allowStale } = {}) {
-        if (this.#size) {
-            for (let i = this.#tail; true;) {
-                if (!this.#isValidIndex(i)) {
-                    break;
-                }
-                if (allowStale || !this.#isStale(i)) {
-                    yield i;
-                }
-                if (i === this.#head) {
-                    break;
-                }
-                else {
-                    i = this.#prev[i];
-                }
-            }
-        }
-    }
-    *#rindexes({ allowStale = this.allowStale } = {}) {
-        if (this.#size) {
-            for (let i = this.#head; true;) {
-                if (!this.#isValidIndex(i)) {
-                    break;
-                }
-                if (allowStale || !this.#isStale(i)) {
-                    yield i;
-                }
-                if (i === this.#tail) {
-                    break;
-                }
-                else {
-                    i = this.#next[i];
-                }
-            }
-        }
-    }
-    #isValidIndex(index) {
-        return (index !== undefined &&
-            this.#keyMap.get(this.#keyList[index]) === index);
-    }
-    /**
-     * Return a generator yielding `[key, value]` pairs,
-     * in order from most recently used to least recently used.
-     */
-    *entries() {
-        for (const i of this.#indexes()) {
-            if (this.#valList[i] !== undefined &&
-                this.#keyList[i] !== undefined &&
-                !this.#isBackgroundFetch(this.#valList[i])) {
-                yield [this.#keyList[i], this.#valList[i]];
-            }
-        }
-    }
-    /**
-     * Inverse order version of {@link LRUCache.entries}
-     *
-     * Return a generator yielding `[key, value]` pairs,
-     * in order from least recently used to most recently used.
-     */
-    *rentries() {
-        for (const i of this.#rindexes()) {
-            if (this.#valList[i] !== undefined &&
-                this.#keyList[i] !== undefined &&
-                !this.#isBackgroundFetch(this.#valList[i])) {
-                yield [this.#keyList[i], this.#valList[i]];
-            }
-        }
-    }
-    /**
-     * Return a generator yielding the keys in the cache,
-     * in order from most recently used to least recently used.
-     */
-    *keys() {
-        for (const i of this.#indexes()) {
-            const k = this.#keyList[i];
-            if (k !== undefined &&
-                !this.#isBackgroundFetch(this.#valList[i])) {
-                yield k;
-            }
-        }
-    }
-    /**
-     * Inverse order version of {@link LRUCache.keys}
-     *
-     * Return a generator yielding the keys in the cache,
-     * in order from least recently used to most recently used.
-     */
-    *rkeys() {
-        for (const i of this.#rindexes()) {
-            const k = this.#keyList[i];
-            if (k !== undefined &&
-                !this.#isBackgroundFetch(this.#valList[i])) {
-                yield k;
-            }
-        }
-    }
-    /**
-     * Return a generator yielding the values in the cache,
-     * in order from most recently used to least recently used.
-     */
-    *values() {
-        for (const i of this.#indexes()) {
-            const v = this.#valList[i];
-            if (v !== undefined &&
-                !this.#isBackgroundFetch(this.#valList[i])) {
-                yield this.#valList[i];
-            }
-        }
-    }
-    /**
-     * Inverse order version of {@link LRUCache.values}
-     *
-     * Return a generator yielding the values in the cache,
-     * in order from least recently used to most recently used.
-     */
-    *rvalues() {
-        for (const i of this.#rindexes()) {
-            const v = this.#valList[i];
-            if (v !== undefined &&
-                !this.#isBackgroundFetch(this.#valList[i])) {
-                yield this.#valList[i];
-            }
-        }
-    }
-    /**
-     * Iterating over the cache itself yields the same results as
-     * {@link LRUCache.entries}
-     */
-    [Symbol.iterator]() {
-        return this.entries();
-    }
-    /**
-     * Find a value for which the supplied fn method returns a truthy value,
-     * similar to Array.find().  fn is called as fn(value, key, cache).
-     */
-    find(fn, getOptions = {}) {
-        for (const i of this.#indexes()) {
-            const v = this.#valList[i];
-            const value = this.#isBackgroundFetch(v)
-                ? v.__staleWhileFetching
-                : v;
-            if (value === undefined)
-                continue;
-            if (fn(value, this.#keyList[i], this)) {
-                return this.get(this.#keyList[i], getOptions);
-            }
-        }
-    }
-    /**
-     * Call the supplied function on each item in the cache, in order from
-     * most recently used to least recently used.  fn is called as
-     * fn(value, key, cache).  Does not update age or recenty of use.
-     * Does not iterate over stale values.
-     */
-    forEach(fn, thisp = this) {
-        for (const i of this.#indexes()) {
-            const v = this.#valList[i];
-            const value = this.#isBackgroundFetch(v)
-                ? v.__staleWhileFetching
-                : v;
-            if (value === undefined)
-                continue;
-            fn.call(thisp, value, this.#keyList[i], this);
-        }
-    }
-    /**
-     * The same as {@link LRUCache.forEach} but items are iterated over in
-     * reverse order.  (ie, less recently used items are iterated over first.)
-     */
-    rforEach(fn, thisp = this) {
-        for (const i of this.#rindexes()) {
-            const v = this.#valList[i];
-            const value = this.#isBackgroundFetch(v)
-                ? v.__staleWhileFetching
-                : v;
-            if (value === undefined)
-                continue;
-            fn.call(thisp, value, this.#keyList[i], this);
-        }
-    }
-    /**
-     * Delete any stale entries. Returns true if anything was removed,
-     * false otherwise.
-     */
-    purgeStale() {
-        let deleted = false;
-        for (const i of this.#rindexes({ allowStale: true })) {
-            if (this.#isStale(i)) {
-                this.delete(this.#keyList[i]);
-                deleted = true;
-            }
-        }
-        return deleted;
-    }
-    /**
-     * Return an array of [key, {@link LRUCache.Entry}] tuples which can be
-     * passed to cache.load()
-     */
-    dump() {
-        const arr = [];
-        for (const i of this.#indexes({ allowStale: true })) {
-            const key = this.#keyList[i];
-            const v = this.#valList[i];
-            const value = this.#isBackgroundFetch(v)
-                ? v.__staleWhileFetching
-                : v;
-            if (value === undefined || key === undefined)
-                continue;
-            const entry = { value };
-            if (this.#ttls && this.#starts) {
-                entry.ttl = this.#ttls[i];
-                // always dump the start relative to a portable timestamp
-                // it's ok for this to be a bit slow, it's a rare operation.
-                const age = perf.now() - this.#starts[i];
-                entry.start = Math.floor(Date.now() - age);
-            }
-            if (this.#sizes) {
-                entry.size = this.#sizes[i];
-            }
-            arr.unshift([key, entry]);
-        }
-        return arr;
-    }
-    /**
-     * Reset the cache and load in the items in entries in the order listed.
-     * Note that the shape of the resulting cache may be different if the
-     * same options are not used in both caches.
-     */
-    load(arr) {
-        this.clear();
-        for (const [key, entry] of arr) {
-            if (entry.start) {
-                // entry.start is a portable timestamp, but we may be using
-                // node's performance.now(), so calculate the offset, so that
-                // we get the intended remaining TTL, no matter how long it's
-                // been on ice.
-                //
-                // it's ok for this to be a bit slow, it's a rare operation.
-                const age = Date.now() - entry.start;
-                entry.start = perf.now() - age;
-            }
-            this.set(key, entry.value, entry);
-        }
-    }
-    /**
-     * Add a value to the cache.
-     *
-     * Note: if `undefined` is specified as a value, this is an alias for
-     * {@link LRUCache#delete}
-     */
-    set(k, v, setOptions = {}) {
-        if (v === undefined) {
-            this.delete(k);
-            return this;
-        }
-        const { ttl = this.ttl, start, noDisposeOnSet = this.noDisposeOnSet, sizeCalculation = this.sizeCalculation, status, } = setOptions;
-        let { noUpdateTTL = this.noUpdateTTL } = setOptions;
-        const size = this.#requireSize(k, v, setOptions.size || 0, sizeCalculation);
-        // if the item doesn't fit, don't do anything
-        // NB: maxEntrySize set to maxSize by default
-        if (this.maxEntrySize && size > this.maxEntrySize) {
-            if (status) {
-                status.set = 'miss';
-                status.maxEntrySizeExceeded = true;
-            }
-            // have to delete, in case something is there already.
-            this.delete(k);
-            return this;
-        }
-        let index = this.#size === 0 ? undefined : this.#keyMap.get(k);
-        if (index === undefined) {
-            // addition
-            index = (this.#size === 0
-                ? this.#tail
-                : this.#free.length !== 0
-                    ? this.#free.pop()
-                    : this.#size === this.#max
-                        ? this.#evict(false)
-                        : this.#size);
-            this.#keyList[index] = k;
-            this.#valList[index] = v;
-            this.#keyMap.set(k, index);
-            this.#next[this.#tail] = index;
-            this.#prev[index] = this.#tail;
-            this.#tail = index;
-            this.#size++;
-            this.#addItemSize(index, size, status);
-            if (status)
-                status.set = 'add';
-            noUpdateTTL = false;
-        }
-        else {
-            // update
-            this.#moveToTail(index);
-            const oldVal = this.#valList[index];
-            if (v !== oldVal) {
-                if (this.#hasFetchMethod && this.#isBackgroundFetch(oldVal)) {
-                    oldVal.__abortController.abort(new Error('replaced'));
-                }
-                else if (!noDisposeOnSet) {
-                    if (this.#hasDispose) {
-                        this.#dispose?.(oldVal, k, 'set');
-                    }
-                    if (this.#hasDisposeAfter) {
-                        this.#disposed?.push([oldVal, k, 'set']);
-                    }
-                }
-                this.#removeItemSize(index);
-                this.#addItemSize(index, size, status);
-                this.#valList[index] = v;
-                if (status) {
-                    status.set = 'replace';
-                    const oldValue = oldVal && this.#isBackgroundFetch(oldVal)
-                        ? oldVal.__staleWhileFetching
-                        : oldVal;
-                    if (oldValue !== undefined)
-                        status.oldValue = oldValue;
-                }
-            }
-            else if (status) {
-                status.set = 'update';
-            }
-        }
-        if (ttl !== 0 && !this.#ttls) {
-            this.#initializeTTLTracking();
-        }
-        if (this.#ttls) {
-            if (!noUpdateTTL) {
-                this.#setItemTTL(index, ttl, start);
-            }
-            if (status)
-                this.#statusTTL(status, index);
-        }
-        if (!noDisposeOnSet && this.#hasDisposeAfter && this.#disposed) {
-            const dt = this.#disposed;
-            let task;
-            while ((task = dt?.shift())) {
-                this.#disposeAfter?.(...task);
-            }
-        }
-        return this;
-    }
-    /**
-     * Evict the least recently used item, returning its value or
-     * `undefined` if cache is empty.
-     */
-    pop() {
-        try {
-            while (this.#size) {
-                const val = this.#valList[this.#head];
-                this.#evict(true);
-                if (this.#isBackgroundFetch(val)) {
-                    if (val.__staleWhileFetching) {
-                        return val.__staleWhileFetching;
-                    }
-                }
-                else if (val !== undefined) {
-                    return val;
-                }
-            }
-        }
-        finally {
-            if (this.#hasDisposeAfter && this.#disposed) {
-                const dt = this.#disposed;
-                let task;
-                while ((task = dt?.shift())) {
-                    this.#disposeAfter?.(...task);
-                }
-            }
-        }
-    }
-    #evict(free) {
-        const head = this.#head;
-        const k = this.#keyList[head];
-        const v = this.#valList[head];
-        if (this.#hasFetchMethod && this.#isBackgroundFetch(v)) {
-            v.__abortController.abort(new Error('evicted'));
-        }
-        else if (this.#hasDispose || this.#hasDisposeAfter) {
-            if (this.#hasDispose) {
-                this.#dispose?.(v, k, 'evict');
-            }
-            if (this.#hasDisposeAfter) {
-                this.#disposed?.push([v, k, 'evict']);
-            }
-        }
-        this.#removeItemSize(head);
-        // if we aren't about to use the index, then null these out
-        if (free) {
-            this.#keyList[head] = undefined;
-            this.#valList[head] = undefined;
-            this.#free.push(head);
-        }
-        if (this.#size === 1) {
-            this.#head = this.#tail = 0;
-            this.#free.length = 0;
-        }
-        else {
-            this.#head = this.#next[head];
-        }
-        this.#keyMap.delete(k);
-        this.#size--;
-        return head;
-    }
-    /**
-     * Check if a key is in the cache, without updating the recency of use.
-     * Will return false if the item is stale, even though it is technically
-     * in the cache.
-     *
-     * Will not update item age unless
-     * {@link LRUCache.OptionsBase.updateAgeOnHas} is set.
-     */
-    has(k, hasOptions = {}) {
-        const { updateAgeOnHas = this.updateAgeOnHas, status } = hasOptions;
-        const index = this.#keyMap.get(k);
-        if (index !== undefined) {
-            const v = this.#valList[index];
-            if (this.#isBackgroundFetch(v) &&
-                v.__staleWhileFetching === undefined) {
-                return false;
-            }
-            if (!this.#isStale(index)) {
-                if (updateAgeOnHas) {
-                    this.#updateItemAge(index);
-                }
-                if (status) {
-                    status.has = 'hit';
-                    this.#statusTTL(status, index);
-                }
-                return true;
-            }
-            else if (status) {
-                status.has = 'stale';
-                this.#statusTTL(status, index);
-            }
-        }
-        else if (status) {
-            status.has = 'miss';
-        }
-        return false;
-    }
-    /**
-     * Like {@link LRUCache#get} but doesn't update recency or delete stale
-     * items.
-     *
-     * Returns `undefined` if the item is stale, unless
-     * {@link LRUCache.OptionsBase.allowStale} is set.
-     */
-    peek(k, peekOptions = {}) {
-        const { allowStale = this.allowStale } = peekOptions;
-        const index = this.#keyMap.get(k);
-        if (index !== undefined &&
-            (allowStale || !this.#isStale(index))) {
-            const v = this.#valList[index];
-            // either stale and allowed, or forcing a refresh of non-stale value
-            return this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
-        }
-    }
-    #backgroundFetch(k, index, options, context) {
-        const v = index === undefined ? undefined : this.#valList[index];
-        if (this.#isBackgroundFetch(v)) {
-            return v;
-        }
-        const ac = new AC();
-        const { signal } = options;
-        // when/if our AC signals, then stop listening to theirs.
-        signal?.addEventListener('abort', () => ac.abort(signal.reason), {
-            signal: ac.signal,
-        });
-        const fetchOpts = {
-            signal: ac.signal,
-            options,
-            context,
-        };
-        const cb = (v, updateCache = false) => {
-            const { aborted } = ac.signal;
-            const ignoreAbort = options.ignoreFetchAbort && v !== undefined;
-            if (options.status) {
-                if (aborted && !updateCache) {
-                    options.status.fetchAborted = true;
-                    options.status.fetchError = ac.signal.reason;
-                    if (ignoreAbort)
-                        options.status.fetchAbortIgnored = true;
-                }
-                else {
-                    options.status.fetchResolved = true;
-                }
-            }
-            if (aborted && !ignoreAbort && !updateCache) {
-                return fetchFail(ac.signal.reason);
-            }
-            // either we didn't abort, and are still here, or we did, and ignored
-            const bf = p;
-            if (this.#valList[index] === p) {
-                if (v === undefined) {
-                    if (bf.__staleWhileFetching) {
-                        this.#valList[index] = bf.__staleWhileFetching;
-                    }
-                    else {
-                        this.delete(k);
-                    }
-                }
-                else {
-                    if (options.status)
-                        options.status.fetchUpdated = true;
-                    this.set(k, v, fetchOpts.options);
-                }
-            }
-            return v;
-        };
-        const eb = (er) => {
-            if (options.status) {
-                options.status.fetchRejected = true;
-                options.status.fetchError = er;
-            }
-            return fetchFail(er);
-        };
-        const fetchFail = (er) => {
-            const { aborted } = ac.signal;
-            const allowStaleAborted = aborted && options.allowStaleOnFetchAbort;
-            const allowStale = allowStaleAborted || options.allowStaleOnFetchRejection;
-            const noDelete = allowStale || options.noDeleteOnFetchRejection;
-            const bf = p;
-            if (this.#valList[index] === p) {
-                // if we allow stale on fetch rejections, then we need to ensure that
-                // the stale value is not removed from the cache when the fetch fails.
-                const del = !noDelete || bf.__staleWhileFetching === undefined;
-                if (del) {
-                    this.delete(k);
-                }
-                else if (!allowStaleAborted) {
-                    // still replace the *promise* with the stale value,
-                    // since we are done with the promise at this point.
-                    // leave it untouched if we're still waiting for an
-                    // aborted background fetch that hasn't yet returned.
-                    this.#valList[index] = bf.__staleWhileFetching;
-                }
-            }
-            if (allowStale) {
-                if (options.status && bf.__staleWhileFetching !== undefined) {
-                    options.status.returnedStale = true;
-                }
-                return bf.__staleWhileFetching;
-            }
-            else if (bf.__returned === bf) {
-                throw er;
-            }
-        };
-        const pcall = (res, rej) => {
-            const fmp = this.#fetchMethod?.(k, v, fetchOpts);
-            if (fmp && fmp instanceof Promise) {
-                fmp.then(v => res(v), rej);
-            }
-            // ignored, we go until we finish, regardless.
-            // defer check until we are actually aborting,
-            // so fetchMethod can override.
-            ac.signal.addEventListener('abort', () => {
-                if (!options.ignoreFetchAbort ||
-                    options.allowStaleOnFetchAbort) {
-                    res();
-                    // when it eventually resolves, update the cache.
-                    if (options.allowStaleOnFetchAbort) {
-                        res = v => cb(v, true);
-                    }
-                }
-            });
-        };
-        if (options.status)
-            options.status.fetchDispatched = true;
-        const p = new Promise(pcall).then(cb, eb);
-        const bf = Object.assign(p, {
-            __abortController: ac,
-            __staleWhileFetching: v,
-            __returned: undefined,
-        });
-        if (index === undefined) {
-            // internal, don't expose status.
-            this.set(k, bf, { ...fetchOpts.options, status: undefined });
-            index = this.#keyMap.get(k);
-        }
-        else {
-            this.#valList[index] = bf;
-        }
-        return bf;
-    }
-    #isBackgroundFetch(p) {
-        if (!this.#hasFetchMethod)
-            return false;
-        const b = p;
-        return (!!b &&
-            b instanceof Promise &&
-            b.hasOwnProperty('__staleWhileFetching') &&
-            b.__abortController instanceof AC);
-    }
-    async fetch(k, fetchOptions = {}) {
-        const {
-        // get options
-        allowStale = this.allowStale, updateAgeOnGet = this.updateAgeOnGet, noDeleteOnStaleGet = this.noDeleteOnStaleGet,
-        // set options
-        ttl = this.ttl, noDisposeOnSet = this.noDisposeOnSet, size = 0, sizeCalculation = this.sizeCalculation, noUpdateTTL = this.noUpdateTTL,
-        // fetch exclusive options
-        noDeleteOnFetchRejection = this.noDeleteOnFetchRejection, allowStaleOnFetchRejection = this.allowStaleOnFetchRejection, ignoreFetchAbort = this.ignoreFetchAbort, allowStaleOnFetchAbort = this.allowStaleOnFetchAbort, context, forceRefresh = false, status, signal, } = fetchOptions;
-        if (!this.#hasFetchMethod) {
-            if (status)
-                status.fetch = 'get';
-            return this.get(k, {
-                allowStale,
-                updateAgeOnGet,
-                noDeleteOnStaleGet,
-                status,
-            });
-        }
-        const options = {
-            allowStale,
-            updateAgeOnGet,
-            noDeleteOnStaleGet,
-            ttl,
-            noDisposeOnSet,
-            size,
-            sizeCalculation,
-            noUpdateTTL,
-            noDeleteOnFetchRejection,
-            allowStaleOnFetchRejection,
-            allowStaleOnFetchAbort,
-            ignoreFetchAbort,
-            status,
-            signal,
-        };
-        let index = this.#keyMap.get(k);
-        if (index === undefined) {
-            if (status)
-                status.fetch = 'miss';
-            const p = this.#backgroundFetch(k, index, options, context);
-            return (p.__returned = p);
-        }
-        else {
-            // in cache, maybe already fetching
-            const v = this.#valList[index];
-            if (this.#isBackgroundFetch(v)) {
-                const stale = allowStale && v.__staleWhileFetching !== undefined;
-                if (status) {
-                    status.fetch = 'inflight';
-                    if (stale)
-                        status.returnedStale = true;
-                }
-                return stale ? v.__staleWhileFetching : (v.__returned = v);
-            }
-            // if we force a refresh, that means do NOT serve the cached value,
-            // unless we are already in the process of refreshing the cache.
-            const isStale = this.#isStale(index);
-            if (!forceRefresh && !isStale) {
-                if (status)
-                    status.fetch = 'hit';
-                this.#moveToTail(index);
-                if (updateAgeOnGet) {
-                    this.#updateItemAge(index);
-                }
-                if (status)
-                    this.#statusTTL(status, index);
-                return v;
-            }
-            // ok, it is stale or a forced refresh, and not already fetching.
-            // refresh the cache.
-            const p = this.#backgroundFetch(k, index, options, context);
-            const hasStale = p.__staleWhileFetching !== undefined;
-            const staleVal = hasStale && allowStale;
-            if (status) {
-                status.fetch = isStale ? 'stale' : 'refresh';
-                if (staleVal && isStale)
-                    status.returnedStale = true;
-            }
-            return staleVal ? p.__staleWhileFetching : (p.__returned = p);
-        }
-    }
-    /**
-     * Return a value from the cache. Will update the recency of the cache
-     * entry found.
-     *
-     * If the key is not found, get() will return `undefined`.
-     */
-    get(k, getOptions = {}) {
-        const { allowStale = this.allowStale, updateAgeOnGet = this.updateAgeOnGet, noDeleteOnStaleGet = this.noDeleteOnStaleGet, status, } = getOptions;
-        const index = this.#keyMap.get(k);
-        if (index !== undefined) {
-            const value = this.#valList[index];
-            const fetching = this.#isBackgroundFetch(value);
-            if (status)
-                this.#statusTTL(status, index);
-            if (this.#isStale(index)) {
-                if (status)
-                    status.get = 'stale';
-                // delete only if not an in-flight background fetch
-                if (!fetching) {
-                    if (!noDeleteOnStaleGet) {
-                        this.delete(k);
-                    }
-                    if (status && allowStale)
-                        status.returnedStale = true;
-                    return allowStale ? value : undefined;
-                }
-                else {
-                    if (status &&
-                        allowStale &&
-                        value.__staleWhileFetching !== undefined) {
-                        status.returnedStale = true;
-                    }
-                    return allowStale ? value.__staleWhileFetching : undefined;
-                }
-            }
-            else {
-                if (status)
-                    status.get = 'hit';
-                // if we're currently fetching it, we don't actually have it yet
-                // it's not stale, which means this isn't a staleWhileRefetching.
-                // If it's not stale, and fetching, AND has a __staleWhileFetching
-                // value, then that means the user fetched with {forceRefresh:true},
-                // so it's safe to return that value.
-                if (fetching) {
-                    return value.__staleWhileFetching;
-                }
-                this.#moveToTail(index);
-                if (updateAgeOnGet) {
-                    this.#updateItemAge(index);
-                }
-                return value;
-            }
-        }
-        else if (status) {
-            status.get = 'miss';
-        }
-    }
-    #connect(p, n) {
-        this.#prev[n] = p;
-        this.#next[p] = n;
-    }
-    #moveToTail(index) {
-        // if tail already, nothing to do
-        // if head, move head to next[index]
-        // else
-        //   move next[prev[index]] to next[index] (head has no prev)
-        //   move prev[next[index]] to prev[index]
-        // prev[index] = tail
-        // next[tail] = index
-        // tail = index
-        if (index !== this.#tail) {
-            if (index === this.#head) {
-                this.#head = this.#next[index];
-            }
-            else {
-                this.#connect(this.#prev[index], this.#next[index]);
-            }
-            this.#connect(this.#tail, index);
-            this.#tail = index;
-        }
-    }
-    /**
-     * Deletes a key out of the cache.
-     * Returns true if the key was deleted, false otherwise.
-     */
-    delete(k) {
-        let deleted = false;
-        if (this.#size !== 0) {
-            const index = this.#keyMap.get(k);
-            if (index !== undefined) {
-                deleted = true;
-                if (this.#size === 1) {
-                    this.clear();
-                }
-                else {
-                    this.#removeItemSize(index);
-                    const v = this.#valList[index];
-                    if (this.#isBackgroundFetch(v)) {
-                        v.__abortController.abort(new Error('deleted'));
-                    }
-                    else if (this.#hasDispose || this.#hasDisposeAfter) {
-                        if (this.#hasDispose) {
-                            this.#dispose?.(v, k, 'delete');
-                        }
-                        if (this.#hasDisposeAfter) {
-                            this.#disposed?.push([v, k, 'delete']);
-                        }
-                    }
-                    this.#keyMap.delete(k);
-                    this.#keyList[index] = undefined;
-                    this.#valList[index] = undefined;
-                    if (index === this.#tail) {
-                        this.#tail = this.#prev[index];
-                    }
-                    else if (index === this.#head) {
-                        this.#head = this.#next[index];
-                    }
-                    else {
-                        this.#next[this.#prev[index]] = this.#next[index];
-                        this.#prev[this.#next[index]] = this.#prev[index];
-                    }
-                    this.#size--;
-                    this.#free.push(index);
-                }
-            }
-        }
-        if (this.#hasDisposeAfter && this.#disposed?.length) {
-            const dt = this.#disposed;
-            let task;
-            while ((task = dt?.shift())) {
-                this.#disposeAfter?.(...task);
-            }
-        }
-        return deleted;
-    }
-    /**
-     * Clear the cache entirely, throwing away all values.
-     */
-    clear() {
-        for (const index of this.#rindexes({ allowStale: true })) {
-            const v = this.#valList[index];
-            if (this.#isBackgroundFetch(v)) {
-                v.__abortController.abort(new Error('deleted'));
-            }
-            else {
-                const k = this.#keyList[index];
-                if (this.#hasDispose) {
-                    this.#dispose?.(v, k, 'delete');
-                }
-                if (this.#hasDisposeAfter) {
-                    this.#disposed?.push([v, k, 'delete']);
-                }
-            }
-        }
-        this.#keyMap.clear();
-        this.#valList.fill(undefined);
-        this.#keyList.fill(undefined);
-        if (this.#ttls && this.#starts) {
-            this.#ttls.fill(0);
-            this.#starts.fill(0);
-        }
-        if (this.#sizes) {
-            this.#sizes.fill(0);
-        }
-        this.#head = 0;
-        this.#tail = 0;
-        this.#free.length = 0;
-        this.#calculatedSize = 0;
-        this.#size = 0;
-        if (this.#hasDisposeAfter && this.#disposed) {
-            const dt = this.#disposed;
-            let task;
-            while ((task = dt?.shift())) {
-                this.#disposeAfter?.(...task);
-            }
-        }
-    }
-}
-//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/deps/npm/node_modules/path-scurry/node_modules/lru-cache/dist/mjs/index.min.js b/deps/npm/node_modules/path-scurry/node_modules/lru-cache/dist/mjs/index.min.js
deleted file mode 100644
index 44bd1c23b86e74..00000000000000
--- a/deps/npm/node_modules/path-scurry/node_modules/lru-cache/dist/mjs/index.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-var U=(o,t,e)=>{if(!t.has(o))throw TypeError("Cannot "+e)};var I=(o,t,e)=>(U(o,t,"read from private field"),e?e.call(o):t.get(o)),j=(o,t,e)=>{if(t.has(o))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(o):t.set(o,e)},D=(o,t,e,i)=>(U(o,t,"write to private field"),i?i.call(o,e):t.set(o,e),e);var v=typeof performance=="object"&&performance&&typeof performance.now=="function"?performance:Date,M=new Set,L=typeof process=="object"&&process?process:{},P=(o,t,e,i)=>{typeof L.emitWarning=="function"?L.emitWarning(o,t,e,i):console.error(`[${e}] ${t}: ${o}`)},R=globalThis.AbortController,N=globalThis.AbortSignal;if(typeof R>"u"){N=class{onabort;_onabort=[];reason;aborted=!1;addEventListener(i,s){this._onabort.push(s)}},R=class{constructor(){t()}signal=new N;abort(i){if(!this.signal.aborted){this.signal.reason=i,this.signal.aborted=!0;for(let s of this.signal._onabort)s(i);this.signal.onabort?.(i)}}};let o=L.env?.LRU_CACHE_IGNORE_AC_WARNING!=="1",t=()=>{o&&(o=!1,P("AbortController is not defined. If using lru-cache in node 14, load an AbortController polyfill from the `node-abort-controller` package. A minimal polyfill is provided for use by LRUCache.fetch(), but it should not be relied upon in other contexts (eg, passing it to other APIs that use AbortController/AbortSignal might have undesirable effects). You may disable this with LRU_CACHE_IGNORE_AC_WARNING=1 in the env.","NO_ABORT_CONTROLLER","ENOTSUP",t))}}var V=o=>!M.has(o),Y=Symbol("type"),m=o=>o&&o===Math.floor(o)&&o>0&&isFinite(o),k=o=>m(o)?o<=Math.pow(2,8)?Uint8Array:o<=Math.pow(2,16)?Uint16Array:o<=Math.pow(2,32)?Uint32Array:o<=Number.MAX_SAFE_INTEGER?z:null:null,z=class extends Array{constructor(t){super(t),this.fill(0)}},E,T=class{heap;length;static create(t){let e=k(t);if(!e)return[];D(T,E,!0);let i=new T(t,e);return D(T,E,!1),i}constructor(t,e){if(!I(T,E))throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new e(t),this.length=0}push(t){this.heap[this.length++]=t}pop(){return this.heap[--this.length]}},C=T;E=new WeakMap,j(C,E,!1);var W=class{#d;#f;#_;#g;#C;ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;#s;#p;#n;#i;#t;#l;#c;#o;#h;#w;#r;#m;#F;#S;#b;#T;#a;static unsafeExposeInternals(t){return{starts:t.#F,ttls:t.#S,sizes:t.#m,keyMap:t.#n,keyList:t.#i,valList:t.#t,next:t.#l,prev:t.#c,get head(){return t.#o},get tail(){return t.#h},free:t.#w,isBackgroundFetch:e=>t.#e(e),backgroundFetch:(e,i,s,n)=>t.#D(e,i,s,n),moveToTail:e=>t.#v(e),indexes:e=>t.#y(e),rindexes:e=>t.#A(e),isStale:e=>t.#u(e)}}get max(){return this.#d}get maxSize(){return this.#f}get calculatedSize(){return this.#p}get size(){return this.#s}get fetchMethod(){return this.#C}get dispose(){return this.#_}get disposeAfter(){return this.#g}constructor(t){let{max:e=0,ttl:i,ttlResolution:s=1,ttlAutopurge:n,updateAgeOnGet:h,updateAgeOnHas:a,allowStale:r,dispose:u,disposeAfter:b,noDisposeOnSet:f,noUpdateTTL:d,maxSize:p=0,maxEntrySize:F=0,sizeCalculation:c,fetchMethod:w,noDeleteOnFetchRejection:l,noDeleteOnStaleGet:S,allowStaleOnFetchRejection:y,allowStaleOnFetchAbort:g,ignoreFetchAbort:_}=t;if(e!==0&&!m(e))throw new TypeError("max option must be a nonnegative integer");let O=e?k(e):Array;if(!O)throw new Error("invalid max value: "+e);if(this.#d=e,this.#f=p,this.maxEntrySize=F||this.#f,this.sizeCalculation=c,this.sizeCalculation){if(!this.#f&&!this.maxEntrySize)throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if(typeof this.sizeCalculation!="function")throw new TypeError("sizeCalculation set to non-function")}if(w!==void 0&&typeof w!="function")throw new TypeError("fetchMethod must be a function if specified");if(this.#C=w,this.#T=!!w,this.#n=new Map,this.#i=new Array(e).fill(void 0),this.#t=new Array(e).fill(void 0),this.#l=new O(e),this.#c=new O(e),this.#o=0,this.#h=0,this.#w=C.create(e),this.#s=0,this.#p=0,typeof u=="function"&&(this.#_=u),typeof b=="function"?(this.#g=b,this.#r=[]):(this.#g=void 0,this.#r=void 0),this.#b=!!this.#_,this.#a=!!this.#g,this.noDisposeOnSet=!!f,this.noUpdateTTL=!!d,this.noDeleteOnFetchRejection=!!l,this.allowStaleOnFetchRejection=!!y,this.allowStaleOnFetchAbort=!!g,this.ignoreFetchAbort=!!_,this.maxEntrySize!==0){if(this.#f!==0&&!m(this.#f))throw new TypeError("maxSize must be a positive integer if specified");if(!m(this.maxEntrySize))throw new TypeError("maxEntrySize must be a positive integer if specified");this.#j()}if(this.allowStale=!!r,this.noDeleteOnStaleGet=!!S,this.updateAgeOnGet=!!h,this.updateAgeOnHas=!!a,this.ttlResolution=m(s)||s===0?s:1,this.ttlAutopurge=!!n,this.ttl=i||0,this.ttl){if(!m(this.ttl))throw new TypeError("ttl must be a positive integer if specified");this.#L()}if(this.#d===0&&this.ttl===0&&this.#f===0)throw new TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#d&&!this.#f){let A="LRU_CACHE_UNBOUNDED";V(A)&&(M.add(A),P("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning",A,W))}}getRemainingTTL(t){return this.#n.has(t)?1/0:0}#L(){let t=new z(this.#d),e=new z(this.#d);this.#S=t,this.#F=e,this.#x=(n,h,a=v.now())=>{if(e[n]=h!==0?a:0,t[n]=h,h!==0&&this.ttlAutopurge){let r=setTimeout(()=>{this.#u(n)&&this.delete(this.#i[n])},h+1);r.unref&&r.unref()}},this.#z=n=>{e[n]=t[n]!==0?v.now():0},this.#O=(n,h)=>{if(t[h]){let a=t[h],r=e[h];n.ttl=a,n.start=r,n.now=i||s();let u=n.now-r;n.remainingTTL=a-u}};let i=0,s=()=>{let n=v.now();if(this.ttlResolution>0){i=n;let h=setTimeout(()=>i=0,this.ttlResolution);h.unref&&h.unref()}return n};this.getRemainingTTL=n=>{let h=this.#n.get(n);if(h===void 0)return 0;let a=t[h],r=e[h];if(a===0||r===0)return 1/0;let u=(i||s())-r;return a-u},this.#u=n=>t[n]!==0&&e[n]!==0&&(i||s())-e[n]>t[n]}#z=()=>{};#O=()=>{};#x=()=>{};#u=()=>!1;#j(){let t=new z(this.#d);this.#p=0,this.#m=t,this.#E=e=>{this.#p-=t[e],t[e]=0},this.#G=(e,i,s,n)=>{if(this.#e(i))return 0;if(!m(s))if(n){if(typeof n!="function")throw new TypeError("sizeCalculation must be a function");if(s=n(i,e),!m(s))throw new TypeError("sizeCalculation return invalid (expect positive integer)")}else throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.");return s},this.#R=(e,i,s)=>{if(t[e]=i,this.#f){let n=this.#f-t[e];for(;this.#p>n;)this.#W(!0)}this.#p+=t[e],s&&(s.entrySize=i,s.totalCalculatedSize=this.#p)}}#E=t=>{};#R=(t,e,i)=>{};#G=(t,e,i,s)=>{if(i||s)throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#y({allowStale:t=this.allowStale}={}){if(this.#s)for(let e=this.#h;!(!this.#U(e)||((t||!this.#u(e))&&(yield e),e===this.#o));)e=this.#c[e]}*#A({allowStale:t=this.allowStale}={}){if(this.#s)for(let e=this.#o;!(!this.#U(e)||((t||!this.#u(e))&&(yield e),e===this.#h));)e=this.#l[e]}#U(t){return t!==void 0&&this.#n.get(this.#i[t])===t}*entries(){for(let t of this.#y())this.#t[t]!==void 0&&this.#i[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#i[t],this.#t[t]])}*rentries(){for(let t of this.#A())this.#t[t]!==void 0&&this.#i[t]!==void 0&&!this.#e(this.#t[t])&&(yield[this.#i[t],this.#t[t]])}*keys(){for(let t of this.#y()){let e=this.#i[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*rkeys(){for(let t of this.#A()){let e=this.#i[t];e!==void 0&&!this.#e(this.#t[t])&&(yield e)}}*values(){for(let t of this.#y())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}*rvalues(){for(let t of this.#A())this.#t[t]!==void 0&&!this.#e(this.#t[t])&&(yield this.#t[t])}[Symbol.iterator](){return this.entries()}find(t,e={}){for(let i of this.#y()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;if(n!==void 0&&t(n,this.#i[i],this))return this.get(this.#i[i],e)}}forEach(t,e=this){for(let i of this.#y()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&t.call(e,n,this.#i[i],this)}}rforEach(t,e=this){for(let i of this.#A()){let s=this.#t[i],n=this.#e(s)?s.__staleWhileFetching:s;n!==void 0&&t.call(e,n,this.#i[i],this)}}purgeStale(){let t=!1;for(let e of this.#A({allowStale:!0}))this.#u(e)&&(this.delete(this.#i[e]),t=!0);return t}dump(){let t=[];for(let e of this.#y({allowStale:!0})){let i=this.#i[e],s=this.#t[e],n=this.#e(s)?s.__staleWhileFetching:s;if(n===void 0||i===void 0)continue;let h={value:n};if(this.#S&&this.#F){h.ttl=this.#S[e];let a=v.now()-this.#F[e];h.start=Math.floor(Date.now()-a)}this.#m&&(h.size=this.#m[e]),t.unshift([i,h])}return t}load(t){this.clear();for(let[e,i]of t){if(i.start){let s=Date.now()-i.start;i.start=v.now()-s}this.set(e,i.value,i)}}set(t,e,i={}){if(e===void 0)return this.delete(t),this;let{ttl:s=this.ttl,start:n,noDisposeOnSet:h=this.noDisposeOnSet,sizeCalculation:a=this.sizeCalculation,status:r}=i,{noUpdateTTL:u=this.noUpdateTTL}=i,b=this.#G(t,e,i.size||0,a);if(this.maxEntrySize&&b>this.maxEntrySize)return r&&(r.set="miss",r.maxEntrySizeExceeded=!0),this.delete(t),this;let f=this.#s===0?void 0:this.#n.get(t);if(f===void 0)f=this.#s===0?this.#h:this.#w.length!==0?this.#w.pop():this.#s===this.#d?this.#W(!1):this.#s,this.#i[f]=t,this.#t[f]=e,this.#n.set(t,f),this.#l[this.#h]=f,this.#c[f]=this.#h,this.#h=f,this.#s++,this.#R(f,b,r),r&&(r.set="add"),u=!1;else{this.#v(f);let d=this.#t[f];if(e!==d){if(this.#T&&this.#e(d)?d.__abortController.abort(new Error("replaced")):h||(this.#b&&this.#_?.(d,t,"set"),this.#a&&this.#r?.push([d,t,"set"])),this.#E(f),this.#R(f,b,r),this.#t[f]=e,r){r.set="replace";let p=d&&this.#e(d)?d.__staleWhileFetching:d;p!==void 0&&(r.oldValue=p)}}else r&&(r.set="update")}if(s!==0&&!this.#S&&this.#L(),this.#S&&(u||this.#x(f,s,n),r&&this.#O(r,f)),!h&&this.#a&&this.#r){let d=this.#r,p;for(;p=d?.shift();)this.#g?.(...p)}return this}pop(){try{for(;this.#s;){let t=this.#t[this.#o];if(this.#W(!0),this.#e(t)){if(t.__staleWhileFetching)return t.__staleWhileFetching}else if(t!==void 0)return t}}finally{if(this.#a&&this.#r){let t=this.#r,e;for(;e=t?.shift();)this.#g?.(...e)}}}#W(t){let e=this.#o,i=this.#i[e],s=this.#t[e];return this.#T&&this.#e(s)?s.__abortController.abort(new Error("evicted")):(this.#b||this.#a)&&(this.#b&&this.#_?.(s,i,"evict"),this.#a&&this.#r?.push([s,i,"evict"])),this.#E(e),t&&(this.#i[e]=void 0,this.#t[e]=void 0,this.#w.push(e)),this.#s===1?(this.#o=this.#h=0,this.#w.length=0):this.#o=this.#l[e],this.#n.delete(i),this.#s--,e}has(t,e={}){let{updateAgeOnHas:i=this.updateAgeOnHas,status:s}=e,n=this.#n.get(t);if(n!==void 0){let h=this.#t[n];if(this.#e(h)&&h.__staleWhileFetching===void 0)return!1;if(this.#u(n))s&&(s.has="stale",this.#O(s,n));else return i&&this.#z(n),s&&(s.has="hit",this.#O(s,n)),!0}else s&&(s.has="miss");return!1}peek(t,e={}){let{allowStale:i=this.allowStale}=e,s=this.#n.get(t);if(s!==void 0&&(i||!this.#u(s))){let n=this.#t[s];return this.#e(n)?n.__staleWhileFetching:n}}#D(t,e,i,s){let n=e===void 0?void 0:this.#t[e];if(this.#e(n))return n;let h=new R,{signal:a}=i;a?.addEventListener("abort",()=>h.abort(a.reason),{signal:h.signal});let r={signal:h.signal,options:i,context:s},u=(c,w=!1)=>{let{aborted:l}=h.signal,S=i.ignoreFetchAbort&&c!==void 0;if(i.status&&(l&&!w?(i.status.fetchAborted=!0,i.status.fetchError=h.signal.reason,S&&(i.status.fetchAbortIgnored=!0)):i.status.fetchResolved=!0),l&&!S&&!w)return f(h.signal.reason);let y=p;return this.#t[e]===p&&(c===void 0?y.__staleWhileFetching?this.#t[e]=y.__staleWhileFetching:this.delete(t):(i.status&&(i.status.fetchUpdated=!0),this.set(t,c,r.options))),c},b=c=>(i.status&&(i.status.fetchRejected=!0,i.status.fetchError=c),f(c)),f=c=>{let{aborted:w}=h.signal,l=w&&i.allowStaleOnFetchAbort,S=l||i.allowStaleOnFetchRejection,y=S||i.noDeleteOnFetchRejection,g=p;if(this.#t[e]===p&&(!y||g.__staleWhileFetching===void 0?this.delete(t):l||(this.#t[e]=g.__staleWhileFetching)),S)return i.status&&g.__staleWhileFetching!==void 0&&(i.status.returnedStale=!0),g.__staleWhileFetching;if(g.__returned===g)throw c},d=(c,w)=>{let l=this.#C?.(t,n,r);l&&l instanceof Promise&&l.then(S=>c(S),w),h.signal.addEventListener("abort",()=>{(!i.ignoreFetchAbort||i.allowStaleOnFetchAbort)&&(c(),i.allowStaleOnFetchAbort&&(c=S=>u(S,!0)))})};i.status&&(i.status.fetchDispatched=!0);let p=new Promise(d).then(u,b),F=Object.assign(p,{__abortController:h,__staleWhileFetching:n,__returned:void 0});return e===void 0?(this.set(t,F,{...r.options,status:void 0}),e=this.#n.get(t)):this.#t[e]=F,F}#e(t){if(!this.#T)return!1;let e=t;return!!e&&e instanceof Promise&&e.hasOwnProperty("__staleWhileFetching")&&e.__abortController instanceof R}async fetch(t,e={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,ttl:h=this.ttl,noDisposeOnSet:a=this.noDisposeOnSet,size:r=0,sizeCalculation:u=this.sizeCalculation,noUpdateTTL:b=this.noUpdateTTL,noDeleteOnFetchRejection:f=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:d=this.allowStaleOnFetchRejection,ignoreFetchAbort:p=this.ignoreFetchAbort,allowStaleOnFetchAbort:F=this.allowStaleOnFetchAbort,context:c,forceRefresh:w=!1,status:l,signal:S}=e;if(!this.#T)return l&&(l.fetch="get"),this.get(t,{allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,status:l});let y={allowStale:i,updateAgeOnGet:s,noDeleteOnStaleGet:n,ttl:h,noDisposeOnSet:a,size:r,sizeCalculation:u,noUpdateTTL:b,noDeleteOnFetchRejection:f,allowStaleOnFetchRejection:d,allowStaleOnFetchAbort:F,ignoreFetchAbort:p,status:l,signal:S},g=this.#n.get(t);if(g===void 0){l&&(l.fetch="miss");let _=this.#D(t,g,y,c);return _.__returned=_}else{let _=this.#t[g];if(this.#e(_)){let G=i&&_.__staleWhileFetching!==void 0;return l&&(l.fetch="inflight",G&&(l.returnedStale=!0)),G?_.__staleWhileFetching:_.__returned=_}let O=this.#u(g);if(!w&&!O)return l&&(l.fetch="hit"),this.#v(g),s&&this.#z(g),l&&this.#O(l,g),_;let A=this.#D(t,g,y,c),x=A.__staleWhileFetching!==void 0&&i;return l&&(l.fetch=O?"stale":"refresh",x&&O&&(l.returnedStale=!0)),x?A.__staleWhileFetching:A.__returned=A}}get(t,e={}){let{allowStale:i=this.allowStale,updateAgeOnGet:s=this.updateAgeOnGet,noDeleteOnStaleGet:n=this.noDeleteOnStaleGet,status:h}=e,a=this.#n.get(t);if(a!==void 0){let r=this.#t[a],u=this.#e(r);return h&&this.#O(h,a),this.#u(a)?(h&&(h.get="stale"),u?(h&&i&&r.__staleWhileFetching!==void 0&&(h.returnedStale=!0),i?r.__staleWhileFetching:void 0):(n||this.delete(t),h&&i&&(h.returnedStale=!0),i?r:void 0)):(h&&(h.get="hit"),u?r.__staleWhileFetching:(this.#v(a),s&&this.#z(a),r))}else h&&(h.get="miss")}#I(t,e){this.#c[e]=t,this.#l[t]=e}#v(t){t!==this.#h&&(t===this.#o?this.#o=this.#l[t]:this.#I(this.#c[t],this.#l[t]),this.#I(this.#h,t),this.#h=t)}delete(t){let e=!1;if(this.#s!==0){let i=this.#n.get(t);if(i!==void 0)if(e=!0,this.#s===1)this.clear();else{this.#E(i);let s=this.#t[i];this.#e(s)?s.__abortController.abort(new Error("deleted")):(this.#b||this.#a)&&(this.#b&&this.#_?.(s,t,"delete"),this.#a&&this.#r?.push([s,t,"delete"])),this.#n.delete(t),this.#i[i]=void 0,this.#t[i]=void 0,i===this.#h?this.#h=this.#c[i]:i===this.#o?this.#o=this.#l[i]:(this.#l[this.#c[i]]=this.#l[i],this.#c[this.#l[i]]=this.#c[i]),this.#s--,this.#w.push(i)}}if(this.#a&&this.#r?.length){let i=this.#r,s;for(;s=i?.shift();)this.#g?.(...s)}return e}clear(){for(let t of this.#A({allowStale:!0})){let e=this.#t[t];if(this.#e(e))e.__abortController.abort(new Error("deleted"));else{let i=this.#i[t];this.#b&&this.#_?.(e,i,"delete"),this.#a&&this.#r?.push([e,i,"delete"])}}if(this.#n.clear(),this.#t.fill(void 0),this.#i.fill(void 0),this.#S&&this.#F&&(this.#S.fill(0),this.#F.fill(0)),this.#m&&this.#m.fill(0),this.#o=0,this.#h=0,this.#w.length=0,this.#p=0,this.#s=0,this.#a&&this.#r){let t=this.#r,e;for(;e=t?.shift();)this.#g?.(...e)}}};export{W as LRUCache};
-//# sourceMappingURL=index.min.js.map
diff --git a/deps/npm/node_modules/path-scurry/node_modules/lru-cache/package.json b/deps/npm/node_modules/path-scurry/node_modules/lru-cache/package.json
deleted file mode 100644
index 69a20582ff9b6f..00000000000000
--- a/deps/npm/node_modules/path-scurry/node_modules/lru-cache/package.json
+++ /dev/null
@@ -1,109 +0,0 @@
-{
-  "name": "lru-cache",
-  "description": "A cache object that deletes the least-recently-used items.",
-  "version": "9.1.1",
-  "author": "Isaac Z. Schlueter ",
-  "keywords": [
-    "mru",
-    "lru",
-    "cache"
-  ],
-  "sideEffects": false,
-  "scripts": {
-    "build": "npm run prepare",
-    "preprepare": "rm -rf dist",
-    "prepare": "tsc -p tsconfig.json && tsc -p tsconfig-esm.json",
-    "postprepare": "bash fixup.sh",
-    "pretest": "npm run prepare",
-    "presnap": "npm run prepare",
-    "test": "c8 tap",
-    "snap": "c8 tap",
-    "preversion": "npm test",
-    "postversion": "npm publish",
-    "prepublishOnly": "git push origin --follow-tags",
-    "format": "prettier --write .",
-    "typedoc": "typedoc --tsconfig tsconfig-esm.json ./src/*.ts",
-    "benchmark-results-typedoc": "bash scripts/benchmark-results-typedoc.sh",
-    "prebenchmark": "npm run prepare",
-    "benchmark": "make -C benchmark",
-    "preprofile": "npm run prepare",
-    "profile": "make -C benchmark profile"
-  },
-  "main": "./dist/cjs/index.js",
-  "module": "./dist/mjs/index.js",
-  "exports": {
-    "./min": {
-      "import": {
-        "types": "./dist/mjs/index.d.ts",
-        "default": "./dist/mjs/index.min.js"
-      },
-      "require": {
-        "types": "./dist/cjs/index.d.ts",
-        "default": "./dist/cjs/index.min.js"
-      }
-    },
-    ".": {
-      "import": {
-        "types": "./dist/mjs/index.d.ts",
-        "default": "./dist/mjs/index.js"
-      },
-      "require": {
-        "types": "./dist/cjs/index.d.ts",
-        "default": "./dist/cjs/index.js"
-      }
-    }
-  },
-  "repository": "git://github.com/isaacs/node-lru-cache.git",
-  "devDependencies": {
-    "@size-limit/preset-small-lib": "^7.0.8",
-    "@types/node": "^17.0.31",
-    "@types/tap": "^15.0.6",
-    "benchmark": "^2.1.4",
-    "c8": "^7.11.2",
-    "clock-mock": "^1.0.6",
-    "esbuild": "^0.17.11",
-    "eslint-config-prettier": "^8.5.0",
-    "marked": "^4.2.12",
-    "mkdirp": "^2.1.5",
-    "prettier": "^2.6.2",
-    "size-limit": "^7.0.8",
-    "tap": "^16.3.4",
-    "ts-node": "^10.7.0",
-    "tslib": "^2.4.0",
-    "typedoc": "^0.23.24",
-    "typescript": "^4.6.4"
-  },
-  "license": "ISC",
-  "files": [
-    "dist"
-  ],
-  "engines": {
-    "node": "14 || >=16.14"
-  },
-  "prettier": {
-    "semi": false,
-    "printWidth": 70,
-    "tabWidth": 2,
-    "useTabs": false,
-    "singleQuote": true,
-    "jsxSingleQuote": false,
-    "bracketSameLine": true,
-    "arrowParens": "avoid",
-    "endOfLine": "lf"
-  },
-  "tap": {
-    "coverage": false,
-    "node-arg": [
-      "--expose-gc",
-      "--no-warnings",
-      "--loader",
-      "ts-node/esm"
-    ],
-    "ts": false
-  },
-  "size-limit": [
-    {
-      "path": "./dist/mjs/index.js"
-    }
-  ]
-}
diff --git a/deps/npm/node_modules/path-scurry/package.json b/deps/npm/node_modules/path-scurry/package.json
index 5b900825e44e00..af04f807fed2bc 100644
--- a/deps/npm/node_modules/path-scurry/package.json
+++ b/deps/npm/node_modules/path-scurry/package.json
@@ -1,6 +1,6 @@
 {
   "name": "path-scurry",
-  "version": "1.9.2",
+  "version": "1.10.1",
   "description": "walk paths fast and efficiently",
   "author": "Isaac Z. Schlueter  (https://blog.izs.me)",
   "main": "./dist/cjs/index.js",
@@ -64,7 +64,7 @@
     "eslint-config-prettier": "^8.6.0",
     "mkdirp": "^3.0.0",
     "prettier": "^2.8.3",
-    "rimraf": "^4.1.2",
+    "rimraf": "^5.0.1",
     "tap": "^16.3.4",
     "ts-node": "^10.9.1",
     "typedoc": "^0.23.24",
@@ -78,10 +78,10 @@
   },
   "repository": {
     "type": "git",
-    "url": "git+https://github.com/isaacs/path-walker"
+    "url": "git+https://github.com/isaacs/path-scurry"
   },
   "dependencies": {
-    "lru-cache": "^9.1.1",
-    "minipass": "^5.0.0 || ^6.0.2"
+    "lru-cache": "^9.1.1 || ^10.0.0",
+    "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
   }
 }
diff --git a/deps/npm/node_modules/read-package-json/package.json b/deps/npm/node_modules/read-package-json/package.json
index 90ab321d51743e..01061f2bc27921 100644
--- a/deps/npm/node_modules/read-package-json/package.json
+++ b/deps/npm/node_modules/read-package-json/package.json
@@ -1,6 +1,6 @@
 {
   "name": "read-package-json",
-  "version": "6.0.4",
+  "version": "7.0.0",
   "author": "GitHub Inc.",
   "description": "The thing npm uses to read package.json files with semantics and defaults and validation",
   "repository": {
@@ -25,12 +25,12 @@
   "dependencies": {
     "glob": "^10.2.2",
     "json-parse-even-better-errors": "^3.0.0",
-    "normalize-package-data": "^5.0.0",
+    "normalize-package-data": "^6.0.0",
     "npm-normalize-package-bin": "^3.0.0"
   },
   "devDependencies": {
     "@npmcli/eslint-config": "^4.0.0",
-    "@npmcli/template-oss": "4.15.1",
+    "@npmcli/template-oss": "4.18.0",
     "tap": "^16.0.1"
   },
   "license": "ISC",
@@ -39,7 +39,7 @@
     "lib/"
   ],
   "engines": {
-    "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+    "node": "^16.14.0 || >=18.0.0"
   },
   "tap": {
     "branches": 73,
@@ -53,7 +53,13 @@
   },
   "templateOSS": {
     "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
-    "version": "4.15.1",
-    "publish": "true"
+    "version": "4.18.0",
+    "publish": "true",
+    "ciVersions": [
+      "16.14.0",
+      "16.x",
+      "18.0.0",
+      "18.x"
+    ]
   }
 }
diff --git a/deps/npm/node_modules/readable-stream/lib/stream/promises.js b/deps/npm/node_modules/readable-stream/lib/stream/promises.js
index b85c51f47f1ce1..5d4ce15f4904b7 100644
--- a/deps/npm/node_modules/readable-stream/lib/stream/promises.js
+++ b/deps/npm/node_modules/readable-stream/lib/stream/promises.js
@@ -4,7 +4,7 @@ const { ArrayPrototypePop, Promise } = require('../ours/primordials')
 const { isIterable, isNodeStream, isWebStream } = require('../internal/streams/utils')
 const { pipelineImpl: pl } = require('../internal/streams/pipeline')
 const { finished } = require('../internal/streams/end-of-stream')
-require('stream')
+require('../../lib/stream.js')
 function pipeline(...streams) {
   return new Promise((resolve, reject) => {
     let signal
diff --git a/deps/npm/node_modules/readable-stream/package.json b/deps/npm/node_modules/readable-stream/package.json
index c4f6504cc7cc66..289f3a45a634f3 100644
--- a/deps/npm/node_modules/readable-stream/package.json
+++ b/deps/npm/node_modules/readable-stream/package.json
@@ -1,6 +1,6 @@
 {
   "name": "readable-stream",
-  "version": "4.4.0",
+  "version": "4.4.2",
   "description": "Node.js Streams, a user-land copy of the stream library from Node.js",
   "homepage": "https://github.com/nodejs/readable-stream",
   "license": "MIT",
@@ -39,6 +39,7 @@
     "test:prepare": "node test/browser/runner-prepare.mjs",
     "test:browsers": "node test/browser/runner-browser.mjs",
     "test:bundlers": "node test/browser/runner-node.mjs",
+    "test:readable-stream-only": "node readable-stream-test/runner-prepare.mjs",
     "coverage": "c8 -c ./c8.json tap --rcfile=./tap.yml test/parallel/test-*.js test/ours/test-*.js",
     "format": "prettier -w src lib test",
     "lint": "eslint src"
@@ -47,7 +48,8 @@
     "abort-controller": "^3.0.0",
     "buffer": "^6.0.3",
     "events": "^3.3.0",
-    "process": "^0.11.10"
+    "process": "^0.11.10",
+    "string_decoder": "^1.3.0"
   },
   "devDependencies": {
     "@babel/core": "^7.17.10",
diff --git a/deps/npm/node_modules/rimraf/LICENSE b/deps/npm/node_modules/rimraf/LICENSE
deleted file mode 100644
index 19129e315fe593..00000000000000
--- a/deps/npm/node_modules/rimraf/LICENSE
+++ /dev/null
@@ -1,15 +0,0 @@
-The ISC License
-
-Copyright (c) Isaac Z. Schlueter and Contributors
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/deps/npm/node_modules/rimraf/README.md b/deps/npm/node_modules/rimraf/README.md
deleted file mode 100644
index 423b8cf854ad3e..00000000000000
--- a/deps/npm/node_modules/rimraf/README.md
+++ /dev/null
@@ -1,101 +0,0 @@
-[![Build Status](https://travis-ci.org/isaacs/rimraf.svg?branch=master)](https://travis-ci.org/isaacs/rimraf) [![Dependency Status](https://david-dm.org/isaacs/rimraf.svg)](https://david-dm.org/isaacs/rimraf) [![devDependency Status](https://david-dm.org/isaacs/rimraf/dev-status.svg)](https://david-dm.org/isaacs/rimraf#info=devDependencies)
-
-The [UNIX command](http://en.wikipedia.org/wiki/Rm_(Unix)) `rm -rf` for node.
-
-Install with `npm install rimraf`, or just drop rimraf.js somewhere.
-
-## API
-
-`rimraf(f, [opts], callback)`
-
-The first parameter will be interpreted as a globbing pattern for files. If you
-want to disable globbing you can do so with `opts.disableGlob` (defaults to
-`false`). This might be handy, for instance, if you have filenames that contain
-globbing wildcard characters.
-
-The callback will be called with an error if there is one.  Certain
-errors are handled for you:
-
-* Windows: `EBUSY` and `ENOTEMPTY` - rimraf will back off a maximum of
-  `opts.maxBusyTries` times before giving up, adding 100ms of wait
-  between each attempt.  The default `maxBusyTries` is 3.
-* `ENOENT` - If the file doesn't exist, rimraf will return
-  successfully, since your desired outcome is already the case.
-* `EMFILE` - Since `readdir` requires opening a file descriptor, it's
-  possible to hit `EMFILE` if too many file descriptors are in use.
-  In the sync case, there's nothing to be done for this.  But in the
-  async case, rimraf will gradually back off with timeouts up to
-  `opts.emfileWait` ms, which defaults to 1000.
-
-## options
-
-* unlink, chmod, stat, lstat, rmdir, readdir,
-  unlinkSync, chmodSync, statSync, lstatSync, rmdirSync, readdirSync
-
-    In order to use a custom file system library, you can override
-    specific fs functions on the options object.
-
-    If any of these functions are present on the options object, then
-    the supplied function will be used instead of the default fs
-    method.
-
-    Sync methods are only relevant for `rimraf.sync()`, of course.
-
-    For example:
-
-    ```javascript
-    var myCustomFS = require('some-custom-fs')
-
-    rimraf('some-thing', myCustomFS, callback)
-    ```
-
-* maxBusyTries
-
-    If an `EBUSY`, `ENOTEMPTY`, or `EPERM` error code is encountered
-    on Windows systems, then rimraf will retry with a linear backoff
-    wait of 100ms longer on each try.  The default maxBusyTries is 3.
-
-    Only relevant for async usage.
-
-* emfileWait
-
-    If an `EMFILE` error is encountered, then rimraf will retry
-    repeatedly with a linear backoff of 1ms longer on each try, until
-    the timeout counter hits this max.  The default limit is 1000.
-
-    If you repeatedly encounter `EMFILE` errors, then consider using
-    [graceful-fs](http://npm.im/graceful-fs) in your program.
-
-    Only relevant for async usage.
-
-* glob
-
-    Set to `false` to disable [glob](http://npm.im/glob) pattern
-    matching.
-
-    Set to an object to pass options to the glob module.  The default
-    glob options are `{ nosort: true, silent: true }`.
-
-    Glob version 6 is used in this module.
-
-    Relevant for both sync and async usage.
-
-* disableGlob
-
-    Set to any non-falsey value to disable globbing entirely.
-    (Equivalent to setting `glob: false`.)
-
-## rimraf.sync
-
-It can remove stuff synchronously, too.  But that's not so good.  Use
-the async API.  It's better.
-
-## CLI
-
-If installed with `npm install rimraf -g` it can be used as a global
-command `rimraf  [ ...]` which is useful for cross platform support.
-
-## mkdirp
-
-If you need to create a directory recursively, check out
-[mkdirp](https://github.com/substack/node-mkdirp).
diff --git a/deps/npm/node_modules/rimraf/bin.js b/deps/npm/node_modules/rimraf/bin.js
deleted file mode 100755
index 023814cc93e849..00000000000000
--- a/deps/npm/node_modules/rimraf/bin.js
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/usr/bin/env node
-
-const rimraf = require('./')
-
-const path = require('path')
-
-const isRoot = arg => /^(\/|[a-zA-Z]:\\)$/.test(path.resolve(arg))
-const filterOutRoot = arg => {
-  const ok = preserveRoot === false || !isRoot(arg)
-  if (!ok) {
-    console.error(`refusing to remove ${arg}`)
-    console.error('Set --no-preserve-root to allow this')
-  }
-  return ok
-}
-
-let help = false
-let dashdash = false
-let noglob = false
-let preserveRoot = true
-const args = process.argv.slice(2).filter(arg => {
-  if (dashdash)
-    return !!arg
-  else if (arg === '--')
-    dashdash = true
-  else if (arg === '--no-glob' || arg === '-G')
-    noglob = true
-  else if (arg === '--glob' || arg === '-g')
-    noglob = false
-  else if (arg.match(/^(-+|\/)(h(elp)?|\?)$/))
-    help = true
-  else if (arg === '--preserve-root')
-    preserveRoot = true
-  else if (arg === '--no-preserve-root')
-    preserveRoot = false
-  else
-    return !!arg
-}).filter(arg => !preserveRoot || filterOutRoot(arg))
-
-const go = n => {
-  if (n >= args.length)
-    return
-  const options = noglob ? { glob: false } : {}
-  rimraf(args[n], options, er => {
-    if (er)
-      throw er
-    go(n+1)
-  })
-}
-
-if (help || args.length === 0) {
-  // If they didn't ask for help, then this is not a "success"
-  const log = help ? console.log : console.error
-  log('Usage: rimraf  [ ...]')
-  log('')
-  log('  Deletes all files and folders at "path" recursively.')
-  log('')
-  log('Options:')
-  log('')
-  log('  -h, --help          Display this usage info')
-  log('  -G, --no-glob       Do not expand glob patterns in arguments')
-  log('  -g, --glob          Expand glob patterns in arguments (default)')
-  log('  --preserve-root     Do not remove \'/\' (default)')
-  log('  --no-preserve-root  Do not treat \'/\' specially')
-  log('  --                  Stop parsing flags')
-  process.exit(help ? 0 : 1)
-} else
-  go(0)
diff --git a/deps/npm/node_modules/rimraf/node_modules/brace-expansion/LICENSE b/deps/npm/node_modules/rimraf/node_modules/brace-expansion/LICENSE
deleted file mode 100644
index de3226673c3874..00000000000000
--- a/deps/npm/node_modules/rimraf/node_modules/brace-expansion/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2013 Julian Gruber 
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/deps/npm/node_modules/rimraf/node_modules/brace-expansion/index.js b/deps/npm/node_modules/rimraf/node_modules/brace-expansion/index.js
deleted file mode 100644
index 2b6f4f85c951fc..00000000000000
--- a/deps/npm/node_modules/rimraf/node_modules/brace-expansion/index.js
+++ /dev/null
@@ -1,200 +0,0 @@
-var concatMap = require('concat-map');
-var balanced = require('balanced-match');
-
-module.exports = expandTop;
-
-var escSlash = '\0SLASH'+Math.random()+'\0';
-var escOpen = '\0OPEN'+Math.random()+'\0';
-var escClose = '\0CLOSE'+Math.random()+'\0';
-var escComma = '\0COMMA'+Math.random()+'\0';
-var escPeriod = '\0PERIOD'+Math.random()+'\0';
-
-function numeric(str) {
-  return parseInt(str, 10) == str
-    ? parseInt(str, 10)
-    : str.charCodeAt(0);
-}
-
-function escapeBraces(str) {
-  return str.split('\\\\').join(escSlash)
-            .split('\\{').join(escOpen)
-            .split('\\}').join(escClose)
-            .split('\\,').join(escComma)
-            .split('\\.').join(escPeriod);
-}
-
-function unescapeBraces(str) {
-  return str.split(escSlash).join('\\')
-            .split(escOpen).join('{')
-            .split(escClose).join('}')
-            .split(escComma).join(',')
-            .split(escPeriod).join('.');
-}
-
-
-// Basically just str.split(","), but handling cases
-// where we have nested braced sections, which should be
-// treated as individual members, like {a,{b,c},d}
-function parseCommaParts(str) {
-  if (!str)
-    return [''];
-
-  var parts = [];
-  var m = balanced('{', '}', str);
-
-  if (!m)
-    return str.split(',');
-
-  var pre = m.pre;
-  var body = m.body;
-  var post = m.post;
-  var p = pre.split(',');
-
-  p[p.length-1] += '{' + body + '}';
-  var postParts = parseCommaParts(post);
-  if (post.length) {
-    p[p.length-1] += postParts.shift();
-    p.push.apply(p, postParts);
-  }
-
-  parts.push.apply(parts, p);
-
-  return parts;
-}
-
-function expandTop(str) {
-  if (!str)
-    return [];
-
-  // I don't know why Bash 4.3 does this, but it does.
-  // Anything starting with {} will have the first two bytes preserved
-  // but *only* at the top level, so {},a}b will not expand to anything,
-  // but a{},b}c will be expanded to [a}c,abc].
-  // One could argue that this is a bug in Bash, but since the goal of
-  // this module is to match Bash's rules, we escape a leading {}
-  if (str.substr(0, 2) === '{}') {
-    str = '\\{\\}' + str.substr(2);
-  }
-
-  return expand(escapeBraces(str), true).map(unescapeBraces);
-}
-
-function identity(e) {
-  return e;
-}
-
-function embrace(str) {
-  return '{' + str + '}';
-}
-function isPadded(el) {
-  return /^-?0\d/.test(el);
-}
-
-function lte(i, y) {
-  return i <= y;
-}
-function gte(i, y) {
-  return i >= y;
-}
-
-function expand(str, isTop) {
-  var expansions = [];
-
-  var m = balanced('{', '}', str);
-  if (!m || /\$$/.test(m.pre)) return [str];
-
-  var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
-  var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
-  var isSequence = isNumericSequence || isAlphaSequence;
-  var isOptions = m.body.indexOf(',') >= 0;
-  if (!isSequence && !isOptions) {
-    // {a},b}
-    if (m.post.match(/,.*\}/)) {
-      str = m.pre + '{' + m.body + escClose + m.post;
-      return expand(str);
-    }
-    return [str];
-  }
-
-  var n;
-  if (isSequence) {
-    n = m.body.split(/\.\./);
-  } else {
-    n = parseCommaParts(m.body);
-    if (n.length === 1) {
-      // x{{a,b}}y ==> x{a}y x{b}y
-      n = expand(n[0], false).map(embrace);
-      if (n.length === 1) {
-        var post = m.post.length
-          ? expand(m.post, false)
-          : [''];
-        return post.map(function(p) {
-          return m.pre + n[0] + p;
-        });
-      }
-    }
-  }
-
-  // at this point, n is the parts, and we know it's not a comma set
-  // with a single entry.
-
-  // no need to expand pre, since it is guaranteed to be free of brace-sets
-  var pre = m.pre;
-  var post = m.post.length
-    ? expand(m.post, false)
-    : [''];
-
-  var N;
-
-  if (isSequence) {
-    var x = numeric(n[0]);
-    var y = numeric(n[1]);
-    var width = Math.max(n[0].length, n[1].length)
-    var incr = n.length == 3
-      ? Math.abs(numeric(n[2]))
-      : 1;
-    var test = lte;
-    var reverse = y < x;
-    if (reverse) {
-      incr *= -1;
-      test = gte;
-    }
-    var pad = n.some(isPadded);
-
-    N = [];
-
-    for (var i = x; test(i, y); i += incr) {
-      var c;
-      if (isAlphaSequence) {
-        c = String.fromCharCode(i);
-        if (c === '\\')
-          c = '';
-      } else {
-        c = String(i);
-        if (pad) {
-          var need = width - c.length;
-          if (need > 0) {
-            var z = new Array(need + 1).join('0');
-            if (i < 0)
-              c = '-' + z + c.slice(1);
-            else
-              c = z + c;
-          }
-        }
-      }
-      N.push(c);
-    }
-  } else {
-    N = concatMap(n, function(el) { return expand(el, false) });
-  }
-
-  for (var j = 0; j < N.length; j++) {
-    for (var k = 0; k < post.length; k++) {
-      var expansion = pre + N[j] + post[k];
-      if (!isTop || isSequence || expansion)
-        expansions.push(expansion);
-    }
-  }
-
-  return expansions;
-}
diff --git a/deps/npm/node_modules/rimraf/node_modules/brace-expansion/package.json b/deps/npm/node_modules/rimraf/node_modules/brace-expansion/package.json
deleted file mode 100644
index a18faa8fd67b82..00000000000000
--- a/deps/npm/node_modules/rimraf/node_modules/brace-expansion/package.json
+++ /dev/null
@@ -1,47 +0,0 @@
-{
-  "name": "brace-expansion",
-  "description": "Brace expansion as known from sh/bash",
-  "version": "1.1.11",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/juliangruber/brace-expansion.git"
-  },
-  "homepage": "https://github.com/juliangruber/brace-expansion",
-  "main": "index.js",
-  "scripts": {
-    "test": "tape test/*.js",
-    "gentest": "bash test/generate.sh",
-    "bench": "matcha test/perf/bench.js"
-  },
-  "dependencies": {
-    "balanced-match": "^1.0.0",
-    "concat-map": "0.0.1"
-  },
-  "devDependencies": {
-    "matcha": "^0.7.0",
-    "tape": "^4.6.0"
-  },
-  "keywords": [],
-  "author": {
-    "name": "Julian Gruber",
-    "email": "mail@juliangruber.com",
-    "url": "http://juliangruber.com"
-  },
-  "license": "MIT",
-  "testling": {
-    "files": "test/*.js",
-    "browsers": [
-      "ie/8..latest",
-      "firefox/20..latest",
-      "firefox/nightly",
-      "chrome/25..latest",
-      "chrome/canary",
-      "opera/12..latest",
-      "opera/next",
-      "safari/5.1..latest",
-      "ipad/6.0..latest",
-      "iphone/6.0..latest",
-      "android-browser/4.2..latest"
-    ]
-  }
-}
diff --git a/deps/npm/node_modules/rimraf/node_modules/glob/LICENSE b/deps/npm/node_modules/rimraf/node_modules/glob/LICENSE
deleted file mode 100644
index 42ca266df1d523..00000000000000
--- a/deps/npm/node_modules/rimraf/node_modules/glob/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The ISC License
-
-Copyright (c) Isaac Z. Schlueter and Contributors
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-## Glob Logo
-
-Glob's logo created by Tanya Brassie , licensed
-under a Creative Commons Attribution-ShareAlike 4.0 International License
-https://creativecommons.org/licenses/by-sa/4.0/
diff --git a/deps/npm/node_modules/rimraf/node_modules/glob/common.js b/deps/npm/node_modules/rimraf/node_modules/glob/common.js
deleted file mode 100644
index 424c46e1dab1be..00000000000000
--- a/deps/npm/node_modules/rimraf/node_modules/glob/common.js
+++ /dev/null
@@ -1,238 +0,0 @@
-exports.setopts = setopts
-exports.ownProp = ownProp
-exports.makeAbs = makeAbs
-exports.finish = finish
-exports.mark = mark
-exports.isIgnored = isIgnored
-exports.childrenIgnored = childrenIgnored
-
-function ownProp (obj, field) {
-  return Object.prototype.hasOwnProperty.call(obj, field)
-}
-
-var fs = require("fs")
-var path = require("path")
-var minimatch = require("minimatch")
-var isAbsolute = require("path-is-absolute")
-var Minimatch = minimatch.Minimatch
-
-function alphasort (a, b) {
-  return a.localeCompare(b, 'en')
-}
-
-function setupIgnores (self, options) {
-  self.ignore = options.ignore || []
-
-  if (!Array.isArray(self.ignore))
-    self.ignore = [self.ignore]
-
-  if (self.ignore.length) {
-    self.ignore = self.ignore.map(ignoreMap)
-  }
-}
-
-// ignore patterns are always in dot:true mode.
-function ignoreMap (pattern) {
-  var gmatcher = null
-  if (pattern.slice(-3) === '/**') {
-    var gpattern = pattern.replace(/(\/\*\*)+$/, '')
-    gmatcher = new Minimatch(gpattern, { dot: true })
-  }
-
-  return {
-    matcher: new Minimatch(pattern, { dot: true }),
-    gmatcher: gmatcher
-  }
-}
-
-function setopts (self, pattern, options) {
-  if (!options)
-    options = {}
-
-  // base-matching: just use globstar for that.
-  if (options.matchBase && -1 === pattern.indexOf("/")) {
-    if (options.noglobstar) {
-      throw new Error("base matching requires globstar")
-    }
-    pattern = "**/" + pattern
-  }
-
-  self.silent = !!options.silent
-  self.pattern = pattern
-  self.strict = options.strict !== false
-  self.realpath = !!options.realpath
-  self.realpathCache = options.realpathCache || Object.create(null)
-  self.follow = !!options.follow
-  self.dot = !!options.dot
-  self.mark = !!options.mark
-  self.nodir = !!options.nodir
-  if (self.nodir)
-    self.mark = true
-  self.sync = !!options.sync
-  self.nounique = !!options.nounique
-  self.nonull = !!options.nonull
-  self.nosort = !!options.nosort
-  self.nocase = !!options.nocase
-  self.stat = !!options.stat
-  self.noprocess = !!options.noprocess
-  self.absolute = !!options.absolute
-  self.fs = options.fs || fs
-
-  self.maxLength = options.maxLength || Infinity
-  self.cache = options.cache || Object.create(null)
-  self.statCache = options.statCache || Object.create(null)
-  self.symlinks = options.symlinks || Object.create(null)
-
-  setupIgnores(self, options)
-
-  self.changedCwd = false
-  var cwd = process.cwd()
-  if (!ownProp(options, "cwd"))
-    self.cwd = cwd
-  else {
-    self.cwd = path.resolve(options.cwd)
-    self.changedCwd = self.cwd !== cwd
-  }
-
-  self.root = options.root || path.resolve(self.cwd, "/")
-  self.root = path.resolve(self.root)
-  if (process.platform === "win32")
-    self.root = self.root.replace(/\\/g, "/")
-
-  // TODO: is an absolute `cwd` supposed to be resolved against `root`?
-  // e.g. { cwd: '/test', root: __dirname } === path.join(__dirname, '/test')
-  self.cwdAbs = isAbsolute(self.cwd) ? self.cwd : makeAbs(self, self.cwd)
-  if (process.platform === "win32")
-    self.cwdAbs = self.cwdAbs.replace(/\\/g, "/")
-  self.nomount = !!options.nomount
-
-  // disable comments and negation in Minimatch.
-  // Note that they are not supported in Glob itself anyway.
-  options.nonegate = true
-  options.nocomment = true
-  // always treat \ in patterns as escapes, not path separators
-  options.allowWindowsEscape = false
-
-  self.minimatch = new Minimatch(pattern, options)
-  self.options = self.minimatch.options
-}
-
-function finish (self) {
-  var nou = self.nounique
-  var all = nou ? [] : Object.create(null)
-
-  for (var i = 0, l = self.matches.length; i < l; i ++) {
-    var matches = self.matches[i]
-    if (!matches || Object.keys(matches).length === 0) {
-      if (self.nonull) {
-        // do like the shell, and spit out the literal glob
-        var literal = self.minimatch.globSet[i]
-        if (nou)
-          all.push(literal)
-        else
-          all[literal] = true
-      }
-    } else {
-      // had matches
-      var m = Object.keys(matches)
-      if (nou)
-        all.push.apply(all, m)
-      else
-        m.forEach(function (m) {
-          all[m] = true
-        })
-    }
-  }
-
-  if (!nou)
-    all = Object.keys(all)
-
-  if (!self.nosort)
-    all = all.sort(alphasort)
-
-  // at *some* point we statted all of these
-  if (self.mark) {
-    for (var i = 0; i < all.length; i++) {
-      all[i] = self._mark(all[i])
-    }
-    if (self.nodir) {
-      all = all.filter(function (e) {
-        var notDir = !(/\/$/.test(e))
-        var c = self.cache[e] || self.cache[makeAbs(self, e)]
-        if (notDir && c)
-          notDir = c !== 'DIR' && !Array.isArray(c)
-        return notDir
-      })
-    }
-  }
-
-  if (self.ignore.length)
-    all = all.filter(function(m) {
-      return !isIgnored(self, m)
-    })
-
-  self.found = all
-}
-
-function mark (self, p) {
-  var abs = makeAbs(self, p)
-  var c = self.cache[abs]
-  var m = p
-  if (c) {
-    var isDir = c === 'DIR' || Array.isArray(c)
-    var slash = p.slice(-1) === '/'
-
-    if (isDir && !slash)
-      m += '/'
-    else if (!isDir && slash)
-      m = m.slice(0, -1)
-
-    if (m !== p) {
-      var mabs = makeAbs(self, m)
-      self.statCache[mabs] = self.statCache[abs]
-      self.cache[mabs] = self.cache[abs]
-    }
-  }
-
-  return m
-}
-
-// lotta situps...
-function makeAbs (self, f) {
-  var abs = f
-  if (f.charAt(0) === '/') {
-    abs = path.join(self.root, f)
-  } else if (isAbsolute(f) || f === '') {
-    abs = f
-  } else if (self.changedCwd) {
-    abs = path.resolve(self.cwd, f)
-  } else {
-    abs = path.resolve(f)
-  }
-
-  if (process.platform === 'win32')
-    abs = abs.replace(/\\/g, '/')
-
-  return abs
-}
-
-
-// Return true, if pattern ends with globstar '**', for the accompanying parent directory.
-// Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents
-function isIgnored (self, path) {
-  if (!self.ignore.length)
-    return false
-
-  return self.ignore.some(function(item) {
-    return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path))
-  })
-}
-
-function childrenIgnored (self, path) {
-  if (!self.ignore.length)
-    return false
-
-  return self.ignore.some(function(item) {
-    return !!(item.gmatcher && item.gmatcher.match(path))
-  })
-}
diff --git a/deps/npm/node_modules/rimraf/node_modules/glob/glob.js b/deps/npm/node_modules/rimraf/node_modules/glob/glob.js
deleted file mode 100644
index 37a4d7e60775a3..00000000000000
--- a/deps/npm/node_modules/rimraf/node_modules/glob/glob.js
+++ /dev/null
@@ -1,790 +0,0 @@
-// Approach:
-//
-// 1. Get the minimatch set
-// 2. For each pattern in the set, PROCESS(pattern, false)
-// 3. Store matches per-set, then uniq them
-//
-// PROCESS(pattern, inGlobStar)
-// Get the first [n] items from pattern that are all strings
-// Join these together.  This is PREFIX.
-//   If there is no more remaining, then stat(PREFIX) and
-//   add to matches if it succeeds.  END.
-//
-// If inGlobStar and PREFIX is symlink and points to dir
-//   set ENTRIES = []
-// else readdir(PREFIX) as ENTRIES
-//   If fail, END
-//
-// with ENTRIES
-//   If pattern[n] is GLOBSTAR
-//     // handle the case where the globstar match is empty
-//     // by pruning it out, and testing the resulting pattern
-//     PROCESS(pattern[0..n] + pattern[n+1 .. $], false)
-//     // handle other cases.
-//     for ENTRY in ENTRIES (not dotfiles)
-//       // attach globstar + tail onto the entry
-//       // Mark that this entry is a globstar match
-//       PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true)
-//
-//   else // not globstar
-//     for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot)
-//       Test ENTRY against pattern[n]
-//       If fails, continue
-//       If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $])
-//
-// Caveat:
-//   Cache all stats and readdirs results to minimize syscall.  Since all
-//   we ever care about is existence and directory-ness, we can just keep
-//   `true` for files, and [children,...] for directories, or `false` for
-//   things that don't exist.
-
-module.exports = glob
-
-var rp = require('fs.realpath')
-var minimatch = require('minimatch')
-var Minimatch = minimatch.Minimatch
-var inherits = require('inherits')
-var EE = require('events').EventEmitter
-var path = require('path')
-var assert = require('assert')
-var isAbsolute = require('path-is-absolute')
-var globSync = require('./sync.js')
-var common = require('./common.js')
-var setopts = common.setopts
-var ownProp = common.ownProp
-var inflight = require('inflight')
-var util = require('util')
-var childrenIgnored = common.childrenIgnored
-var isIgnored = common.isIgnored
-
-var once = require('once')
-
-function glob (pattern, options, cb) {
-  if (typeof options === 'function') cb = options, options = {}
-  if (!options) options = {}
-
-  if (options.sync) {
-    if (cb)
-      throw new TypeError('callback provided to sync glob')
-    return globSync(pattern, options)
-  }
-
-  return new Glob(pattern, options, cb)
-}
-
-glob.sync = globSync
-var GlobSync = glob.GlobSync = globSync.GlobSync
-
-// old api surface
-glob.glob = glob
-
-function extend (origin, add) {
-  if (add === null || typeof add !== 'object') {
-    return origin
-  }
-
-  var keys = Object.keys(add)
-  var i = keys.length
-  while (i--) {
-    origin[keys[i]] = add[keys[i]]
-  }
-  return origin
-}
-
-glob.hasMagic = function (pattern, options_) {
-  var options = extend({}, options_)
-  options.noprocess = true
-
-  var g = new Glob(pattern, options)
-  var set = g.minimatch.set
-
-  if (!pattern)
-    return false
-
-  if (set.length > 1)
-    return true
-
-  for (var j = 0; j < set[0].length; j++) {
-    if (typeof set[0][j] !== 'string')
-      return true
-  }
-
-  return false
-}
-
-glob.Glob = Glob
-inherits(Glob, EE)
-function Glob (pattern, options, cb) {
-  if (typeof options === 'function') {
-    cb = options
-    options = null
-  }
-
-  if (options && options.sync) {
-    if (cb)
-      throw new TypeError('callback provided to sync glob')
-    return new GlobSync(pattern, options)
-  }
-
-  if (!(this instanceof Glob))
-    return new Glob(pattern, options, cb)
-
-  setopts(this, pattern, options)
-  this._didRealPath = false
-
-  // process each pattern in the minimatch set
-  var n = this.minimatch.set.length
-
-  // The matches are stored as {: true,...} so that
-  // duplicates are automagically pruned.
-  // Later, we do an Object.keys() on these.
-  // Keep them as a list so we can fill in when nonull is set.
-  this.matches = new Array(n)
-
-  if (typeof cb === 'function') {
-    cb = once(cb)
-    this.on('error', cb)
-    this.on('end', function (matches) {
-      cb(null, matches)
-    })
-  }
-
-  var self = this
-  this._processing = 0
-
-  this._emitQueue = []
-  this._processQueue = []
-  this.paused = false
-
-  if (this.noprocess)
-    return this
-
-  if (n === 0)
-    return done()
-
-  var sync = true
-  for (var i = 0; i < n; i ++) {
-    this._process(this.minimatch.set[i], i, false, done)
-  }
-  sync = false
-
-  function done () {
-    --self._processing
-    if (self._processing <= 0) {
-      if (sync) {
-        process.nextTick(function () {
-          self._finish()
-        })
-      } else {
-        self._finish()
-      }
-    }
-  }
-}
-
-Glob.prototype._finish = function () {
-  assert(this instanceof Glob)
-  if (this.aborted)
-    return
-
-  if (this.realpath && !this._didRealpath)
-    return this._realpath()
-
-  common.finish(this)
-  this.emit('end', this.found)
-}
-
-Glob.prototype._realpath = function () {
-  if (this._didRealpath)
-    return
-
-  this._didRealpath = true
-
-  var n = this.matches.length
-  if (n === 0)
-    return this._finish()
-
-  var self = this
-  for (var i = 0; i < this.matches.length; i++)
-    this._realpathSet(i, next)
-
-  function next () {
-    if (--n === 0)
-      self._finish()
-  }
-}
-
-Glob.prototype._realpathSet = function (index, cb) {
-  var matchset = this.matches[index]
-  if (!matchset)
-    return cb()
-
-  var found = Object.keys(matchset)
-  var self = this
-  var n = found.length
-
-  if (n === 0)
-    return cb()
-
-  var set = this.matches[index] = Object.create(null)
-  found.forEach(function (p, i) {
-    // If there's a problem with the stat, then it means that
-    // one or more of the links in the realpath couldn't be
-    // resolved.  just return the abs value in that case.
-    p = self._makeAbs(p)
-    rp.realpath(p, self.realpathCache, function (er, real) {
-      if (!er)
-        set[real] = true
-      else if (er.syscall === 'stat')
-        set[p] = true
-      else
-        self.emit('error', er) // srsly wtf right here
-
-      if (--n === 0) {
-        self.matches[index] = set
-        cb()
-      }
-    })
-  })
-}
-
-Glob.prototype._mark = function (p) {
-  return common.mark(this, p)
-}
-
-Glob.prototype._makeAbs = function (f) {
-  return common.makeAbs(this, f)
-}
-
-Glob.prototype.abort = function () {
-  this.aborted = true
-  this.emit('abort')
-}
-
-Glob.prototype.pause = function () {
-  if (!this.paused) {
-    this.paused = true
-    this.emit('pause')
-  }
-}
-
-Glob.prototype.resume = function () {
-  if (this.paused) {
-    this.emit('resume')
-    this.paused = false
-    if (this._emitQueue.length) {
-      var eq = this._emitQueue.slice(0)
-      this._emitQueue.length = 0
-      for (var i = 0; i < eq.length; i ++) {
-        var e = eq[i]
-        this._emitMatch(e[0], e[1])
-      }
-    }
-    if (this._processQueue.length) {
-      var pq = this._processQueue.slice(0)
-      this._processQueue.length = 0
-      for (var i = 0; i < pq.length; i ++) {
-        var p = pq[i]
-        this._processing--
-        this._process(p[0], p[1], p[2], p[3])
-      }
-    }
-  }
-}
-
-Glob.prototype._process = function (pattern, index, inGlobStar, cb) {
-  assert(this instanceof Glob)
-  assert(typeof cb === 'function')
-
-  if (this.aborted)
-    return
-
-  this._processing++
-  if (this.paused) {
-    this._processQueue.push([pattern, index, inGlobStar, cb])
-    return
-  }
-
-  //console.error('PROCESS %d', this._processing, pattern)
-
-  // Get the first [n] parts of pattern that are all strings.
-  var n = 0
-  while (typeof pattern[n] === 'string') {
-    n ++
-  }
-  // now n is the index of the first one that is *not* a string.
-
-  // see if there's anything else
-  var prefix
-  switch (n) {
-    // if not, then this is rather simple
-    case pattern.length:
-      this._processSimple(pattern.join('/'), index, cb)
-      return
-
-    case 0:
-      // pattern *starts* with some non-trivial item.
-      // going to readdir(cwd), but not include the prefix in matches.
-      prefix = null
-      break
-
-    default:
-      // pattern has some string bits in the front.
-      // whatever it starts with, whether that's 'absolute' like /foo/bar,
-      // or 'relative' like '../baz'
-      prefix = pattern.slice(0, n).join('/')
-      break
-  }
-
-  var remain = pattern.slice(n)
-
-  // get the list of entries.
-  var read
-  if (prefix === null)
-    read = '.'
-  else if (isAbsolute(prefix) ||
-      isAbsolute(pattern.map(function (p) {
-        return typeof p === 'string' ? p : '[*]'
-      }).join('/'))) {
-    if (!prefix || !isAbsolute(prefix))
-      prefix = '/' + prefix
-    read = prefix
-  } else
-    read = prefix
-
-  var abs = this._makeAbs(read)
-
-  //if ignored, skip _processing
-  if (childrenIgnored(this, read))
-    return cb()
-
-  var isGlobStar = remain[0] === minimatch.GLOBSTAR
-  if (isGlobStar)
-    this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb)
-  else
-    this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb)
-}
-
-Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) {
-  var self = this
-  this._readdir(abs, inGlobStar, function (er, entries) {
-    return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
-  })
-}
-
-Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
-
-  // if the abs isn't a dir, then nothing can match!
-  if (!entries)
-    return cb()
-
-  // It will only match dot entries if it starts with a dot, or if
-  // dot is set.  Stuff like @(.foo|.bar) isn't allowed.
-  var pn = remain[0]
-  var negate = !!this.minimatch.negate
-  var rawGlob = pn._glob
-  var dotOk = this.dot || rawGlob.charAt(0) === '.'
-
-  var matchedEntries = []
-  for (var i = 0; i < entries.length; i++) {
-    var e = entries[i]
-    if (e.charAt(0) !== '.' || dotOk) {
-      var m
-      if (negate && !prefix) {
-        m = !e.match(pn)
-      } else {
-        m = e.match(pn)
-      }
-      if (m)
-        matchedEntries.push(e)
-    }
-  }
-
-  //console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries)
-
-  var len = matchedEntries.length
-  // If there are no matched entries, then nothing matches.
-  if (len === 0)
-    return cb()
-
-  // if this is the last remaining pattern bit, then no need for
-  // an additional stat *unless* the user has specified mark or
-  // stat explicitly.  We know they exist, since readdir returned
-  // them.
-
-  if (remain.length === 1 && !this.mark && !this.stat) {
-    if (!this.matches[index])
-      this.matches[index] = Object.create(null)
-
-    for (var i = 0; i < len; i ++) {
-      var e = matchedEntries[i]
-      if (prefix) {
-        if (prefix !== '/')
-          e = prefix + '/' + e
-        else
-          e = prefix + e
-      }
-
-      if (e.charAt(0) === '/' && !this.nomount) {
-        e = path.join(this.root, e)
-      }
-      this._emitMatch(index, e)
-    }
-    // This was the last one, and no stats were needed
-    return cb()
-  }
-
-  // now test all matched entries as stand-ins for that part
-  // of the pattern.
-  remain.shift()
-  for (var i = 0; i < len; i ++) {
-    var e = matchedEntries[i]
-    var newPattern
-    if (prefix) {
-      if (prefix !== '/')
-        e = prefix + '/' + e
-      else
-        e = prefix + e
-    }
-    this._process([e].concat(remain), index, inGlobStar, cb)
-  }
-  cb()
-}
-
-Glob.prototype._emitMatch = function (index, e) {
-  if (this.aborted)
-    return
-
-  if (isIgnored(this, e))
-    return
-
-  if (this.paused) {
-    this._emitQueue.push([index, e])
-    return
-  }
-
-  var abs = isAbsolute(e) ? e : this._makeAbs(e)
-
-  if (this.mark)
-    e = this._mark(e)
-
-  if (this.absolute)
-    e = abs
-
-  if (this.matches[index][e])
-    return
-
-  if (this.nodir) {
-    var c = this.cache[abs]
-    if (c === 'DIR' || Array.isArray(c))
-      return
-  }
-
-  this.matches[index][e] = true
-
-  var st = this.statCache[abs]
-  if (st)
-    this.emit('stat', e, st)
-
-  this.emit('match', e)
-}
-
-Glob.prototype._readdirInGlobStar = function (abs, cb) {
-  if (this.aborted)
-    return
-
-  // follow all symlinked directories forever
-  // just proceed as if this is a non-globstar situation
-  if (this.follow)
-    return this._readdir(abs, false, cb)
-
-  var lstatkey = 'lstat\0' + abs
-  var self = this
-  var lstatcb = inflight(lstatkey, lstatcb_)
-
-  if (lstatcb)
-    self.fs.lstat(abs, lstatcb)
-
-  function lstatcb_ (er, lstat) {
-    if (er && er.code === 'ENOENT')
-      return cb()
-
-    var isSym = lstat && lstat.isSymbolicLink()
-    self.symlinks[abs] = isSym
-
-    // If it's not a symlink or a dir, then it's definitely a regular file.
-    // don't bother doing a readdir in that case.
-    if (!isSym && lstat && !lstat.isDirectory()) {
-      self.cache[abs] = 'FILE'
-      cb()
-    } else
-      self._readdir(abs, false, cb)
-  }
-}
-
-Glob.prototype._readdir = function (abs, inGlobStar, cb) {
-  if (this.aborted)
-    return
-
-  cb = inflight('readdir\0'+abs+'\0'+inGlobStar, cb)
-  if (!cb)
-    return
-
-  //console.error('RD %j %j', +inGlobStar, abs)
-  if (inGlobStar && !ownProp(this.symlinks, abs))
-    return this._readdirInGlobStar(abs, cb)
-
-  if (ownProp(this.cache, abs)) {
-    var c = this.cache[abs]
-    if (!c || c === 'FILE')
-      return cb()
-
-    if (Array.isArray(c))
-      return cb(null, c)
-  }
-
-  var self = this
-  self.fs.readdir(abs, readdirCb(this, abs, cb))
-}
-
-function readdirCb (self, abs, cb) {
-  return function (er, entries) {
-    if (er)
-      self._readdirError(abs, er, cb)
-    else
-      self._readdirEntries(abs, entries, cb)
-  }
-}
-
-Glob.prototype._readdirEntries = function (abs, entries, cb) {
-  if (this.aborted)
-    return
-
-  // if we haven't asked to stat everything, then just
-  // assume that everything in there exists, so we can avoid
-  // having to stat it a second time.
-  if (!this.mark && !this.stat) {
-    for (var i = 0; i < entries.length; i ++) {
-      var e = entries[i]
-      if (abs === '/')
-        e = abs + e
-      else
-        e = abs + '/' + e
-      this.cache[e] = true
-    }
-  }
-
-  this.cache[abs] = entries
-  return cb(null, entries)
-}
-
-Glob.prototype._readdirError = function (f, er, cb) {
-  if (this.aborted)
-    return
-
-  // handle errors, and cache the information
-  switch (er.code) {
-    case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205
-    case 'ENOTDIR': // totally normal. means it *does* exist.
-      var abs = this._makeAbs(f)
-      this.cache[abs] = 'FILE'
-      if (abs === this.cwdAbs) {
-        var error = new Error(er.code + ' invalid cwd ' + this.cwd)
-        error.path = this.cwd
-        error.code = er.code
-        this.emit('error', error)
-        this.abort()
-      }
-      break
-
-    case 'ENOENT': // not terribly unusual
-    case 'ELOOP':
-    case 'ENAMETOOLONG':
-    case 'UNKNOWN':
-      this.cache[this._makeAbs(f)] = false
-      break
-
-    default: // some unusual error.  Treat as failure.
-      this.cache[this._makeAbs(f)] = false
-      if (this.strict) {
-        this.emit('error', er)
-        // If the error is handled, then we abort
-        // if not, we threw out of here
-        this.abort()
-      }
-      if (!this.silent)
-        console.error('glob error', er)
-      break
-  }
-
-  return cb()
-}
-
-Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) {
-  var self = this
-  this._readdir(abs, inGlobStar, function (er, entries) {
-    self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
-  })
-}
-
-
-Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
-  //console.error('pgs2', prefix, remain[0], entries)
-
-  // no entries means not a dir, so it can never have matches
-  // foo.txt/** doesn't match foo.txt
-  if (!entries)
-    return cb()
-
-  // test without the globstar, and with every child both below
-  // and replacing the globstar.
-  var remainWithoutGlobStar = remain.slice(1)
-  var gspref = prefix ? [ prefix ] : []
-  var noGlobStar = gspref.concat(remainWithoutGlobStar)
-
-  // the noGlobStar pattern exits the inGlobStar state
-  this._process(noGlobStar, index, false, cb)
-
-  var isSym = this.symlinks[abs]
-  var len = entries.length
-
-  // If it's a symlink, and we're in a globstar, then stop
-  if (isSym && inGlobStar)
-    return cb()
-
-  for (var i = 0; i < len; i++) {
-    var e = entries[i]
-    if (e.charAt(0) === '.' && !this.dot)
-      continue
-
-    // these two cases enter the inGlobStar state
-    var instead = gspref.concat(entries[i], remainWithoutGlobStar)
-    this._process(instead, index, true, cb)
-
-    var below = gspref.concat(entries[i], remain)
-    this._process(below, index, true, cb)
-  }
-
-  cb()
-}
-
-Glob.prototype._processSimple = function (prefix, index, cb) {
-  // XXX review this.  Shouldn't it be doing the mounting etc
-  // before doing stat?  kinda weird?
-  var self = this
-  this._stat(prefix, function (er, exists) {
-    self._processSimple2(prefix, index, er, exists, cb)
-  })
-}
-Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) {
-
-  //console.error('ps2', prefix, exists)
-
-  if (!this.matches[index])
-    this.matches[index] = Object.create(null)
-
-  // If it doesn't exist, then just mark the lack of results
-  if (!exists)
-    return cb()
-
-  if (prefix && isAbsolute(prefix) && !this.nomount) {
-    var trail = /[\/\\]$/.test(prefix)
-    if (prefix.charAt(0) === '/') {
-      prefix = path.join(this.root, prefix)
-    } else {
-      prefix = path.resolve(this.root, prefix)
-      if (trail)
-        prefix += '/'
-    }
-  }
-
-  if (process.platform === 'win32')
-    prefix = prefix.replace(/\\/g, '/')
-
-  // Mark this as a match
-  this._emitMatch(index, prefix)
-  cb()
-}
-
-// Returns either 'DIR', 'FILE', or false
-Glob.prototype._stat = function (f, cb) {
-  var abs = this._makeAbs(f)
-  var needDir = f.slice(-1) === '/'
-
-  if (f.length > this.maxLength)
-    return cb()
-
-  if (!this.stat && ownProp(this.cache, abs)) {
-    var c = this.cache[abs]
-
-    if (Array.isArray(c))
-      c = 'DIR'
-
-    // It exists, but maybe not how we need it
-    if (!needDir || c === 'DIR')
-      return cb(null, c)
-
-    if (needDir && c === 'FILE')
-      return cb()
-
-    // otherwise we have to stat, because maybe c=true
-    // if we know it exists, but not what it is.
-  }
-
-  var exists
-  var stat = this.statCache[abs]
-  if (stat !== undefined) {
-    if (stat === false)
-      return cb(null, stat)
-    else {
-      var type = stat.isDirectory() ? 'DIR' : 'FILE'
-      if (needDir && type === 'FILE')
-        return cb()
-      else
-        return cb(null, type, stat)
-    }
-  }
-
-  var self = this
-  var statcb = inflight('stat\0' + abs, lstatcb_)
-  if (statcb)
-    self.fs.lstat(abs, statcb)
-
-  function lstatcb_ (er, lstat) {
-    if (lstat && lstat.isSymbolicLink()) {
-      // If it's a symlink, then treat it as the target, unless
-      // the target does not exist, then treat it as a file.
-      return self.fs.stat(abs, function (er, stat) {
-        if (er)
-          self._stat2(f, abs, null, lstat, cb)
-        else
-          self._stat2(f, abs, er, stat, cb)
-      })
-    } else {
-      self._stat2(f, abs, er, lstat, cb)
-    }
-  }
-}
-
-Glob.prototype._stat2 = function (f, abs, er, stat, cb) {
-  if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) {
-    this.statCache[abs] = false
-    return cb()
-  }
-
-  var needDir = f.slice(-1) === '/'
-  this.statCache[abs] = stat
-
-  if (abs.slice(-1) === '/' && stat && !stat.isDirectory())
-    return cb(null, false, stat)
-
-  var c = true
-  if (stat)
-    c = stat.isDirectory() ? 'DIR' : 'FILE'
-  this.cache[abs] = this.cache[abs] || c
-
-  if (needDir && c === 'FILE')
-    return cb()
-
-  return cb(null, c, stat)
-}
diff --git a/deps/npm/node_modules/rimraf/node_modules/glob/package.json b/deps/npm/node_modules/rimraf/node_modules/glob/package.json
deleted file mode 100644
index 5940b649b7e65a..00000000000000
--- a/deps/npm/node_modules/rimraf/node_modules/glob/package.json
+++ /dev/null
@@ -1,55 +0,0 @@
-{
-  "author": "Isaac Z. Schlueter  (http://blog.izs.me/)",
-  "name": "glob",
-  "description": "a little globber",
-  "version": "7.2.3",
-  "publishConfig": {
-    "tag": "v7-legacy"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/node-glob.git"
-  },
-  "main": "glob.js",
-  "files": [
-    "glob.js",
-    "sync.js",
-    "common.js"
-  ],
-  "engines": {
-    "node": "*"
-  },
-  "dependencies": {
-    "fs.realpath": "^1.0.0",
-    "inflight": "^1.0.4",
-    "inherits": "2",
-    "minimatch": "^3.1.1",
-    "once": "^1.3.0",
-    "path-is-absolute": "^1.0.0"
-  },
-  "devDependencies": {
-    "memfs": "^3.2.0",
-    "mkdirp": "0",
-    "rimraf": "^2.2.8",
-    "tap": "^15.0.6",
-    "tick": "0.0.6"
-  },
-  "tap": {
-    "before": "test/00-setup.js",
-    "after": "test/zz-cleanup.js",
-    "jobs": 1
-  },
-  "scripts": {
-    "prepublish": "npm run benchclean",
-    "profclean": "rm -f v8.log profile.txt",
-    "test": "tap",
-    "test-regen": "npm run profclean && TEST_REGEN=1 node test/00-setup.js",
-    "bench": "bash benchmark.sh",
-    "prof": "bash prof.sh && cat profile.txt",
-    "benchclean": "node benchclean.js"
-  },
-  "license": "ISC",
-  "funding": {
-    "url": "https://github.com/sponsors/isaacs"
-  }
-}
diff --git a/deps/npm/node_modules/rimraf/node_modules/glob/sync.js b/deps/npm/node_modules/rimraf/node_modules/glob/sync.js
deleted file mode 100644
index 2c4f480192d28d..00000000000000
--- a/deps/npm/node_modules/rimraf/node_modules/glob/sync.js
+++ /dev/null
@@ -1,486 +0,0 @@
-module.exports = globSync
-globSync.GlobSync = GlobSync
-
-var rp = require('fs.realpath')
-var minimatch = require('minimatch')
-var Minimatch = minimatch.Minimatch
-var Glob = require('./glob.js').Glob
-var util = require('util')
-var path = require('path')
-var assert = require('assert')
-var isAbsolute = require('path-is-absolute')
-var common = require('./common.js')
-var setopts = common.setopts
-var ownProp = common.ownProp
-var childrenIgnored = common.childrenIgnored
-var isIgnored = common.isIgnored
-
-function globSync (pattern, options) {
-  if (typeof options === 'function' || arguments.length === 3)
-    throw new TypeError('callback provided to sync glob\n'+
-                        'See: https://github.com/isaacs/node-glob/issues/167')
-
-  return new GlobSync(pattern, options).found
-}
-
-function GlobSync (pattern, options) {
-  if (!pattern)
-    throw new Error('must provide pattern')
-
-  if (typeof options === 'function' || arguments.length === 3)
-    throw new TypeError('callback provided to sync glob\n'+
-                        'See: https://github.com/isaacs/node-glob/issues/167')
-
-  if (!(this instanceof GlobSync))
-    return new GlobSync(pattern, options)
-
-  setopts(this, pattern, options)
-
-  if (this.noprocess)
-    return this
-
-  var n = this.minimatch.set.length
-  this.matches = new Array(n)
-  for (var i = 0; i < n; i ++) {
-    this._process(this.minimatch.set[i], i, false)
-  }
-  this._finish()
-}
-
-GlobSync.prototype._finish = function () {
-  assert.ok(this instanceof GlobSync)
-  if (this.realpath) {
-    var self = this
-    this.matches.forEach(function (matchset, index) {
-      var set = self.matches[index] = Object.create(null)
-      for (var p in matchset) {
-        try {
-          p = self._makeAbs(p)
-          var real = rp.realpathSync(p, self.realpathCache)
-          set[real] = true
-        } catch (er) {
-          if (er.syscall === 'stat')
-            set[self._makeAbs(p)] = true
-          else
-            throw er
-        }
-      }
-    })
-  }
-  common.finish(this)
-}
-
-
-GlobSync.prototype._process = function (pattern, index, inGlobStar) {
-  assert.ok(this instanceof GlobSync)
-
-  // Get the first [n] parts of pattern that are all strings.
-  var n = 0
-  while (typeof pattern[n] === 'string') {
-    n ++
-  }
-  // now n is the index of the first one that is *not* a string.
-
-  // See if there's anything else
-  var prefix
-  switch (n) {
-    // if not, then this is rather simple
-    case pattern.length:
-      this._processSimple(pattern.join('/'), index)
-      return
-
-    case 0:
-      // pattern *starts* with some non-trivial item.
-      // going to readdir(cwd), but not include the prefix in matches.
-      prefix = null
-      break
-
-    default:
-      // pattern has some string bits in the front.
-      // whatever it starts with, whether that's 'absolute' like /foo/bar,
-      // or 'relative' like '../baz'
-      prefix = pattern.slice(0, n).join('/')
-      break
-  }
-
-  var remain = pattern.slice(n)
-
-  // get the list of entries.
-  var read
-  if (prefix === null)
-    read = '.'
-  else if (isAbsolute(prefix) ||
-      isAbsolute(pattern.map(function (p) {
-        return typeof p === 'string' ? p : '[*]'
-      }).join('/'))) {
-    if (!prefix || !isAbsolute(prefix))
-      prefix = '/' + prefix
-    read = prefix
-  } else
-    read = prefix
-
-  var abs = this._makeAbs(read)
-
-  //if ignored, skip processing
-  if (childrenIgnored(this, read))
-    return
-
-  var isGlobStar = remain[0] === minimatch.GLOBSTAR
-  if (isGlobStar)
-    this._processGlobStar(prefix, read, abs, remain, index, inGlobStar)
-  else
-    this._processReaddir(prefix, read, abs, remain, index, inGlobStar)
-}
-
-
-GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) {
-  var entries = this._readdir(abs, inGlobStar)
-
-  // if the abs isn't a dir, then nothing can match!
-  if (!entries)
-    return
-
-  // It will only match dot entries if it starts with a dot, or if
-  // dot is set.  Stuff like @(.foo|.bar) isn't allowed.
-  var pn = remain[0]
-  var negate = !!this.minimatch.negate
-  var rawGlob = pn._glob
-  var dotOk = this.dot || rawGlob.charAt(0) === '.'
-
-  var matchedEntries = []
-  for (var i = 0; i < entries.length; i++) {
-    var e = entries[i]
-    if (e.charAt(0) !== '.' || dotOk) {
-      var m
-      if (negate && !prefix) {
-        m = !e.match(pn)
-      } else {
-        m = e.match(pn)
-      }
-      if (m)
-        matchedEntries.push(e)
-    }
-  }
-
-  var len = matchedEntries.length
-  // If there are no matched entries, then nothing matches.
-  if (len === 0)
-    return
-
-  // if this is the last remaining pattern bit, then no need for
-  // an additional stat *unless* the user has specified mark or
-  // stat explicitly.  We know they exist, since readdir returned
-  // them.
-
-  if (remain.length === 1 && !this.mark && !this.stat) {
-    if (!this.matches[index])
-      this.matches[index] = Object.create(null)
-
-    for (var i = 0; i < len; i ++) {
-      var e = matchedEntries[i]
-      if (prefix) {
-        if (prefix.slice(-1) !== '/')
-          e = prefix + '/' + e
-        else
-          e = prefix + e
-      }
-
-      if (e.charAt(0) === '/' && !this.nomount) {
-        e = path.join(this.root, e)
-      }
-      this._emitMatch(index, e)
-    }
-    // This was the last one, and no stats were needed
-    return
-  }
-
-  // now test all matched entries as stand-ins for that part
-  // of the pattern.
-  remain.shift()
-  for (var i = 0; i < len; i ++) {
-    var e = matchedEntries[i]
-    var newPattern
-    if (prefix)
-      newPattern = [prefix, e]
-    else
-      newPattern = [e]
-    this._process(newPattern.concat(remain), index, inGlobStar)
-  }
-}
-
-
-GlobSync.prototype._emitMatch = function (index, e) {
-  if (isIgnored(this, e))
-    return
-
-  var abs = this._makeAbs(e)
-
-  if (this.mark)
-    e = this._mark(e)
-
-  if (this.absolute) {
-    e = abs
-  }
-
-  if (this.matches[index][e])
-    return
-
-  if (this.nodir) {
-    var c = this.cache[abs]
-    if (c === 'DIR' || Array.isArray(c))
-      return
-  }
-
-  this.matches[index][e] = true
-
-  if (this.stat)
-    this._stat(e)
-}
-
-
-GlobSync.prototype._readdirInGlobStar = function (abs) {
-  // follow all symlinked directories forever
-  // just proceed as if this is a non-globstar situation
-  if (this.follow)
-    return this._readdir(abs, false)
-
-  var entries
-  var lstat
-  var stat
-  try {
-    lstat = this.fs.lstatSync(abs)
-  } catch (er) {
-    if (er.code === 'ENOENT') {
-      // lstat failed, doesn't exist
-      return null
-    }
-  }
-
-  var isSym = lstat && lstat.isSymbolicLink()
-  this.symlinks[abs] = isSym
-
-  // If it's not a symlink or a dir, then it's definitely a regular file.
-  // don't bother doing a readdir in that case.
-  if (!isSym && lstat && !lstat.isDirectory())
-    this.cache[abs] = 'FILE'
-  else
-    entries = this._readdir(abs, false)
-
-  return entries
-}
-
-GlobSync.prototype._readdir = function (abs, inGlobStar) {
-  var entries
-
-  if (inGlobStar && !ownProp(this.symlinks, abs))
-    return this._readdirInGlobStar(abs)
-
-  if (ownProp(this.cache, abs)) {
-    var c = this.cache[abs]
-    if (!c || c === 'FILE')
-      return null
-
-    if (Array.isArray(c))
-      return c
-  }
-
-  try {
-    return this._readdirEntries(abs, this.fs.readdirSync(abs))
-  } catch (er) {
-    this._readdirError(abs, er)
-    return null
-  }
-}
-
-GlobSync.prototype._readdirEntries = function (abs, entries) {
-  // if we haven't asked to stat everything, then just
-  // assume that everything in there exists, so we can avoid
-  // having to stat it a second time.
-  if (!this.mark && !this.stat) {
-    for (var i = 0; i < entries.length; i ++) {
-      var e = entries[i]
-      if (abs === '/')
-        e = abs + e
-      else
-        e = abs + '/' + e
-      this.cache[e] = true
-    }
-  }
-
-  this.cache[abs] = entries
-
-  // mark and cache dir-ness
-  return entries
-}
-
-GlobSync.prototype._readdirError = function (f, er) {
-  // handle errors, and cache the information
-  switch (er.code) {
-    case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205
-    case 'ENOTDIR': // totally normal. means it *does* exist.
-      var abs = this._makeAbs(f)
-      this.cache[abs] = 'FILE'
-      if (abs === this.cwdAbs) {
-        var error = new Error(er.code + ' invalid cwd ' + this.cwd)
-        error.path = this.cwd
-        error.code = er.code
-        throw error
-      }
-      break
-
-    case 'ENOENT': // not terribly unusual
-    case 'ELOOP':
-    case 'ENAMETOOLONG':
-    case 'UNKNOWN':
-      this.cache[this._makeAbs(f)] = false
-      break
-
-    default: // some unusual error.  Treat as failure.
-      this.cache[this._makeAbs(f)] = false
-      if (this.strict)
-        throw er
-      if (!this.silent)
-        console.error('glob error', er)
-      break
-  }
-}
-
-GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) {
-
-  var entries = this._readdir(abs, inGlobStar)
-
-  // no entries means not a dir, so it can never have matches
-  // foo.txt/** doesn't match foo.txt
-  if (!entries)
-    return
-
-  // test without the globstar, and with every child both below
-  // and replacing the globstar.
-  var remainWithoutGlobStar = remain.slice(1)
-  var gspref = prefix ? [ prefix ] : []
-  var noGlobStar = gspref.concat(remainWithoutGlobStar)
-
-  // the noGlobStar pattern exits the inGlobStar state
-  this._process(noGlobStar, index, false)
-
-  var len = entries.length
-  var isSym = this.symlinks[abs]
-
-  // If it's a symlink, and we're in a globstar, then stop
-  if (isSym && inGlobStar)
-    return
-
-  for (var i = 0; i < len; i++) {
-    var e = entries[i]
-    if (e.charAt(0) === '.' && !this.dot)
-      continue
-
-    // these two cases enter the inGlobStar state
-    var instead = gspref.concat(entries[i], remainWithoutGlobStar)
-    this._process(instead, index, true)
-
-    var below = gspref.concat(entries[i], remain)
-    this._process(below, index, true)
-  }
-}
-
-GlobSync.prototype._processSimple = function (prefix, index) {
-  // XXX review this.  Shouldn't it be doing the mounting etc
-  // before doing stat?  kinda weird?
-  var exists = this._stat(prefix)
-
-  if (!this.matches[index])
-    this.matches[index] = Object.create(null)
-
-  // If it doesn't exist, then just mark the lack of results
-  if (!exists)
-    return
-
-  if (prefix && isAbsolute(prefix) && !this.nomount) {
-    var trail = /[\/\\]$/.test(prefix)
-    if (prefix.charAt(0) === '/') {
-      prefix = path.join(this.root, prefix)
-    } else {
-      prefix = path.resolve(this.root, prefix)
-      if (trail)
-        prefix += '/'
-    }
-  }
-
-  if (process.platform === 'win32')
-    prefix = prefix.replace(/\\/g, '/')
-
-  // Mark this as a match
-  this._emitMatch(index, prefix)
-}
-
-// Returns either 'DIR', 'FILE', or false
-GlobSync.prototype._stat = function (f) {
-  var abs = this._makeAbs(f)
-  var needDir = f.slice(-1) === '/'
-
-  if (f.length > this.maxLength)
-    return false
-
-  if (!this.stat && ownProp(this.cache, abs)) {
-    var c = this.cache[abs]
-
-    if (Array.isArray(c))
-      c = 'DIR'
-
-    // It exists, but maybe not how we need it
-    if (!needDir || c === 'DIR')
-      return c
-
-    if (needDir && c === 'FILE')
-      return false
-
-    // otherwise we have to stat, because maybe c=true
-    // if we know it exists, but not what it is.
-  }
-
-  var exists
-  var stat = this.statCache[abs]
-  if (!stat) {
-    var lstat
-    try {
-      lstat = this.fs.lstatSync(abs)
-    } catch (er) {
-      if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) {
-        this.statCache[abs] = false
-        return false
-      }
-    }
-
-    if (lstat && lstat.isSymbolicLink()) {
-      try {
-        stat = this.fs.statSync(abs)
-      } catch (er) {
-        stat = lstat
-      }
-    } else {
-      stat = lstat
-    }
-  }
-
-  this.statCache[abs] = stat
-
-  var c = true
-  if (stat)
-    c = stat.isDirectory() ? 'DIR' : 'FILE'
-
-  this.cache[abs] = this.cache[abs] || c
-
-  if (needDir && c === 'FILE')
-    return false
-
-  return c
-}
-
-GlobSync.prototype._mark = function (p) {
-  return common.mark(this, p)
-}
-
-GlobSync.prototype._makeAbs = function (f) {
-  return common.makeAbs(this, f)
-}
diff --git a/deps/npm/node_modules/rimraf/node_modules/minimatch/LICENSE b/deps/npm/node_modules/rimraf/node_modules/minimatch/LICENSE
deleted file mode 100644
index 19129e315fe593..00000000000000
--- a/deps/npm/node_modules/rimraf/node_modules/minimatch/LICENSE
+++ /dev/null
@@ -1,15 +0,0 @@
-The ISC License
-
-Copyright (c) Isaac Z. Schlueter and Contributors
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/deps/npm/node_modules/rimraf/node_modules/minimatch/minimatch.js b/deps/npm/node_modules/rimraf/node_modules/minimatch/minimatch.js
deleted file mode 100644
index fda45ade7cfc35..00000000000000
--- a/deps/npm/node_modules/rimraf/node_modules/minimatch/minimatch.js
+++ /dev/null
@@ -1,947 +0,0 @@
-module.exports = minimatch
-minimatch.Minimatch = Minimatch
-
-var path = (function () { try { return require('path') } catch (e) {}}()) || {
-  sep: '/'
-}
-minimatch.sep = path.sep
-
-var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
-var expand = require('brace-expansion')
-
-var plTypes = {
-  '!': { open: '(?:(?!(?:', close: '))[^/]*?)'},
-  '?': { open: '(?:', close: ')?' },
-  '+': { open: '(?:', close: ')+' },
-  '*': { open: '(?:', close: ')*' },
-  '@': { open: '(?:', close: ')' }
-}
-
-// any single thing other than /
-// don't need to escape / when using new RegExp()
-var qmark = '[^/]'
-
-// * => any number of characters
-var star = qmark + '*?'
-
-// ** when dots are allowed.  Anything goes, except .. and .
-// not (^ or / followed by one or two dots followed by $ or /),
-// followed by anything, any number of times.
-var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?'
-
-// not a ^ or / followed by a dot,
-// followed by anything, any number of times.
-var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?'
-
-// characters that need to be escaped in RegExp.
-var reSpecials = charSet('().*{}+?[]^$\\!')
-
-// "abc" -> { a:true, b:true, c:true }
-function charSet (s) {
-  return s.split('').reduce(function (set, c) {
-    set[c] = true
-    return set
-  }, {})
-}
-
-// normalizes slashes.
-var slashSplit = /\/+/
-
-minimatch.filter = filter
-function filter (pattern, options) {
-  options = options || {}
-  return function (p, i, list) {
-    return minimatch(p, pattern, options)
-  }
-}
-
-function ext (a, b) {
-  b = b || {}
-  var t = {}
-  Object.keys(a).forEach(function (k) {
-    t[k] = a[k]
-  })
-  Object.keys(b).forEach(function (k) {
-    t[k] = b[k]
-  })
-  return t
-}
-
-minimatch.defaults = function (def) {
-  if (!def || typeof def !== 'object' || !Object.keys(def).length) {
-    return minimatch
-  }
-
-  var orig = minimatch
-
-  var m = function minimatch (p, pattern, options) {
-    return orig(p, pattern, ext(def, options))
-  }
-
-  m.Minimatch = function Minimatch (pattern, options) {
-    return new orig.Minimatch(pattern, ext(def, options))
-  }
-  m.Minimatch.defaults = function defaults (options) {
-    return orig.defaults(ext(def, options)).Minimatch
-  }
-
-  m.filter = function filter (pattern, options) {
-    return orig.filter(pattern, ext(def, options))
-  }
-
-  m.defaults = function defaults (options) {
-    return orig.defaults(ext(def, options))
-  }
-
-  m.makeRe = function makeRe (pattern, options) {
-    return orig.makeRe(pattern, ext(def, options))
-  }
-
-  m.braceExpand = function braceExpand (pattern, options) {
-    return orig.braceExpand(pattern, ext(def, options))
-  }
-
-  m.match = function (list, pattern, options) {
-    return orig.match(list, pattern, ext(def, options))
-  }
-
-  return m
-}
-
-Minimatch.defaults = function (def) {
-  return minimatch.defaults(def).Minimatch
-}
-
-function minimatch (p, pattern, options) {
-  assertValidPattern(pattern)
-
-  if (!options) options = {}
-
-  // shortcut: comments match nothing.
-  if (!options.nocomment && pattern.charAt(0) === '#') {
-    return false
-  }
-
-  return new Minimatch(pattern, options).match(p)
-}
-
-function Minimatch (pattern, options) {
-  if (!(this instanceof Minimatch)) {
-    return new Minimatch(pattern, options)
-  }
-
-  assertValidPattern(pattern)
-
-  if (!options) options = {}
-
-  pattern = pattern.trim()
-
-  // windows support: need to use /, not \
-  if (!options.allowWindowsEscape && path.sep !== '/') {
-    pattern = pattern.split(path.sep).join('/')
-  }
-
-  this.options = options
-  this.set = []
-  this.pattern = pattern
-  this.regexp = null
-  this.negate = false
-  this.comment = false
-  this.empty = false
-  this.partial = !!options.partial
-
-  // make the set of regexps etc.
-  this.make()
-}
-
-Minimatch.prototype.debug = function () {}
-
-Minimatch.prototype.make = make
-function make () {
-  var pattern = this.pattern
-  var options = this.options
-
-  // empty patterns and comments match nothing.
-  if (!options.nocomment && pattern.charAt(0) === '#') {
-    this.comment = true
-    return
-  }
-  if (!pattern) {
-    this.empty = true
-    return
-  }
-
-  // step 1: figure out negation, etc.
-  this.parseNegate()
-
-  // step 2: expand braces
-  var set = this.globSet = this.braceExpand()
-
-  if (options.debug) this.debug = function debug() { console.error.apply(console, arguments) }
-
-  this.debug(this.pattern, set)
-
-  // step 3: now we have a set, so turn each one into a series of path-portion
-  // matching patterns.
-  // These will be regexps, except in the case of "**", which is
-  // set to the GLOBSTAR object for globstar behavior,
-  // and will not contain any / characters
-  set = this.globParts = set.map(function (s) {
-    return s.split(slashSplit)
-  })
-
-  this.debug(this.pattern, set)
-
-  // glob --> regexps
-  set = set.map(function (s, si, set) {
-    return s.map(this.parse, this)
-  }, this)
-
-  this.debug(this.pattern, set)
-
-  // filter out everything that didn't compile properly.
-  set = set.filter(function (s) {
-    return s.indexOf(false) === -1
-  })
-
-  this.debug(this.pattern, set)
-
-  this.set = set
-}
-
-Minimatch.prototype.parseNegate = parseNegate
-function parseNegate () {
-  var pattern = this.pattern
-  var negate = false
-  var options = this.options
-  var negateOffset = 0
-
-  if (options.nonegate) return
-
-  for (var i = 0, l = pattern.length
-    ; i < l && pattern.charAt(i) === '!'
-    ; i++) {
-    negate = !negate
-    negateOffset++
-  }
-
-  if (negateOffset) this.pattern = pattern.substr(negateOffset)
-  this.negate = negate
-}
-
-// Brace expansion:
-// a{b,c}d -> abd acd
-// a{b,}c -> abc ac
-// a{0..3}d -> a0d a1d a2d a3d
-// a{b,c{d,e}f}g -> abg acdfg acefg
-// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
-//
-// Invalid sets are not expanded.
-// a{2..}b -> a{2..}b
-// a{b}c -> a{b}c
-minimatch.braceExpand = function (pattern, options) {
-  return braceExpand(pattern, options)
-}
-
-Minimatch.prototype.braceExpand = braceExpand
-
-function braceExpand (pattern, options) {
-  if (!options) {
-    if (this instanceof Minimatch) {
-      options = this.options
-    } else {
-      options = {}
-    }
-  }
-
-  pattern = typeof pattern === 'undefined'
-    ? this.pattern : pattern
-
-  assertValidPattern(pattern)
-
-  // Thanks to Yeting Li  for
-  // improving this regexp to avoid a ReDOS vulnerability.
-  if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
-    // shortcut. no need to expand.
-    return [pattern]
-  }
-
-  return expand(pattern)
-}
-
-var MAX_PATTERN_LENGTH = 1024 * 64
-var assertValidPattern = function (pattern) {
-  if (typeof pattern !== 'string') {
-    throw new TypeError('invalid pattern')
-  }
-
-  if (pattern.length > MAX_PATTERN_LENGTH) {
-    throw new TypeError('pattern is too long')
-  }
-}
-
-// parse a component of the expanded set.
-// At this point, no pattern may contain "/" in it
-// so we're going to return a 2d array, where each entry is the full
-// pattern, split on '/', and then turned into a regular expression.
-// A regexp is made at the end which joins each array with an
-// escaped /, and another full one which joins each regexp with |.
-//
-// Following the lead of Bash 4.1, note that "**" only has special meaning
-// when it is the *only* thing in a path portion.  Otherwise, any series
-// of * is equivalent to a single *.  Globstar behavior is enabled by
-// default, and can be disabled by setting options.noglobstar.
-Minimatch.prototype.parse = parse
-var SUBPARSE = {}
-function parse (pattern, isSub) {
-  assertValidPattern(pattern)
-
-  var options = this.options
-
-  // shortcuts
-  if (pattern === '**') {
-    if (!options.noglobstar)
-      return GLOBSTAR
-    else
-      pattern = '*'
-  }
-  if (pattern === '') return ''
-
-  var re = ''
-  var hasMagic = !!options.nocase
-  var escaping = false
-  // ? => one single character
-  var patternListStack = []
-  var negativeLists = []
-  var stateChar
-  var inClass = false
-  var reClassStart = -1
-  var classStart = -1
-  // . and .. never match anything that doesn't start with .,
-  // even when options.dot is set.
-  var patternStart = pattern.charAt(0) === '.' ? '' // anything
-  // not (start or / followed by . or .. followed by / or end)
-  : options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))'
-  : '(?!\\.)'
-  var self = this
-
-  function clearStateChar () {
-    if (stateChar) {
-      // we had some state-tracking character
-      // that wasn't consumed by this pass.
-      switch (stateChar) {
-        case '*':
-          re += star
-          hasMagic = true
-        break
-        case '?':
-          re += qmark
-          hasMagic = true
-        break
-        default:
-          re += '\\' + stateChar
-        break
-      }
-      self.debug('clearStateChar %j %j', stateChar, re)
-      stateChar = false
-    }
-  }
-
-  for (var i = 0, len = pattern.length, c
-    ; (i < len) && (c = pattern.charAt(i))
-    ; i++) {
-    this.debug('%s\t%s %s %j', pattern, i, re, c)
-
-    // skip over any that are escaped.
-    if (escaping && reSpecials[c]) {
-      re += '\\' + c
-      escaping = false
-      continue
-    }
-
-    switch (c) {
-      /* istanbul ignore next */
-      case '/': {
-        // completely not allowed, even escaped.
-        // Should already be path-split by now.
-        return false
-      }
-
-      case '\\':
-        clearStateChar()
-        escaping = true
-      continue
-
-      // the various stateChar values
-      // for the "extglob" stuff.
-      case '?':
-      case '*':
-      case '+':
-      case '@':
-      case '!':
-        this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c)
-
-        // all of those are literals inside a class, except that
-        // the glob [!a] means [^a] in regexp
-        if (inClass) {
-          this.debug('  in class')
-          if (c === '!' && i === classStart + 1) c = '^'
-          re += c
-          continue
-        }
-
-        // if we already have a stateChar, then it means
-        // that there was something like ** or +? in there.
-        // Handle the stateChar, then proceed with this one.
-        self.debug('call clearStateChar %j', stateChar)
-        clearStateChar()
-        stateChar = c
-        // if extglob is disabled, then +(asdf|foo) isn't a thing.
-        // just clear the statechar *now*, rather than even diving into
-        // the patternList stuff.
-        if (options.noext) clearStateChar()
-      continue
-
-      case '(':
-        if (inClass) {
-          re += '('
-          continue
-        }
-
-        if (!stateChar) {
-          re += '\\('
-          continue
-        }
-
-        patternListStack.push({
-          type: stateChar,
-          start: i - 1,
-          reStart: re.length,
-          open: plTypes[stateChar].open,
-          close: plTypes[stateChar].close
-        })
-        // negation is (?:(?!js)[^/]*)
-        re += stateChar === '!' ? '(?:(?!(?:' : '(?:'
-        this.debug('plType %j %j', stateChar, re)
-        stateChar = false
-      continue
-
-      case ')':
-        if (inClass || !patternListStack.length) {
-          re += '\\)'
-          continue
-        }
-
-        clearStateChar()
-        hasMagic = true
-        var pl = patternListStack.pop()
-        // negation is (?:(?!js)[^/]*)
-        // The others are (?:)
-        re += pl.close
-        if (pl.type === '!') {
-          negativeLists.push(pl)
-        }
-        pl.reEnd = re.length
-      continue
-
-      case '|':
-        if (inClass || !patternListStack.length || escaping) {
-          re += '\\|'
-          escaping = false
-          continue
-        }
-
-        clearStateChar()
-        re += '|'
-      continue
-
-      // these are mostly the same in regexp and glob
-      case '[':
-        // swallow any state-tracking char before the [
-        clearStateChar()
-
-        if (inClass) {
-          re += '\\' + c
-          continue
-        }
-
-        inClass = true
-        classStart = i
-        reClassStart = re.length
-        re += c
-      continue
-
-      case ']':
-        //  a right bracket shall lose its special
-        //  meaning and represent itself in
-        //  a bracket expression if it occurs
-        //  first in the list.  -- POSIX.2 2.8.3.2
-        if (i === classStart + 1 || !inClass) {
-          re += '\\' + c
-          escaping = false
-          continue
-        }
-
-        // handle the case where we left a class open.
-        // "[z-a]" is valid, equivalent to "\[z-a\]"
-        // split where the last [ was, make sure we don't have
-        // an invalid re. if so, re-walk the contents of the
-        // would-be class to re-translate any characters that
-        // were passed through as-is
-        // TODO: It would probably be faster to determine this
-        // without a try/catch and a new RegExp, but it's tricky
-        // to do safely.  For now, this is safe and works.
-        var cs = pattern.substring(classStart + 1, i)
-        try {
-          RegExp('[' + cs + ']')
-        } catch (er) {
-          // not a valid class!
-          var sp = this.parse(cs, SUBPARSE)
-          re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'
-          hasMagic = hasMagic || sp[1]
-          inClass = false
-          continue
-        }
-
-        // finish up the class.
-        hasMagic = true
-        inClass = false
-        re += c
-      continue
-
-      default:
-        // swallow any state char that wasn't consumed
-        clearStateChar()
-
-        if (escaping) {
-          // no need
-          escaping = false
-        } else if (reSpecials[c]
-          && !(c === '^' && inClass)) {
-          re += '\\'
-        }
-
-        re += c
-
-    } // switch
-  } // for
-
-  // handle the case where we left a class open.
-  // "[abc" is valid, equivalent to "\[abc"
-  if (inClass) {
-    // split where the last [ was, and escape it
-    // this is a huge pita.  We now have to re-walk
-    // the contents of the would-be class to re-translate
-    // any characters that were passed through as-is
-    cs = pattern.substr(classStart + 1)
-    sp = this.parse(cs, SUBPARSE)
-    re = re.substr(0, reClassStart) + '\\[' + sp[0]
-    hasMagic = hasMagic || sp[1]
-  }
-
-  // handle the case where we had a +( thing at the *end*
-  // of the pattern.
-  // each pattern list stack adds 3 chars, and we need to go through
-  // and escape any | chars that were passed through as-is for the regexp.
-  // Go through and escape them, taking care not to double-escape any
-  // | chars that were already escaped.
-  for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
-    var tail = re.slice(pl.reStart + pl.open.length)
-    this.debug('setting tail', re, pl)
-    // maybe some even number of \, then maybe 1 \, followed by a |
-    tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) {
-      if (!$2) {
-        // the | isn't already escaped, so escape it.
-        $2 = '\\'
-      }
-
-      // need to escape all those slashes *again*, without escaping the
-      // one that we need for escaping the | character.  As it works out,
-      // escaping an even number of slashes can be done by simply repeating
-      // it exactly after itself.  That's why this trick works.
-      //
-      // I am sorry that you have to see this.
-      return $1 + $1 + $2 + '|'
-    })
-
-    this.debug('tail=%j\n   %s', tail, tail, pl, re)
-    var t = pl.type === '*' ? star
-      : pl.type === '?' ? qmark
-      : '\\' + pl.type
-
-    hasMagic = true
-    re = re.slice(0, pl.reStart) + t + '\\(' + tail
-  }
-
-  // handle trailing things that only matter at the very end.
-  clearStateChar()
-  if (escaping) {
-    // trailing \\
-    re += '\\\\'
-  }
-
-  // only need to apply the nodot start if the re starts with
-  // something that could conceivably capture a dot
-  var addPatternStart = false
-  switch (re.charAt(0)) {
-    case '[': case '.': case '(': addPatternStart = true
-  }
-
-  // Hack to work around lack of negative lookbehind in JS
-  // A pattern like: *.!(x).!(y|z) needs to ensure that a name
-  // like 'a.xyz.yz' doesn't match.  So, the first negative
-  // lookahead, has to look ALL the way ahead, to the end of
-  // the pattern.
-  for (var n = negativeLists.length - 1; n > -1; n--) {
-    var nl = negativeLists[n]
-
-    var nlBefore = re.slice(0, nl.reStart)
-    var nlFirst = re.slice(nl.reStart, nl.reEnd - 8)
-    var nlLast = re.slice(nl.reEnd - 8, nl.reEnd)
-    var nlAfter = re.slice(nl.reEnd)
-
-    nlLast += nlAfter
-
-    // Handle nested stuff like *(*.js|!(*.json)), where open parens
-    // mean that we should *not* include the ) in the bit that is considered
-    // "after" the negated section.
-    var openParensBefore = nlBefore.split('(').length - 1
-    var cleanAfter = nlAfter
-    for (i = 0; i < openParensBefore; i++) {
-      cleanAfter = cleanAfter.replace(/\)[+*?]?/, '')
-    }
-    nlAfter = cleanAfter
-
-    var dollar = ''
-    if (nlAfter === '' && isSub !== SUBPARSE) {
-      dollar = '$'
-    }
-    var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast
-    re = newRe
-  }
-
-  // if the re is not "" at this point, then we need to make sure
-  // it doesn't match against an empty path part.
-  // Otherwise a/* will match a/, which it should not.
-  if (re !== '' && hasMagic) {
-    re = '(?=.)' + re
-  }
-
-  if (addPatternStart) {
-    re = patternStart + re
-  }
-
-  // parsing just a piece of a larger pattern.
-  if (isSub === SUBPARSE) {
-    return [re, hasMagic]
-  }
-
-  // skip the regexp for non-magical patterns
-  // unescape anything in it, though, so that it'll be
-  // an exact match against a file etc.
-  if (!hasMagic) {
-    return globUnescape(pattern)
-  }
-
-  var flags = options.nocase ? 'i' : ''
-  try {
-    var regExp = new RegExp('^' + re + '$', flags)
-  } catch (er) /* istanbul ignore next - should be impossible */ {
-    // If it was an invalid regular expression, then it can't match
-    // anything.  This trick looks for a character after the end of
-    // the string, which is of course impossible, except in multi-line
-    // mode, but it's not a /m regex.
-    return new RegExp('$.')
-  }
-
-  regExp._glob = pattern
-  regExp._src = re
-
-  return regExp
-}
-
-minimatch.makeRe = function (pattern, options) {
-  return new Minimatch(pattern, options || {}).makeRe()
-}
-
-Minimatch.prototype.makeRe = makeRe
-function makeRe () {
-  if (this.regexp || this.regexp === false) return this.regexp
-
-  // at this point, this.set is a 2d array of partial
-  // pattern strings, or "**".
-  //
-  // It's better to use .match().  This function shouldn't
-  // be used, really, but it's pretty convenient sometimes,
-  // when you just want to work with a regex.
-  var set = this.set
-
-  if (!set.length) {
-    this.regexp = false
-    return this.regexp
-  }
-  var options = this.options
-
-  var twoStar = options.noglobstar ? star
-    : options.dot ? twoStarDot
-    : twoStarNoDot
-  var flags = options.nocase ? 'i' : ''
-
-  var re = set.map(function (pattern) {
-    return pattern.map(function (p) {
-      return (p === GLOBSTAR) ? twoStar
-      : (typeof p === 'string') ? regExpEscape(p)
-      : p._src
-    }).join('\\\/')
-  }).join('|')
-
-  // must match entire pattern
-  // ending in a * or ** will make it less strict.
-  re = '^(?:' + re + ')$'
-
-  // can match anything, as long as it's not this.
-  if (this.negate) re = '^(?!' + re + ').*$'
-
-  try {
-    this.regexp = new RegExp(re, flags)
-  } catch (ex) /* istanbul ignore next - should be impossible */ {
-    this.regexp = false
-  }
-  return this.regexp
-}
-
-minimatch.match = function (list, pattern, options) {
-  options = options || {}
-  var mm = new Minimatch(pattern, options)
-  list = list.filter(function (f) {
-    return mm.match(f)
-  })
-  if (mm.options.nonull && !list.length) {
-    list.push(pattern)
-  }
-  return list
-}
-
-Minimatch.prototype.match = function match (f, partial) {
-  if (typeof partial === 'undefined') partial = this.partial
-  this.debug('match', f, this.pattern)
-  // short-circuit in the case of busted things.
-  // comments, etc.
-  if (this.comment) return false
-  if (this.empty) return f === ''
-
-  if (f === '/' && partial) return true
-
-  var options = this.options
-
-  // windows: need to use /, not \
-  if (path.sep !== '/') {
-    f = f.split(path.sep).join('/')
-  }
-
-  // treat the test path as a set of pathparts.
-  f = f.split(slashSplit)
-  this.debug(this.pattern, 'split', f)
-
-  // just ONE of the pattern sets in this.set needs to match
-  // in order for it to be valid.  If negating, then just one
-  // match means that we have failed.
-  // Either way, return on the first hit.
-
-  var set = this.set
-  this.debug(this.pattern, 'set', set)
-
-  // Find the basename of the path by looking for the last non-empty segment
-  var filename
-  var i
-  for (i = f.length - 1; i >= 0; i--) {
-    filename = f[i]
-    if (filename) break
-  }
-
-  for (i = 0; i < set.length; i++) {
-    var pattern = set[i]
-    var file = f
-    if (options.matchBase && pattern.length === 1) {
-      file = [filename]
-    }
-    var hit = this.matchOne(file, pattern, partial)
-    if (hit) {
-      if (options.flipNegate) return true
-      return !this.negate
-    }
-  }
-
-  // didn't get any hits.  this is success if it's a negative
-  // pattern, failure otherwise.
-  if (options.flipNegate) return false
-  return this.negate
-}
-
-// set partial to true to test if, for example,
-// "/a/b" matches the start of "/*/b/*/d"
-// Partial means, if you run out of file before you run
-// out of pattern, then that's fine, as long as all
-// the parts match.
-Minimatch.prototype.matchOne = function (file, pattern, partial) {
-  var options = this.options
-
-  this.debug('matchOne',
-    { 'this': this, file: file, pattern: pattern })
-
-  this.debug('matchOne', file.length, pattern.length)
-
-  for (var fi = 0,
-      pi = 0,
-      fl = file.length,
-      pl = pattern.length
-      ; (fi < fl) && (pi < pl)
-      ; fi++, pi++) {
-    this.debug('matchOne loop')
-    var p = pattern[pi]
-    var f = file[fi]
-
-    this.debug(pattern, p, f)
-
-    // should be impossible.
-    // some invalid regexp stuff in the set.
-    /* istanbul ignore if */
-    if (p === false) return false
-
-    if (p === GLOBSTAR) {
-      this.debug('GLOBSTAR', [pattern, p, f])
-
-      // "**"
-      // a/**/b/**/c would match the following:
-      // a/b/x/y/z/c
-      // a/x/y/z/b/c
-      // a/b/x/b/x/c
-      // a/b/c
-      // To do this, take the rest of the pattern after
-      // the **, and see if it would match the file remainder.
-      // If so, return success.
-      // If not, the ** "swallows" a segment, and try again.
-      // This is recursively awful.
-      //
-      // a/**/b/**/c matching a/b/x/y/z/c
-      // - a matches a
-      // - doublestar
-      //   - matchOne(b/x/y/z/c, b/**/c)
-      //     - b matches b
-      //     - doublestar
-      //       - matchOne(x/y/z/c, c) -> no
-      //       - matchOne(y/z/c, c) -> no
-      //       - matchOne(z/c, c) -> no
-      //       - matchOne(c, c) yes, hit
-      var fr = fi
-      var pr = pi + 1
-      if (pr === pl) {
-        this.debug('** at the end')
-        // a ** at the end will just swallow the rest.
-        // We have found a match.
-        // however, it will not swallow /.x, unless
-        // options.dot is set.
-        // . and .. are *never* matched by **, for explosively
-        // exponential reasons.
-        for (; fi < fl; fi++) {
-          if (file[fi] === '.' || file[fi] === '..' ||
-            (!options.dot && file[fi].charAt(0) === '.')) return false
-        }
-        return true
-      }
-
-      // ok, let's see if we can swallow whatever we can.
-      while (fr < fl) {
-        var swallowee = file[fr]
-
-        this.debug('\nglobstar while', file, fr, pattern, pr, swallowee)
-
-        // XXX remove this slice.  Just pass the start index.
-        if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
-          this.debug('globstar found match!', fr, fl, swallowee)
-          // found a match.
-          return true
-        } else {
-          // can't swallow "." or ".." ever.
-          // can only swallow ".foo" when explicitly asked.
-          if (swallowee === '.' || swallowee === '..' ||
-            (!options.dot && swallowee.charAt(0) === '.')) {
-            this.debug('dot detected!', file, fr, pattern, pr)
-            break
-          }
-
-          // ** swallows a segment, and continue.
-          this.debug('globstar swallow a segment, and continue')
-          fr++
-        }
-      }
-
-      // no match was found.
-      // However, in partial mode, we can't say this is necessarily over.
-      // If there's more *pattern* left, then
-      /* istanbul ignore if */
-      if (partial) {
-        // ran out of file
-        this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
-        if (fr === fl) return true
-      }
-      return false
-    }
-
-    // something other than **
-    // non-magic patterns just have to match exactly
-    // patterns with magic have been turned into regexps.
-    var hit
-    if (typeof p === 'string') {
-      hit = f === p
-      this.debug('string match', p, f, hit)
-    } else {
-      hit = f.match(p)
-      this.debug('pattern match', p, f, hit)
-    }
-
-    if (!hit) return false
-  }
-
-  // Note: ending in / means that we'll get a final ""
-  // at the end of the pattern.  This can only match a
-  // corresponding "" at the end of the file.
-  // If the file ends in /, then it can only match a
-  // a pattern that ends in /, unless the pattern just
-  // doesn't have any more for it. But, a/b/ should *not*
-  // match "a/b/*", even though "" matches against the
-  // [^/]*? pattern, except in partial mode, where it might
-  // simply not be reached yet.
-  // However, a/b/ should still satisfy a/*
-
-  // now either we fell off the end of the pattern, or we're done.
-  if (fi === fl && pi === pl) {
-    // ran out of pattern and filename at the same time.
-    // an exact hit!
-    return true
-  } else if (fi === fl) {
-    // ran out of file, but still had pattern left.
-    // this is ok if we're doing the match as part of
-    // a glob fs traversal.
-    return partial
-  } else /* istanbul ignore else */ if (pi === pl) {
-    // ran out of pattern, still have file left.
-    // this is only acceptable if we're on the very last
-    // empty segment of a file with a trailing slash.
-    // a/* should match a/b/
-    return (fi === fl - 1) && (file[fi] === '')
-  }
-
-  // should be unreachable.
-  /* istanbul ignore next */
-  throw new Error('wtf?')
-}
-
-// replace stuff like \* with *
-function globUnescape (s) {
-  return s.replace(/\\(.)/g, '$1')
-}
-
-function regExpEscape (s) {
-  return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
-}
diff --git a/deps/npm/node_modules/rimraf/node_modules/minimatch/package.json b/deps/npm/node_modules/rimraf/node_modules/minimatch/package.json
deleted file mode 100644
index 566efdfe45cb80..00000000000000
--- a/deps/npm/node_modules/rimraf/node_modules/minimatch/package.json
+++ /dev/null
@@ -1,33 +0,0 @@
-{
-  "author": "Isaac Z. Schlueter  (http://blog.izs.me)",
-  "name": "minimatch",
-  "description": "a glob matcher in javascript",
-  "version": "3.1.2",
-  "publishConfig": {
-    "tag": "v3-legacy"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/isaacs/minimatch.git"
-  },
-  "main": "minimatch.js",
-  "scripts": {
-    "test": "tap",
-    "preversion": "npm test",
-    "postversion": "npm publish",
-    "postpublish": "git push origin --all; git push origin --tags"
-  },
-  "engines": {
-    "node": "*"
-  },
-  "dependencies": {
-    "brace-expansion": "^1.1.7"
-  },
-  "devDependencies": {
-    "tap": "^15.1.6"
-  },
-  "license": "ISC",
-  "files": [
-    "minimatch.js"
-  ]
-}
diff --git a/deps/npm/node_modules/rimraf/package.json b/deps/npm/node_modules/rimraf/package.json
deleted file mode 100644
index 1bf8d5e38775d7..00000000000000
--- a/deps/npm/node_modules/rimraf/package.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
-  "name": "rimraf",
-  "version": "3.0.2",
-  "main": "rimraf.js",
-  "description": "A deep deletion module for node (like `rm -rf`)",
-  "author": "Isaac Z. Schlueter  (http://blog.izs.me/)",
-  "license": "ISC",
-  "repository": "git://github.com/isaacs/rimraf.git",
-  "scripts": {
-    "preversion": "npm test",
-    "postversion": "npm publish",
-    "postpublish": "git push origin --follow-tags",
-    "test": "tap test/*.js"
-  },
-  "bin": "./bin.js",
-  "dependencies": {
-    "glob": "^7.1.3"
-  },
-  "files": [
-    "LICENSE",
-    "README.md",
-    "bin.js",
-    "rimraf.js"
-  ],
-  "devDependencies": {
-    "mkdirp": "^0.5.1",
-    "tap": "^12.1.1"
-  },
-  "funding": {
-    "url": "https://github.com/sponsors/isaacs"
-  }
-}
diff --git a/deps/npm/node_modules/rimraf/rimraf.js b/deps/npm/node_modules/rimraf/rimraf.js
deleted file mode 100644
index 34da4171d75598..00000000000000
--- a/deps/npm/node_modules/rimraf/rimraf.js
+++ /dev/null
@@ -1,360 +0,0 @@
-const assert = require("assert")
-const path = require("path")
-const fs = require("fs")
-let glob = undefined
-try {
-  glob = require("glob")
-} catch (_err) {
-  // treat glob as optional.
-}
-
-const defaultGlobOpts = {
-  nosort: true,
-  silent: true
-}
-
-// for EMFILE handling
-let timeout = 0
-
-const isWindows = (process.platform === "win32")
-
-const defaults = options => {
-  const methods = [
-    'unlink',
-    'chmod',
-    'stat',
-    'lstat',
-    'rmdir',
-    'readdir'
-  ]
-  methods.forEach(m => {
-    options[m] = options[m] || fs[m]
-    m = m + 'Sync'
-    options[m] = options[m] || fs[m]
-  })
-
-  options.maxBusyTries = options.maxBusyTries || 3
-  options.emfileWait = options.emfileWait || 1000
-  if (options.glob === false) {
-    options.disableGlob = true
-  }
-  if (options.disableGlob !== true && glob === undefined) {
-    throw Error('glob dependency not found, set `options.disableGlob = true` if intentional')
-  }
-  options.disableGlob = options.disableGlob || false
-  options.glob = options.glob || defaultGlobOpts
-}
-
-const rimraf = (p, options, cb) => {
-  if (typeof options === 'function') {
-    cb = options
-    options = {}
-  }
-
-  assert(p, 'rimraf: missing path')
-  assert.equal(typeof p, 'string', 'rimraf: path should be a string')
-  assert.equal(typeof cb, 'function', 'rimraf: callback function required')
-  assert(options, 'rimraf: invalid options argument provided')
-  assert.equal(typeof options, 'object', 'rimraf: options should be object')
-
-  defaults(options)
-
-  let busyTries = 0
-  let errState = null
-  let n = 0
-
-  const next = (er) => {
-    errState = errState || er
-    if (--n === 0)
-      cb(errState)
-  }
-
-  const afterGlob = (er, results) => {
-    if (er)
-      return cb(er)
-
-    n = results.length
-    if (n === 0)
-      return cb()
-
-    results.forEach(p => {
-      const CB = (er) => {
-        if (er) {
-          if ((er.code === "EBUSY" || er.code === "ENOTEMPTY" || er.code === "EPERM") &&
-              busyTries < options.maxBusyTries) {
-            busyTries ++
-            // try again, with the same exact callback as this one.
-            return setTimeout(() => rimraf_(p, options, CB), busyTries * 100)
-          }
-
-          // this one won't happen if graceful-fs is used.
-          if (er.code === "EMFILE" && timeout < options.emfileWait) {
-            return setTimeout(() => rimraf_(p, options, CB), timeout ++)
-          }
-
-          // already gone
-          if (er.code === "ENOENT") er = null
-        }
-
-        timeout = 0
-        next(er)
-      }
-      rimraf_(p, options, CB)
-    })
-  }
-
-  if (options.disableGlob || !glob.hasMagic(p))
-    return afterGlob(null, [p])
-
-  options.lstat(p, (er, stat) => {
-    if (!er)
-      return afterGlob(null, [p])
-
-    glob(p, options.glob, afterGlob)
-  })
-
-}
-
-// Two possible strategies.
-// 1. Assume it's a file.  unlink it, then do the dir stuff on EPERM or EISDIR
-// 2. Assume it's a directory.  readdir, then do the file stuff on ENOTDIR
-//
-// Both result in an extra syscall when you guess wrong.  However, there
-// are likely far more normal files in the world than directories.  This
-// is based on the assumption that a the average number of files per
-// directory is >= 1.
-//
-// If anyone ever complains about this, then I guess the strategy could
-// be made configurable somehow.  But until then, YAGNI.
-const rimraf_ = (p, options, cb) => {
-  assert(p)
-  assert(options)
-  assert(typeof cb === 'function')
-
-  // sunos lets the root user unlink directories, which is... weird.
-  // so we have to lstat here and make sure it's not a dir.
-  options.lstat(p, (er, st) => {
-    if (er && er.code === "ENOENT")
-      return cb(null)
-
-    // Windows can EPERM on stat.  Life is suffering.
-    if (er && er.code === "EPERM" && isWindows)
-      fixWinEPERM(p, options, er, cb)
-
-    if (st && st.isDirectory())
-      return rmdir(p, options, er, cb)
-
-    options.unlink(p, er => {
-      if (er) {
-        if (er.code === "ENOENT")
-          return cb(null)
-        if (er.code === "EPERM")
-          return (isWindows)
-            ? fixWinEPERM(p, options, er, cb)
-            : rmdir(p, options, er, cb)
-        if (er.code === "EISDIR")
-          return rmdir(p, options, er, cb)
-      }
-      return cb(er)
-    })
-  })
-}
-
-const fixWinEPERM = (p, options, er, cb) => {
-  assert(p)
-  assert(options)
-  assert(typeof cb === 'function')
-
-  options.chmod(p, 0o666, er2 => {
-    if (er2)
-      cb(er2.code === "ENOENT" ? null : er)
-    else
-      options.stat(p, (er3, stats) => {
-        if (er3)
-          cb(er3.code === "ENOENT" ? null : er)
-        else if (stats.isDirectory())
-          rmdir(p, options, er, cb)
-        else
-          options.unlink(p, cb)
-      })
-  })
-}
-
-const fixWinEPERMSync = (p, options, er) => {
-  assert(p)
-  assert(options)
-
-  try {
-    options.chmodSync(p, 0o666)
-  } catch (er2) {
-    if (er2.code === "ENOENT")
-      return
-    else
-      throw er
-  }
-
-  let stats
-  try {
-    stats = options.statSync(p)
-  } catch (er3) {
-    if (er3.code === "ENOENT")
-      return
-    else
-      throw er
-  }
-
-  if (stats.isDirectory())
-    rmdirSync(p, options, er)
-  else
-    options.unlinkSync(p)
-}
-
-const rmdir = (p, options, originalEr, cb) => {
-  assert(p)
-  assert(options)
-  assert(typeof cb === 'function')
-
-  // try to rmdir first, and only readdir on ENOTEMPTY or EEXIST (SunOS)
-  // if we guessed wrong, and it's not a directory, then
-  // raise the original error.
-  options.rmdir(p, er => {
-    if (er && (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM"))
-      rmkids(p, options, cb)
-    else if (er && er.code === "ENOTDIR")
-      cb(originalEr)
-    else
-      cb(er)
-  })
-}
-
-const rmkids = (p, options, cb) => {
-  assert(p)
-  assert(options)
-  assert(typeof cb === 'function')
-
-  options.readdir(p, (er, files) => {
-    if (er)
-      return cb(er)
-    let n = files.length
-    if (n === 0)
-      return options.rmdir(p, cb)
-    let errState
-    files.forEach(f => {
-      rimraf(path.join(p, f), options, er => {
-        if (errState)
-          return
-        if (er)
-          return cb(errState = er)
-        if (--n === 0)
-          options.rmdir(p, cb)
-      })
-    })
-  })
-}
-
-// this looks simpler, and is strictly *faster*, but will
-// tie up the JavaScript thread and fail on excessively
-// deep directory trees.
-const rimrafSync = (p, options) => {
-  options = options || {}
-  defaults(options)
-
-  assert(p, 'rimraf: missing path')
-  assert.equal(typeof p, 'string', 'rimraf: path should be a string')
-  assert(options, 'rimraf: missing options')
-  assert.equal(typeof options, 'object', 'rimraf: options should be object')
-
-  let results
-
-  if (options.disableGlob || !glob.hasMagic(p)) {
-    results = [p]
-  } else {
-    try {
-      options.lstatSync(p)
-      results = [p]
-    } catch (er) {
-      results = glob.sync(p, options.glob)
-    }
-  }
-
-  if (!results.length)
-    return
-
-  for (let i = 0; i < results.length; i++) {
-    const p = results[i]
-
-    let st
-    try {
-      st = options.lstatSync(p)
-    } catch (er) {
-      if (er.code === "ENOENT")
-        return
-
-      // Windows can EPERM on stat.  Life is suffering.
-      if (er.code === "EPERM" && isWindows)
-        fixWinEPERMSync(p, options, er)
-    }
-
-    try {
-      // sunos lets the root user unlink directories, which is... weird.
-      if (st && st.isDirectory())
-        rmdirSync(p, options, null)
-      else
-        options.unlinkSync(p)
-    } catch (er) {
-      if (er.code === "ENOENT")
-        return
-      if (er.code === "EPERM")
-        return isWindows ? fixWinEPERMSync(p, options, er) : rmdirSync(p, options, er)
-      if (er.code !== "EISDIR")
-        throw er
-
-      rmdirSync(p, options, er)
-    }
-  }
-}
-
-const rmdirSync = (p, options, originalEr) => {
-  assert(p)
-  assert(options)
-
-  try {
-    options.rmdirSync(p)
-  } catch (er) {
-    if (er.code === "ENOENT")
-      return
-    if (er.code === "ENOTDIR")
-      throw originalEr
-    if (er.code === "ENOTEMPTY" || er.code === "EEXIST" || er.code === "EPERM")
-      rmkidsSync(p, options)
-  }
-}
-
-const rmkidsSync = (p, options) => {
-  assert(p)
-  assert(options)
-  options.readdirSync(p).forEach(f => rimrafSync(path.join(p, f), options))
-
-  // We only end up here once we got ENOTEMPTY at least once, and
-  // at this point, we are guaranteed to have removed all the kids.
-  // So, we know that it won't be ENOENT or ENOTDIR or anything else.
-  // try really hard to delete stuff on windows, because it has a
-  // PROFOUNDLY annoying habit of not closing handles promptly when
-  // files are deleted, resulting in spurious ENOTEMPTY errors.
-  const retries = isWindows ? 100 : 1
-  let i = 0
-  do {
-    let threw = true
-    try {
-      const ret = options.rmdirSync(p, options)
-      threw = false
-      return ret
-    } finally {
-      if (++i < retries && threw)
-        continue
-    }
-  } while (true)
-}
-
-module.exports = rimraf
-rimraf.sync = rimrafSync
diff --git a/deps/npm/node_modules/sigstore/README.md b/deps/npm/node_modules/sigstore/README.md
deleted file mode 100644
index 2540fa808b9796..00000000000000
--- a/deps/npm/node_modules/sigstore/README.md
+++ /dev/null
@@ -1,165 +0,0 @@
-# sigstore · [![npm version](https://img.shields.io/npm/v/sigstore.svg?style=flat)](https://www.npmjs.com/package/sigstore) [![CI Status](https://github.com/sigstore/sigstore-js/workflows/CI/badge.svg)](https://github.com/sigstore/sigstore-js/actions/workflows/ci.yml) [![Smoke Test Status](https://github.com/sigstore/sigstore-js/workflows/smoke-test/badge.svg)](https://github.com/sigstore/sigstore-js/actions/workflows/smoke-test.yml)
-
-A JavaScript library for generating and verifying Sigstore signatures. One of
-the intended uses is to sign and verify npm packages but it can be used to sign
-and verify any file.
-
-## Features
-
-* Support for signing using an OpenID Connect identity
-* Support for publishing signatures to a [Rekor][1] instance
-* Support for verifying Sigstore bundles
-
-## Prerequisites
-
-- Node.js version >= 14.17.0
-
-## Installation
-
-```
-npm install sigstore
-```
-
-## Usage
-
-```javascript
-const { sigstore } = require('sigstore')
-```
-
-```javascript
-import { sigstore } from 'sigstore'
-```
-
-### sign(payload[, options])
-
-Generates a Sigstore signature for the supplied payload. Returns a
-[Sigstore bundle][2] containing the signature and the verification material
-necessary to verify the signature.
-
-* `payload` ``: The bytes of the artifact to be signed.
-* `options` ``
-  * `fulcioURL` ``: The base URL of the Fulcio instance to use for retrieving the signing certificate. Defaults to `'https://fulcio.sigstore.dev'`.
-  * `rekorURL` ``: The base URL of the Rekor instance to use when adding the signature to the transparency log. Defaults to `'https://rekor.sigstore.dev'`.
-  * `tsaServerURL` ``: The base URL of the Timestamp Authority instance to use when requesting a signed timestamp. If omitted, no timestamp will be requested.
-  * `tlogUpload` ``: Flag indicating whether or not the signature should be recorded on the Rekor transparency log. Defaults to `true`.
-  * `identityToken` ``: The OIDC token identifying the signer. If no explicit token is supplied, an attempt will be made to retrieve one from the environment. This config cannot be used with `identityProvider`.
-  * `identityProvider` ``: Object which implements `getToken: () => Promise`. The supplied provider will be used to retrieve an OIDC token. If no provider is supplied, an attempt will be made to retrieve an OIDC token from the environment. This config cannot be used with `identityToken`.
-
-### attest(payload, payloadType[, options])
-
-Generates a Sigstore signature for the supplied in-toto statement. Returns a
-[Sigstore bundle][2] containing the [DSSE][3]-wrapped statement and signature
-as well as the verification material necessary to verify the signature.
-
-* `payload` ``: The bytes of the statement to be signed.
-* `payloadType` ``: MIME or content type describing the statement to be signed.
-* `options` ``
-  * `fulcioURL` ``: The base URL of the Fulcio instance to use for retrieving the signing certificate. Defaults to `'https://fulcio.sigstore.dev'`.
-  * `rekorURL` ``: The base URL of the Rekor instance to use when adding the signature to the transparency log. Defaults to `'https://rekor.sigstore.dev'`.
-  * `tsaServerURL` ``: The base URL of the Timestamp Authority instance to use when requesting a signed timestamp. If omitted, no timestamp will be requested.
-  * `tlogUpload` ``: Flag indicating whether or not the signed statement should be recorded on the Rekor transparency log. Defaults to `true`.
-  * `identityToken` ``: The OIDC token identifying the signer. If no explicit token is supplied, an attempt will be made to retrieve one from the environment. This config cannot be used with `identityProvider`.
-  * `identityProvider` ``: Object which implements `getToken: () => Promise`. The supplied provider will be used to retrieve an OIDC token. If no provider is supplied, an attempt will be made to retrieve an OIDC token from the environment. This config cannot be used with `identityToken`.
-
-
-### verify(bundle[, payload][, options])
-
-Verifies the signature in the supplied bundle.
-
-* `bundle` ``: The Sigstore bundle containing the signature to be verified and the verification material necessary to verify the signature.
-* `payload` ``: The bytes of the artifact over which the signature was created. Only necessary when the `sign` function was used to generate the signature since the Bundle does not contain any information about the artifact which was signed. Not required when the `attest` function was used to generate the Bundle.
-* `options` ``
-  * `ctLogThreshold` ``: The number of certificate transparency logs on which the signing certificate must appear. Defaults to `1`.
-  * `tlogThreshold` ``: The number of transparency logs on which the signature must appear. Defaults to `1`.
-  * `certificateIssuer` ``: Value that must appear in the signing certificate's issuer extension (OID 1.3.6.1.4.1.57264.1.1). Not verified if no value is supplied.
-  * `certificateIdentityEmail` ``: Email address which must appear in the signing certificate's Subject Alternative Name (SAN) extension. Must be specified in conjunction with the `certificateIssuer` option. Takes precedence over the `certificateIdentityURI` option. Not verified if no value is supplied.
-  * `certificateIdentityURI` ``: URI which must appear in the signing certificate's Subject Alternative Name (SAN) extension. Must be specified in conjunction with the `certificateIssuer` option. Ignored if the `certificateIdentityEmail` option is set. Not verified if no value is supplied.
-  * `certificateOIDs` ``: A collection of OID/value pairs which must be present in the certificate's extension list. Not verified if no value is supplied.
-  * `keySelector` ``: Callback invoked to retrieve the public key (as either `string` or `Buffer`) necessary to verify the bundle signature. Not used when the signature was generated from a Fulcio-issued signing certificate.
-    * `hint` ``: The hint from the bundle used to identify the the signing key.
-
-### tuf
-
-The `tuf` object contains utility function for working with the Sigstore TUF repository.
-
-#### client([options])
-
-Returns a TUF client which can be used to retrieve targets from the Sigstore TUF repository.
-
-* `options` ``
-  * `tufMirrorURL` ``: Base URL for the Sigstore TUF repository. Defaults to `'https://tuf-repo-cdn.sigstore.dev'`
-  * `tufRootPath` ``: Path to the initial trusted root for the TUF repository. Defaults to the embedded root.
-  * `tufCachePath` ``: Absolute path to the directory to be used for caching downloaded TUF metadata and targets. Defaults to a directory named "sigstore-js" within the platform-specific application data directory.
-
-The returned object exposes a `getTarget(path)` function which returns the
-contents of the target at the specified path in the Sigstore TUF repository.
-
-#### getTarget(path[, options]) (deprecated)
-
-Returns the contents of the target at the specified path in the Sigstore TUF repository.
-This method has been deprecated and will be removed in the next major version.
-You should use the TUF `client` function to retrieve a stateful TUF client and
-then call `getTarget` against that object. This will avoid re-initializing the
-internal TUF state between requests.
-
-* `path` ``: The [path-relative-url string](https://url.spec.whatwg.org/#path-relative-url-string) that uniquely identifies the target within the Sigstore TUF repository.
-* `options` ``
-  * `tufMirrorURL` ``: Base URL for the Sigstore TUF repository. Defaults to `'https://tuf-repo-cdn.sigstore.dev'`
-  * `tufRootPath` ``: Path to the initial trusted root for the TUF repository. Defaults to the embedded root.
-  * `tufCachePath` ``: Absolute path to the directory to be used for caching downloaded TUF metadata and targets. Defaults to a directory named "sigstore-js" within the platform-specific application data directory.
-
-
-### utils
-
-The `utils` object contains a few internal utility functions. These are exposed
-to support the needs of specific `sigstore-js` consumers but should **NOT** be
-considered part of the stable public interface.
-
-## CLI
-
-The `sigstore-js` library comes packaged with a basic command line interface
-for testing and demo purposes. However, the CLI should **NOT** be considered
-part of the stable interface of the library. If you require a production-ready
-Sigstore CLI, we recommend you use [`cosign`][4].
-
-```shell
-$ npx sigstore help
-sigstore  
-
-  Usage:
-
-  sigstore sign         sign an artifact
-  sigstore attest       sign an artifact using dsse (Dead Simple Signing Envelope)
-  sigstore verify       verify an artifact
-  sigstore version      print version information
-  sigstore help         print help information
-```
-
-## Credential Sources
-
-### GitHub Actions
-
-If sigstore-js detects that it is being executed on GitHub Actions, it will use `ACTIONS_ID_TOKEN_REQUEST_URL`
-and `ACTIONS_ID_TOKEN_REQUEST_TOKEN` environment variables to request an OIDC token with the correct scope.
-
-Note: the `id_token: write` permission must be granted to the GitHub Action Job.
-
-See https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect
-for more details.
-
-### Environment Variables
-
-If the `SIGSTORE_ID_TOKEN` environment variable is set, it will use this to authenticate to Fulcio.
-It is the callers responsibility to make sure that this token has the correct scopes.
-
-### Interactive Flow
-
-If sigstore-js cannot detect ambient credentials, then it will prompt the user to go through the
-interactive flow.
-
-
-
-[1]: https://github.com/sigstore/rekor
-[2]: https://github.com/sigstore/protobuf-specs/blob/9b722b68a717778ba4f11543afa4ef93205ab502/protos/sigstore_bundle.proto#L63-L84
-[3]: https://github.com/secure-systems-lab/dsse
-[4]: https://github.com/sigstore/cosign
diff --git a/deps/npm/node_modules/sigstore/bin/sigstore.js b/deps/npm/node_modules/sigstore/bin/sigstore.js
deleted file mode 100755
index a07b7bdc1af95a..00000000000000
--- a/deps/npm/node_modules/sigstore/bin/sigstore.js
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env node
-/*
-Copyright 2022 The Sigstore Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-require('../dist/cli').processArgv();
diff --git a/deps/npm/node_modules/sigstore/dist/ca/format.d.ts b/deps/npm/node_modules/sigstore/dist/ca/format.d.ts
deleted file mode 100644
index b29f51a71f5647..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/ca/format.d.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-/// 
-/// 
-import { KeyObject } from 'crypto';
-import type { SigningCertificateRequest } from '../external/fulcio';
-export declare function toCertificateRequest(identityToken: string, publicKey: KeyObject, challenge: Buffer): SigningCertificateRequest;
diff --git a/deps/npm/node_modules/sigstore/dist/ca/format.js b/deps/npm/node_modules/sigstore/dist/ca/format.js
deleted file mode 100644
index 6374243e80e026..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/ca/format.js
+++ /dev/null
@@ -1,20 +0,0 @@
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.toCertificateRequest = void 0;
-function toCertificateRequest(identityToken, publicKey, challenge) {
-    return {
-        credentials: {
-            oidcIdentityToken: identityToken,
-        },
-        publicKeyRequest: {
-            publicKey: {
-                algorithm: 'ECDSA',
-                content: publicKey
-                    .export({ format: 'pem', type: 'spki' })
-                    .toString('ascii'),
-            },
-            proofOfPossession: challenge.toString('base64'),
-        },
-    };
-}
-exports.toCertificateRequest = toCertificateRequest;
diff --git a/deps/npm/node_modules/sigstore/dist/ca/index.d.ts b/deps/npm/node_modules/sigstore/dist/ca/index.d.ts
deleted file mode 100644
index 3a6347293aaa8b..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/ca/index.d.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-/// 
-/// 
-import { KeyObject } from 'crypto';
-import type { FetchOptions } from '../types/fetch';
-export interface CA {
-    createSigningCertificate: (identityToken: string, publicKey: KeyObject, challenge: Buffer) => Promise;
-}
-export type CAClientOptions = {
-    fulcioBaseURL: string;
-} & FetchOptions;
-export declare class CAClient implements CA {
-    private fulcio;
-    constructor(options: CAClientOptions);
-    createSigningCertificate(identityToken: string, publicKey: KeyObject, challenge: Buffer): Promise;
-}
diff --git a/deps/npm/node_modules/sigstore/dist/ca/index.js b/deps/npm/node_modules/sigstore/dist/ca/index.js
deleted file mode 100644
index 340dd46609aad2..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/ca/index.js
+++ /dev/null
@@ -1,39 +0,0 @@
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.CAClient = void 0;
-const error_1 = require("../error");
-const external_1 = require("../external");
-const format_1 = require("./format");
-class CAClient {
-    constructor(options) {
-        this.fulcio = new external_1.Fulcio({
-            baseURL: options.fulcioBaseURL,
-            retry: options.retry,
-            timeout: options.timeout,
-        });
-    }
-    async createSigningCertificate(identityToken, publicKey, challenge) {
-        const request = (0, format_1.toCertificateRequest)(identityToken, publicKey, challenge);
-        try {
-            const resp = await this.fulcio.createSigningCertificate(request);
-            // Account for the fact that the response may contain either a
-            // signedCertificateEmbeddedSct or a signedCertificateDetachedSct.
-            const cert = resp.signedCertificateEmbeddedSct
-                ? resp.signedCertificateEmbeddedSct
-                : resp.signedCertificateDetachedSct;
-            // Return the first certificate in the chain, which is the signing
-            // certificate. Specifically not returning the rest of the chain to
-            // mitigate the risk of errors when verifying the certificate chain.
-            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-            return cert.chain.certificates.slice(0, 1);
-        }
-        catch (err) {
-            throw new error_1.InternalError({
-                code: 'CA_CREATE_SIGNING_CERTIFICATE_ERROR',
-                message: 'error creating signing certificate',
-                cause: err,
-            });
-        }
-    }
-}
-exports.CAClient = CAClient;
diff --git a/deps/npm/node_modules/sigstore/dist/ca/verify/chain.d.ts b/deps/npm/node_modules/sigstore/dist/ca/verify/chain.d.ts
deleted file mode 100644
index 0a79b42f714a0f..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/ca/verify/chain.d.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import * as sigstore from '../../types/sigstore';
-import { x509Certificate } from '../../x509/cert';
-export declare function verifyChain(certificate: sigstore.X509Certificate, certificateAuthorities: sigstore.CertificateAuthority[]): x509Certificate[];
diff --git a/deps/npm/node_modules/sigstore/dist/ca/verify/index.d.ts b/deps/npm/node_modules/sigstore/dist/ca/verify/index.d.ts
deleted file mode 100644
index ddf65ff6dfffd8..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/ca/verify/index.d.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-import * as sigstore from '../../types/sigstore';
-export declare function verifySigningCertificate(bundle: sigstore.BundleWithCertificateChain, trustedRoot: sigstore.TrustedRoot, options: sigstore.CAArtifactVerificationOptions): void;
diff --git a/deps/npm/node_modules/sigstore/dist/ca/verify/sct.d.ts b/deps/npm/node_modules/sigstore/dist/ca/verify/sct.d.ts
deleted file mode 100644
index 29391a74cb65e6..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/ca/verify/sct.d.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import * as sigstore from '../../types/sigstore';
-import { x509Certificate } from '../../x509/cert';
-export declare function verifySCTs(certificateChain: x509Certificate[], ctLogs: sigstore.TransparencyLogInstance[], options: sigstore.ArtifactVerificationOptions_CtlogOptions): void;
diff --git a/deps/npm/node_modules/sigstore/dist/ca/verify/signer.d.ts b/deps/npm/node_modules/sigstore/dist/ca/verify/signer.d.ts
deleted file mode 100644
index 7241b90f6ac5c8..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/ca/verify/signer.d.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import * as sigstore from '../../types/sigstore';
-import { x509Certificate } from '../../x509/cert';
-export declare function verifySignerIdentity(signingCert: x509Certificate, identities: sigstore.CertificateIdentities): void;
diff --git a/deps/npm/node_modules/sigstore/dist/ca/verify/signer.js b/deps/npm/node_modules/sigstore/dist/ca/verify/signer.js
index 51d722d7631ee0..6f47651b944c94 100644
--- a/deps/npm/node_modules/sigstore/dist/ca/verify/signer.js
+++ b/deps/npm/node_modules/sigstore/dist/ca/verify/signer.js
@@ -54,7 +54,10 @@ function verifySignerIdentity(signingCert, identities) {
     // specified identities
     const signerVerified = identities.identities.some((identity) => verifyIdentity(signingCert, identity));
     if (!signerVerified) {
-        throw new error_1.PolicyError('Certificate issued to untrusted signer');
+        throw new error_1.PolicyError({
+            code: 'UNTRUSTED_SIGNER_ERROR',
+            message: 'Certificate issued to untrusted signer',
+        });
     }
 }
 exports.verifySignerIdentity = verifySignerIdentity;
diff --git a/deps/npm/node_modules/sigstore/dist/cli/index.d.ts b/deps/npm/node_modules/sigstore/dist/cli/index.d.ts
deleted file mode 100644
index 395f0a5a69d304..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/cli/index.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-export declare function processArgv(): Promise;
diff --git a/deps/npm/node_modules/sigstore/dist/cli/index.js b/deps/npm/node_modules/sigstore/dist/cli/index.js
deleted file mode 100644
index 6015cd9df74eac..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/cli/index.js
+++ /dev/null
@@ -1,125 +0,0 @@
-"use strict";
-var __importDefault = (this && this.__importDefault) || function (mod) {
-    return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.processArgv = void 0;
-/*
-Copyright 2022 The Sigstore Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-const fs_1 = __importDefault(require("fs"));
-const index_1 = require("../index");
-const INTOTO_PAYLOAD_TYPE = 'application/vnd.in-toto+json';
-async function cli(args) {
-    switch (args[0]) {
-        case 'sign':
-            await sign(args[1]);
-            break;
-        case 'attest':
-            await attest(args[1], args[2]);
-            break;
-        case 'verify':
-            await verify(args[1], args[2]);
-            break;
-        case 'version':
-        case '-version':
-        case '--version':
-        case '-v':
-            // eslint-disable-next-line @typescript-eslint/no-var-requires
-            console.log(require('../../package.json').version);
-            break;
-        case 'help':
-        case '--help':
-        case '-h':
-        case '-?':
-            printUsage();
-            break;
-        default:
-            throw 'Unknown command';
-    }
-}
-function printUsage() {
-    console.log(`sigstore  
-
-  Usage:
-
-  sigstore sign         sign an artifact
-  sigstore attest       sign an artifact using dsse (Dead Simple Signing Envelope)
-  sigstore verify       verify an artifact
-  sigstore version      print version information
-  sigstore help         print help information
-  `);
-}
-function printRekorEntry(bundle, options) {
-    let url;
-    if (options.rekorURL === index_1.sigstore.DEFAULT_REKOR_URL) {
-        url = `https://search.sigstore.dev`;
-    }
-    else {
-        url = `${options.rekorURL}/api/v1/log/entries`;
-    }
-    const logIndex = bundle.verificationMaterial?.tlogEntries[0].logIndex;
-    console.error(`Created entry at index ${logIndex}, available at`);
-    console.error(`${url}?logIndex=${logIndex}`);
-}
-// TODO: Allow customing these options
-const signOptions = {
-    oidcClientID: 'sigstore',
-    oidcIssuer: 'https://oauth2.sigstore.dev/auth',
-    oidcRedirectURL: process.env.OIDC_REDIRECT_URL,
-    rekorURL: index_1.sigstore.DEFAULT_REKOR_URL,
-};
-async function sign(artifactPath) {
-    const buffer = fs_1.default.readFileSync(artifactPath);
-    const bundle = await index_1.sigstore.sign(buffer, signOptions);
-    printRekorEntry(bundle, signOptions);
-    console.log(JSON.stringify(bundle));
-}
-async function attest(artifactPath, payloadType = INTOTO_PAYLOAD_TYPE) {
-    const buffer = fs_1.default.readFileSync(artifactPath);
-    const bundle = await index_1.sigstore.attest(buffer, payloadType, signOptions);
-    printRekorEntry(bundle, signOptions);
-    console.log(JSON.stringify(bundle));
-}
-async function verify(bundlePath, artifactPath) {
-    let payload = undefined;
-    if (artifactPath) {
-        payload = fs_1.default.readFileSync(artifactPath);
-    }
-    const bundleFile = fs_1.default.readFileSync(bundlePath);
-    const bundle = JSON.parse(bundleFile.toString('utf-8'));
-    try {
-        await index_1.sigstore.verify(bundle, payload, {});
-        console.error('Verified OK');
-    }
-    catch (e) {
-        console.error('Verification failed');
-        if (e instanceof Error) {
-            console.error('Error: ' + e.message);
-        }
-        process.exit(1);
-    }
-}
-async function processArgv() {
-    try {
-        await cli(process.argv.slice(2));
-        process.exit(0);
-    }
-    catch (e) {
-        console.error(e);
-        process.exit(1);
-    }
-}
-exports.processArgv = processArgv;
diff --git a/deps/npm/node_modules/sigstore/dist/config.d.ts b/deps/npm/node_modules/sigstore/dist/config.d.ts
deleted file mode 100644
index 89f42038099530..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/config.d.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-import { CA } from './ca';
-import { Provider } from './identity';
-import { TLog } from './tlog';
-import { TSA } from './tsa';
-import * as sigstore from './types/sigstore';
-import type { FetchOptions, Retry } from './types/fetch';
-import type { KeySelector } from './verify';
-interface CAOptions {
-    fulcioURL?: string;
-}
-interface TLogOptions {
-    rekorURL?: string;
-}
-interface TSAOptions {
-    tsaServerURL?: string;
-}
-export interface IdentityProviderOptions {
-    identityToken?: string;
-    oidcIssuer?: string;
-    oidcClientID?: string;
-    oidcClientSecret?: string;
-    oidcRedirectURL?: string;
-}
-export type TUFOptions = {
-    tufMirrorURL?: string;
-    tufRootPath?: string;
-    tufCachePath?: string;
-} & FetchOptions;
-export type SignOptions = {
-    identityProvider?: Provider;
-    tlogUpload?: boolean;
-} & CAOptions & TLogOptions & TSAOptions & FetchOptions & IdentityProviderOptions;
-export type VerifyOptions = {
-    ctLogThreshold?: number;
-    tlogThreshold?: number;
-    certificateIssuer?: string;
-    certificateIdentityEmail?: string;
-    certificateIdentityURI?: string;
-    certificateOIDs?: Record;
-    keySelector?: KeySelector;
-} & TLogOptions & TUFOptions;
-export type CreateVerifierOptions = {
-    keySelector?: KeySelector;
-} & TUFOptions;
-export declare const DEFAULT_FULCIO_URL = "https://fulcio.sigstore.dev";
-export declare const DEFAULT_REKOR_URL = "https://rekor.sigstore.dev";
-export declare const DEFAULT_RETRY: Retry;
-export declare const DEFAULT_TIMEOUT = 5000;
-export declare function createCAClient(options: CAOptions & FetchOptions): CA;
-export declare function createTLogClient(options: TLogOptions & FetchOptions): TLog;
-export declare function createTSAClient(options: TSAOptions & FetchOptions): TSA | undefined;
-export declare function artifactVerificationOptions(options: VerifyOptions): sigstore.RequiredArtifactVerificationOptions;
-export declare function identityProviders(options: IdentityProviderOptions): Provider[];
-export {};
diff --git a/deps/npm/node_modules/sigstore/dist/config.js b/deps/npm/node_modules/sigstore/dist/config.js
index 1a22c5fef313b7..43c236f0eebd07 100644
--- a/deps/npm/node_modules/sigstore/dist/config.js
+++ b/deps/npm/node_modules/sigstore/dist/config.js
@@ -22,11 +22,8 @@ var __importStar = (this && this.__importStar) || function (mod) {
     __setModuleDefault(result, mod);
     return result;
 };
-var __importDefault = (this && this.__importDefault) || function (mod) {
-    return (mod && mod.__esModule) ? mod : { "default": mod };
-};
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.identityProviders = exports.artifactVerificationOptions = exports.createTSAClient = exports.createTLogClient = exports.createCAClient = exports.DEFAULT_TIMEOUT = exports.DEFAULT_RETRY = exports.DEFAULT_REKOR_URL = exports.DEFAULT_FULCIO_URL = void 0;
+exports.artifactVerificationOptions = exports.createBundleBuilder = exports.DEFAULT_TIMEOUT = exports.DEFAULT_RETRY = void 0;
 /*
 Copyright 2023 The Sigstore Authors.
 
@@ -42,41 +39,72 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */
-const ca_1 = require("./ca");
-const identity_1 = __importDefault(require("./identity"));
-const tlog_1 = require("./tlog");
-const tsa_1 = require("./tsa");
+const sign_1 = require("@sigstore/sign");
 const sigstore = __importStar(require("./types/sigstore"));
-exports.DEFAULT_FULCIO_URL = 'https://fulcio.sigstore.dev';
-exports.DEFAULT_REKOR_URL = 'https://rekor.sigstore.dev';
 exports.DEFAULT_RETRY = { retries: 2 };
 exports.DEFAULT_TIMEOUT = 5000;
-function createCAClient(options) {
-    return new ca_1.CAClient({
-        fulcioBaseURL: options.fulcioURL || exports.DEFAULT_FULCIO_URL,
-        retry: options.retry ?? exports.DEFAULT_RETRY,
-        timeout: options.timeout ?? exports.DEFAULT_TIMEOUT,
-    });
+function createBundleBuilder(bundleType, options) {
+    const bundlerOptions = {
+        signer: initSigner(options),
+        witnesses: initWitnesses(options),
+    };
+    switch (bundleType) {
+        case 'messageSignature':
+            return new sign_1.MessageSignatureBundleBuilder(bundlerOptions);
+        case 'dsseEnvelope':
+            return new sign_1.DSSEBundleBuilder(bundlerOptions);
+    }
 }
-exports.createCAClient = createCAClient;
-function createTLogClient(options) {
-    return new tlog_1.TLogClient({
-        rekorBaseURL: options.rekorURL || exports.DEFAULT_REKOR_URL,
+exports.createBundleBuilder = createBundleBuilder;
+// Instantiate the FulcioSigner based on the supplied options.
+function initSigner(options) {
+    return new sign_1.FulcioSigner({
+        fulcioBaseURL: options.fulcioURL,
+        identityProvider: options.identityProvider || initIdentityProvider(options),
         retry: options.retry ?? exports.DEFAULT_RETRY,
         timeout: options.timeout ?? exports.DEFAULT_TIMEOUT,
     });
 }
-exports.createTLogClient = createTLogClient;
-function createTSAClient(options) {
-    return options.tsaServerURL
-        ? new tsa_1.TSAClient({
+// Instantiate an identity provider based on the supplied options. If an
+// explicit identity token is provided, use that. Otherwise, use the CI
+// context provider.
+function initIdentityProvider(options) {
+    const token = options.identityToken;
+    if (token) {
+        return { getToken: () => Promise.resolve(token) };
+    }
+    else {
+        return new sign_1.CIContextProvider('sigstore');
+    }
+}
+// Instantiate a collection of witnesses based on the supplied options.
+function initWitnesses(options) {
+    const witnesses = [];
+    if (isRekorEnabled(options)) {
+        witnesses.push(new sign_1.RekorWitness({
+            rekorBaseURL: options.rekorURL,
+            fetchOnConflict: false,
+            retry: options.retry ?? exports.DEFAULT_RETRY,
+            timeout: options.timeout ?? exports.DEFAULT_TIMEOUT,
+        }));
+    }
+    if (isTSAEnabled(options)) {
+        witnesses.push(new sign_1.TSAWitness({
             tsaBaseURL: options.tsaServerURL,
             retry: options.retry ?? exports.DEFAULT_RETRY,
             timeout: options.timeout ?? exports.DEFAULT_TIMEOUT,
-        })
-        : undefined;
+        }));
+    }
+    return witnesses;
+}
+// Type assertion to ensure that Rekor is enabled
+function isRekorEnabled(options) {
+    return options.tlogUpload !== false;
+}
+// Type assertion to ensure that TSA is enabled
+function isTSAEnabled(options) {
+    return options.tsaServerURL !== undefined;
 }
-exports.createTSAClient = createTSAClient;
 // Assembles the AtifactVerificationOptions from the supplied VerifyOptions.
 function artifactVerificationOptions(options) {
     // The trusted signers are only used if the options contain a certificate
@@ -102,7 +130,7 @@ function artifactVerificationOptions(options) {
                 },
             };
         }
-        const oids = Object.entries(options.certificateOIDs || {}).map(([oid, value]) => ({
+        const oids = Object.entries(options.certificateOIDs || /* istanbul ignore next */ {}).map(([oid, value]) => ({
             oid: { id: oid.split('.').map((s) => parseInt(s, 10)) },
             value: Buffer.from(value),
         }));
@@ -122,41 +150,16 @@ function artifactVerificationOptions(options) {
     // Construct the artifact verification options w/ defaults
     return {
         ctlogOptions: {
-            disable: false,
-            threshold: options.ctLogThreshold || 1,
+            disable: options.ctLogThreshold === 0,
+            threshold: options.ctLogThreshold ?? 1,
             detachedSct: false,
         },
         tlogOptions: {
-            disable: false,
-            threshold: options.tlogThreshold || 1,
+            disable: options.tlogThreshold === 0,
+            threshold: options.tlogThreshold ?? 1,
             performOnlineVerification: false,
         },
         signers,
     };
 }
 exports.artifactVerificationOptions = artifactVerificationOptions;
-// Translates the IdenityProviderOptions into a list of Providers which
-// should be queried to retrieve an identity token.
-function identityProviders(options) {
-    const idps = [];
-    const token = options.identityToken;
-    // If an explicit identity token is provided, use that. Setup a dummy
-    // provider that just returns the token. Otherwise, setup the CI context
-    // provider and (optionally) the OAuth provider.
-    if (token) {
-        idps.push({ getToken: () => Promise.resolve(token) });
-    }
-    else {
-        idps.push(identity_1.default.ciContextProvider());
-        if (options.oidcIssuer && options.oidcClientID) {
-            idps.push(identity_1.default.oauthProvider({
-                issuer: options.oidcIssuer,
-                clientID: options.oidcClientID,
-                clientSecret: options.oidcClientSecret,
-                redirectURL: options.oidcRedirectURL,
-            }));
-        }
-    }
-    return idps;
-}
-exports.identityProviders = identityProviders;
diff --git a/deps/npm/node_modules/sigstore/dist/error.d.ts b/deps/npm/node_modules/sigstore/dist/error.d.ts
deleted file mode 100644
index c03bbc31697745..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/error.d.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-declare class BaseError extends Error {
-    cause: any | undefined;
-    constructor(message: string, cause?: any);
-}
-export declare class VerificationError extends BaseError {
-}
-export declare class ValidationError extends BaseError {
-}
-export declare class PolicyError extends BaseError {
-}
-type InternalErrorCode = 'TLOG_FETCH_ENTRY_ERROR' | 'TLOG_CREATE_ENTRY_ERROR' | 'CA_CREATE_SIGNING_CERTIFICATE_ERROR' | 'TSA_CREATE_TIMESTAMP_ERROR' | 'TUF_FIND_TARGET_ERROR' | 'TUF_REFRESH_METADATA_ERROR' | 'TUF_DOWNLOAD_TARGET_ERROR' | 'TUF_READ_TARGET_ERROR';
-export declare class InternalError extends BaseError {
-    code: InternalErrorCode;
-    constructor({ code, message, cause, }: {
-        code: InternalErrorCode;
-        message: string;
-        cause?: any;
-    });
-}
-export {};
diff --git a/deps/npm/node_modules/sigstore/dist/error.js b/deps/npm/node_modules/sigstore/dist/error.js
index cee15dff90b614..b0a7dbc83f7105 100644
--- a/deps/npm/node_modules/sigstore/dist/error.js
+++ b/deps/npm/node_modules/sigstore/dist/error.js
@@ -1,6 +1,4 @@
 "use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.InternalError = exports.PolicyError = exports.ValidationError = exports.VerificationError = void 0;
 /*
 Copyright 2023 The Sigstore Authors.
 
@@ -16,27 +14,22 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */
-/* eslint-disable @typescript-eslint/no-explicit-any */
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.PolicyError = exports.VerificationError = void 0;
 class BaseError extends Error {
-    constructor(message, cause) {
+    constructor({ code, message, cause, }) {
         super(message);
         this.name = this.constructor.name;
+        this.code = code;
         this.cause = cause;
     }
 }
 class VerificationError extends BaseError {
+    constructor(message) {
+        super({ code: 'VERIFICATION_ERROR', message });
+    }
 }
 exports.VerificationError = VerificationError;
-class ValidationError extends BaseError {
-}
-exports.ValidationError = ValidationError;
 class PolicyError extends BaseError {
 }
 exports.PolicyError = PolicyError;
-class InternalError extends BaseError {
-    constructor({ code, message, cause, }) {
-        super(message, cause);
-        this.code = code;
-    }
-}
-exports.InternalError = InternalError;
diff --git a/deps/npm/node_modules/sigstore/dist/external/error.d.ts b/deps/npm/node_modules/sigstore/dist/external/error.d.ts
deleted file mode 100644
index 87a4bc5451a3de..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/external/error.d.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import fetch from 'make-fetch-happen';
-type Response = Awaited>;
-export declare class HTTPError extends Error {
-    response: Response;
-    statusCode: number;
-    location?: string;
-    constructor(response: Response);
-}
-export declare const checkStatus: (response: Response) => Response;
-export {};
diff --git a/deps/npm/node_modules/sigstore/dist/external/error.js b/deps/npm/node_modules/sigstore/dist/external/error.js
deleted file mode 100644
index d1e1c3df8a8787..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/external/error.js
+++ /dev/null
@@ -1,21 +0,0 @@
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.checkStatus = exports.HTTPError = void 0;
-class HTTPError extends Error {
-    constructor(response) {
-        super(`HTTP Error: ${response.status} ${response.statusText}`);
-        this.response = response;
-        this.statusCode = response.status;
-        this.location = response.headers?.get('Location') || undefined;
-    }
-}
-exports.HTTPError = HTTPError;
-const checkStatus = (response) => {
-    if (response.ok) {
-        return response;
-    }
-    else {
-        throw new HTTPError(response);
-    }
-};
-exports.checkStatus = checkStatus;
diff --git a/deps/npm/node_modules/sigstore/dist/external/fulcio.d.ts b/deps/npm/node_modules/sigstore/dist/external/fulcio.d.ts
deleted file mode 100644
index 64b0fc5e347982..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/external/fulcio.d.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import type { FetchOptions } from '../types/fetch';
-export type FulcioOptions = {
-    baseURL: string;
-} & FetchOptions;
-export interface SigningCertificateRequest {
-    credentials: {
-        oidcIdentityToken: string;
-    };
-    publicKeyRequest: {
-        publicKey: {
-            algorithm: string;
-            content: string;
-        };
-        proofOfPossession: string;
-    };
-}
-export interface SigningCertificateResponse {
-    signedCertificateEmbeddedSct?: {
-        chain: {
-            certificates: string[];
-        };
-    };
-    signedCertificateDetachedSct?: {
-        chain: {
-            certificates: string[];
-        };
-        signedCertificateTimestamp: string;
-    };
-}
-/**
- * Fulcio API client.
- */
-export declare class Fulcio {
-    private fetch;
-    private baseUrl;
-    constructor(options: FulcioOptions);
-    createSigningCertificate(request: SigningCertificateRequest): Promise;
-}
diff --git a/deps/npm/node_modules/sigstore/dist/external/index.d.ts b/deps/npm/node_modules/sigstore/dist/external/index.d.ts
deleted file mode 100644
index ef28eca4a951dd..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/external/index.d.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export { HTTPError } from './error';
-export { Fulcio } from './fulcio';
-export { Rekor } from './rekor';
-export { TimestampAuthority } from './tsa';
diff --git a/deps/npm/node_modules/sigstore/dist/external/index.js b/deps/npm/node_modules/sigstore/dist/external/index.js
deleted file mode 100644
index f40816e9b7ca40..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/external/index.js
+++ /dev/null
@@ -1,26 +0,0 @@
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.TimestampAuthority = exports.Rekor = exports.Fulcio = exports.HTTPError = void 0;
-/*
-Copyright 2022 The Sigstore Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-var error_1 = require("./error");
-Object.defineProperty(exports, "HTTPError", { enumerable: true, get: function () { return error_1.HTTPError; } });
-var fulcio_1 = require("./fulcio");
-Object.defineProperty(exports, "Fulcio", { enumerable: true, get: function () { return fulcio_1.Fulcio; } });
-var rekor_1 = require("./rekor");
-Object.defineProperty(exports, "Rekor", { enumerable: true, get: function () { return rekor_1.Rekor; } });
-var tsa_1 = require("./tsa");
-Object.defineProperty(exports, "TimestampAuthority", { enumerable: true, get: function () { return tsa_1.TimestampAuthority; } });
diff --git a/deps/npm/node_modules/sigstore/dist/external/rekor.d.ts b/deps/npm/node_modules/sigstore/dist/external/rekor.d.ts
deleted file mode 100644
index 6729ad3e2aacf6..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/external/rekor.d.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import type { LogEntry, ProposedDSSEEntry, ProposedEntry, ProposedHashedRekordEntry, ProposedIntotoEntry, InclusionProof as RekorInclusionProof, SearchIndex, SearchLogQuery } from '@sigstore/rekor-types';
-import type { FetchOptions } from '../types/fetch';
-export type { ProposedDSSEEntry, ProposedEntry, ProposedHashedRekordEntry, ProposedIntotoEntry, RekorInclusionProof, SearchIndex, SearchLogQuery, };
-export type Entry = {
-    uuid: string;
-} & LogEntry['x'];
-export type RekorOptions = {
-    baseURL: string;
-} & FetchOptions;
-/**
- * Rekor API client.
- */
-export declare class Rekor {
-    private fetch;
-    private baseUrl;
-    constructor(options: RekorOptions);
-    /**
-     * Create a new entry in the Rekor log.
-     * @param propsedEntry {ProposedEntry} Data to create a new entry
-     * @returns {Promise} The created entry
-     */
-    createEntry(propsedEntry: ProposedEntry): Promise;
-    /**
-     * Get an entry from the Rekor log.
-     * @param uuid {string} The UUID of the entry to retrieve
-     * @returns {Promise} The retrieved entry
-     */
-    getEntry(uuid: string): Promise;
-    /**
-     * Search the Rekor log index for entries matching the given query.
-     * @param opts {SearchIndex} Options to search the Rekor log
-     * @returns {Promise} UUIDs of matching entries
-     */
-    searchIndex(opts: SearchIndex): Promise;
-    /**
-     * Search the Rekor logs for matching the given query.
-     * @param opts {SearchLogQuery} Query to search the Rekor log
-     * @returns {Promise} List of matching entries
-     */
-    searchLog(opts: SearchLogQuery): Promise;
-}
diff --git a/deps/npm/node_modules/sigstore/dist/external/tsa.d.ts b/deps/npm/node_modules/sigstore/dist/external/tsa.d.ts
deleted file mode 100644
index 9b5f31151a83d8..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/external/tsa.d.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-/// 
-import type { FetchOptions } from '../types/fetch';
-export interface TimestampRequest {
-    artifactHash: string;
-    hashAlgorithm: string;
-    certificates?: boolean;
-    nonce?: number;
-    tsaPolicyOID?: string;
-}
-export type TimestampAuthorityOptions = {
-    baseURL: string;
-} & FetchOptions;
-export declare class TimestampAuthority {
-    private fetch;
-    private baseUrl;
-    constructor(options: TimestampAuthorityOptions);
-    createTimestamp(request: TimestampRequest): Promise;
-}
diff --git a/deps/npm/node_modules/sigstore/dist/identity/ci.d.ts b/deps/npm/node_modules/sigstore/dist/identity/ci.d.ts
deleted file mode 100644
index 428606f26524bb..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/identity/ci.d.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { Provider } from './provider';
-/**
- * CIContextProvider is a composite identity provider which will iterate
- * over all of the CI-specific providers and return the token from the first
- * one that resolves.
- */
-export declare class CIContextProvider implements Provider {
-    private audience;
-    constructor(audience: string);
-    getToken(): Promise;
-}
diff --git a/deps/npm/node_modules/sigstore/dist/identity/index.d.ts b/deps/npm/node_modules/sigstore/dist/identity/index.d.ts
deleted file mode 100644
index 3eb0b444d120ff..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/identity/index.d.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { Provider } from './provider';
-/**
- * oauthProvider returns a new Provider instance which attempts to retrieve
- * an identity token from the configured OAuth2 issuer.
- *
- * @param issuer Base URL of the issuer
- * @param clientID Client ID for the issuer
- * @param clientSecret Client secret for the issuer (optional)
- * @returns {Provider}
- */
-declare function oauthProvider(options: {
-    issuer: string;
-    clientID: string;
-    clientSecret?: string;
-    redirectURL?: string;
-}): Provider;
-/**
- * ciContextProvider returns a new Provider instance which attempts to retrieve
- * an identity token from the CI context.
- *
- * @param audience audience claim for the generated token
- * @returns {Provider}
- */
-declare function ciContextProvider(audience?: string): Provider;
-declare const _default: {
-    ciContextProvider: typeof ciContextProvider;
-    oauthProvider: typeof oauthProvider;
-};
-export default _default;
-export { Provider } from './provider';
diff --git a/deps/npm/node_modules/sigstore/dist/identity/index.js b/deps/npm/node_modules/sigstore/dist/identity/index.js
deleted file mode 100644
index 351d607106700f..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/identity/index.js
+++ /dev/null
@@ -1,51 +0,0 @@
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-/*
-Copyright 2022 The Sigstore Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-const ci_1 = require("./ci");
-const issuer_1 = require("./issuer");
-const oauth_1 = require("./oauth");
-/**
- * oauthProvider returns a new Provider instance which attempts to retrieve
- * an identity token from the configured OAuth2 issuer.
- *
- * @param issuer Base URL of the issuer
- * @param clientID Client ID for the issuer
- * @param clientSecret Client secret for the issuer (optional)
- * @returns {Provider}
- */
-function oauthProvider(options) {
-    return new oauth_1.OAuthProvider({
-        issuer: new issuer_1.Issuer(options.issuer),
-        clientID: options.clientID,
-        clientSecret: options.clientSecret,
-        redirectURL: options.redirectURL,
-    });
-}
-/**
- * ciContextProvider returns a new Provider instance which attempts to retrieve
- * an identity token from the CI context.
- *
- * @param audience audience claim for the generated token
- * @returns {Provider}
- */
-function ciContextProvider(audience = 'sigstore') {
-    return new ci_1.CIContextProvider(audience);
-}
-exports.default = {
-    ciContextProvider,
-    oauthProvider,
-};
diff --git a/deps/npm/node_modules/sigstore/dist/identity/issuer.d.ts b/deps/npm/node_modules/sigstore/dist/identity/issuer.d.ts
deleted file mode 100644
index 37ad713f4d89a7..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/identity/issuer.d.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-/**
- * The Issuer reperesents a single OAuth2 provider.
- *
- * The Issuer is configured with a provider's base OAuth2 endpoint which is
- * used to retrieve the associated configuration information.
- */
-export declare class Issuer {
-    private baseURL;
-    private fetch;
-    private config?;
-    constructor(baseURL: string);
-    authEndpoint(): Promise;
-    tokenEndpoint(): Promise;
-    private loadOpenIDConfig;
-}
diff --git a/deps/npm/node_modules/sigstore/dist/identity/issuer.js b/deps/npm/node_modules/sigstore/dist/identity/issuer.js
deleted file mode 100644
index 2bf6c20f34932d..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/identity/issuer.js
+++ /dev/null
@@ -1,53 +0,0 @@
-"use strict";
-var __importDefault = (this && this.__importDefault) || function (mod) {
-    return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.Issuer = void 0;
-/*
-Copyright 2022 The Sigstore Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-const make_fetch_happen_1 = __importDefault(require("make-fetch-happen"));
-// Standard endpoint for retrieving OpenID configuration information
-const OPENID_CONFIG_PATH = '/.well-known/openid-configuration';
-/**
- * The Issuer reperesents a single OAuth2 provider.
- *
- * The Issuer is configured with a provider's base OAuth2 endpoint which is
- * used to retrieve the associated configuration information.
- */
-class Issuer {
-    constructor(baseURL) {
-        this.baseURL = baseURL;
-        this.fetch = make_fetch_happen_1.default.defaults({ retry: 2 });
-    }
-    async authEndpoint() {
-        if (!this.config) {
-            this.config = await this.loadOpenIDConfig();
-        }
-        return this.config.authorization_endpoint;
-    }
-    async tokenEndpoint() {
-        if (!this.config) {
-            this.config = await this.loadOpenIDConfig();
-        }
-        return this.config.token_endpoint;
-    }
-    async loadOpenIDConfig() {
-        const url = `${this.baseURL}${OPENID_CONFIG_PATH}`;
-        return this.fetch(url).then((res) => res.json());
-    }
-}
-exports.Issuer = Issuer;
diff --git a/deps/npm/node_modules/sigstore/dist/identity/oauth.d.ts b/deps/npm/node_modules/sigstore/dist/identity/oauth.d.ts
deleted file mode 100644
index 3c9fae9ac15387..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/identity/oauth.d.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { Issuer } from './issuer';
-import { Provider } from './provider';
-interface OAuthProviderOptions {
-    issuer: Issuer;
-    clientID: string;
-    clientSecret?: string;
-    redirectURL?: string;
-}
-export declare class OAuthProvider implements Provider {
-    private clientID;
-    private clientSecret;
-    private issuer;
-    private codeVerifier;
-    private state;
-    private redirectURI?;
-    constructor(options: OAuthProviderOptions);
-    getToken(): Promise;
-    private initiateAuthRequest;
-    private getIDToken;
-    private getBasicAuthHeaderValue;
-    private getAuthRequestURL;
-    private getAuthRequestParams;
-    private getCodeChallenge;
-    private openURL;
-}
-export {};
diff --git a/deps/npm/node_modules/sigstore/dist/identity/oauth.js b/deps/npm/node_modules/sigstore/dist/identity/oauth.js
deleted file mode 100644
index 7cb5a00cdb6942..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/identity/oauth.js
+++ /dev/null
@@ -1,197 +0,0 @@
-"use strict";
-var __importDefault = (this && this.__importDefault) || function (mod) {
-    return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.OAuthProvider = void 0;
-/*
-Copyright 2022 The Sigstore Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-const assert_1 = __importDefault(require("assert"));
-const child_process_1 = __importDefault(require("child_process"));
-const http_1 = __importDefault(require("http"));
-const make_fetch_happen_1 = __importDefault(require("make-fetch-happen"));
-const url_1 = require("url");
-const util_1 = require("../util");
-class OAuthProvider {
-    constructor(options) {
-        this.clientID = options.clientID;
-        this.clientSecret = options.clientSecret || '';
-        this.issuer = options.issuer;
-        this.redirectURI = options.redirectURL;
-        this.codeVerifier = generateRandomString(32);
-        this.state = generateRandomString(16);
-    }
-    async getToken() {
-        const authCode = await this.initiateAuthRequest();
-        return this.getIDToken(authCode);
-    }
-    // Initates the authorization request. This will start an HTTP server to
-    // receive the post-auth redirect and then open the user's default browser to
-    // the provider's authorization page.
-    async initiateAuthRequest() {
-        const server = http_1.default.createServer();
-        const sockets = new Set();
-        // Start server and wait till it is listening. If a redirect URL was
-        // provided, use that. Otherwise, use a random port and construct the
-        // redirect URL.
-        await new Promise((resolve) => {
-            if (this.redirectURI) {
-                const url = new url_1.URL(this.redirectURI);
-                server.listen(Number(url.port), url.hostname, resolve);
-            }
-            else {
-                server.listen(0, resolve);
-                // Get port the server is listening on and construct the server URL
-                const port = server.address().port;
-                this.redirectURI = `http://localhost:${port}`;
-            }
-        });
-        // Keep track of connections to the server so we can force a shutdown
-        server.on('connection', (socket) => {
-            sockets.add(socket);
-            socket.once('close', () => {
-                sockets.delete(socket);
-            });
-        });
-        const result = new Promise((resolve, reject) => {
-            // Set-up handler for post-auth redirect
-            server.on('request', (req, res) => {
-                if (!req.url) {
-                    reject('invalid server request');
-                    return;
-                }
-                res.writeHead(200);
-                res.end('Auth Successful');
-                // Parse incoming request URL
-                const query = new url_1.URL(req.url, this.redirectURI).searchParams;
-                // Check to see if the state matches
-                if (query.get('state') !== this.state) {
-                    reject('invalid state value');
-                    return;
-                }
-                const authCode = query.get('code');
-                // Force-close any open connections to the server so we can get a
-                // clean shutdown
-                for (const socket of sockets) {
-                    socket.destroy();
-                    sockets.delete(socket);
-                }
-                // Return auth code once we've shutdown server
-                server.close(() => {
-                    if (!authCode) {
-                        reject('authorization code not found');
-                    }
-                    else {
-                        resolve(authCode);
-                    }
-                });
-            });
-        });
-        try {
-            // Open browser to start authorization request
-            const authBaseURL = await this.issuer.authEndpoint();
-            const authURL = this.getAuthRequestURL(authBaseURL);
-            await this.openURL(authURL);
-        }
-        catch (err) {
-            // Prevent leaked server handler on error
-            server.close();
-            throw err;
-        }
-        return result;
-    }
-    // Uses the provided authorization code, to retrieve the ID token from the
-    // provider
-    async getIDToken(authCode) {
-        (0, assert_1.default)(this.redirectURI);
-        const tokenEndpointURL = await this.issuer.tokenEndpoint();
-        const params = new url_1.URLSearchParams();
-        params.append('grant_type', 'authorization_code');
-        params.append('code', authCode);
-        params.append('redirect_uri', this.redirectURI);
-        params.append('code_verifier', this.codeVerifier);
-        const response = await (0, make_fetch_happen_1.default)(tokenEndpointURL, {
-            method: 'POST',
-            headers: { Authorization: `Basic ${this.getBasicAuthHeaderValue()}` },
-            body: params,
-        }).then((r) => r.json());
-        return response.id_token;
-    }
-    // Construct the basic auth header value from the client ID and secret
-    getBasicAuthHeaderValue() {
-        return util_1.encoding.base64Encode(`${this.clientID}:${this.clientSecret}`);
-    }
-    // Generate starting URL for authorization request
-    getAuthRequestURL(baseURL) {
-        const params = this.getAuthRequestParams();
-        return `${baseURL}?${params.toString()}`;
-    }
-    // Collect parameters for authorization request
-    getAuthRequestParams() {
-        (0, assert_1.default)(this.redirectURI);
-        const codeChallenge = this.getCodeChallenge();
-        return new url_1.URLSearchParams({
-            response_type: 'code',
-            client_id: this.clientID,
-            client_secret: this.clientSecret,
-            scope: 'openid email',
-            redirect_uri: this.redirectURI,
-            code_challenge: codeChallenge,
-            code_challenge_method: 'S256',
-            state: this.state,
-            nonce: generateRandomString(16),
-        });
-    }
-    // Generate code challenge for authorization request
-    getCodeChallenge() {
-        return util_1.encoding.base64URLEscape(util_1.crypto.hash(this.codeVerifier).toString('base64'));
-    }
-    // Open the supplied URL in the user's default browser
-    async openURL(url) {
-        return new Promise((resolve, reject) => {
-            let open = null;
-            let command = `"${url}"`;
-            switch (process.platform) {
-                case 'darwin':
-                    open = 'open';
-                    break;
-                case 'linux' || 'freebsd' || 'netbsd' || 'openbsd':
-                    open = 'xdg-open';
-                    break;
-                case 'win32':
-                    open = 'start';
-                    command = `"" ${command}`;
-                    break;
-                default:
-                    return reject(`OAuth: unsupported platform: ${process.platform}`);
-            }
-            console.error(`Your browser will now be opened to: ${url}`);
-            child_process_1.default.exec(`${open} ${command}`, undefined, (err) => {
-                if (err) {
-                    reject(err);
-                }
-                else {
-                    resolve();
-                }
-            });
-        });
-    }
-}
-exports.OAuthProvider = OAuthProvider;
-// Generate random code verifier value
-function generateRandomString(len) {
-    return util_1.encoding.base64URLEscape(util_1.crypto.randomBytes(len).toString('base64'));
-}
diff --git a/deps/npm/node_modules/sigstore/dist/identity/provider.d.ts b/deps/npm/node_modules/sigstore/dist/identity/provider.d.ts
deleted file mode 100644
index 95ec03e9ffff6c..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/identity/provider.d.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export interface Provider {
-    getToken: () => Promise;
-}
diff --git a/deps/npm/node_modules/sigstore/dist/index.d.ts b/deps/npm/node_modules/sigstore/dist/index.d.ts
deleted file mode 100644
index dbac0640092b04..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/index.d.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export type { Provider as IdentityProvider } from './identity';
-export * as sigstore from './sigstore';
diff --git a/deps/npm/node_modules/sigstore/dist/index.js b/deps/npm/node_modules/sigstore/dist/index.js
index 126fce58e45bde..341c1fa504d1e8 100644
--- a/deps/npm/node_modules/sigstore/dist/index.js
+++ b/deps/npm/node_modules/sigstore/dist/index.js
@@ -1,27 +1,34 @@
 "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 (mod) {
-    if (mod && mod.__esModule) return mod;
-    var result = {};
-    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
-    __setModuleDefault(result, mod);
-    return result;
-};
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.sigstore = void 0;
-exports.sigstore = __importStar(require("./sigstore"));
+exports.verify = exports.sign = exports.createVerifier = exports.attest = exports.VerificationError = exports.PolicyError = exports.TUFError = exports.InternalError = exports.DEFAULT_REKOR_URL = exports.DEFAULT_FULCIO_URL = exports.ValidationError = void 0;
+/*
+Copyright 2022 The Sigstore Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+var bundle_1 = require("@sigstore/bundle");
+Object.defineProperty(exports, "ValidationError", { enumerable: true, get: function () { return bundle_1.ValidationError; } });
+var sign_1 = require("@sigstore/sign");
+Object.defineProperty(exports, "DEFAULT_FULCIO_URL", { enumerable: true, get: function () { return sign_1.DEFAULT_FULCIO_URL; } });
+Object.defineProperty(exports, "DEFAULT_REKOR_URL", { enumerable: true, get: function () { return sign_1.DEFAULT_REKOR_URL; } });
+Object.defineProperty(exports, "InternalError", { enumerable: true, get: function () { return sign_1.InternalError; } });
+var tuf_1 = require("@sigstore/tuf");
+Object.defineProperty(exports, "TUFError", { enumerable: true, get: function () { return tuf_1.TUFError; } });
+var error_1 = require("./error");
+Object.defineProperty(exports, "PolicyError", { enumerable: true, get: function () { return error_1.PolicyError; } });
+Object.defineProperty(exports, "VerificationError", { enumerable: true, get: function () { return error_1.VerificationError; } });
+var sigstore_1 = require("./sigstore");
+Object.defineProperty(exports, "attest", { enumerable: true, get: function () { return sigstore_1.attest; } });
+Object.defineProperty(exports, "createVerifier", { enumerable: true, get: function () { return sigstore_1.createVerifier; } });
+Object.defineProperty(exports, "sign", { enumerable: true, get: function () { return sigstore_1.sign; } });
+Object.defineProperty(exports, "verify", { enumerable: true, get: function () { return sigstore_1.verify; } });
diff --git a/deps/npm/node_modules/sigstore/dist/sign.d.ts b/deps/npm/node_modules/sigstore/dist/sign.d.ts
deleted file mode 100644
index 7d903c06e120a0..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/sign.d.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-/// 
-import { SignerFunc } from './types/signature';
-import * as sigstore from './types/sigstore';
-import type { CA } from './ca';
-import type { Provider } from './identity';
-import type { TLog } from './tlog';
-import type { TSA } from './tsa';
-export interface SignOptions {
-    ca: CA;
-    tlog: TLog;
-    tsa?: TSA;
-    identityProviders: Provider[];
-    tlogUpload?: boolean;
-    signer?: SignerFunc;
-}
-export declare class Signer {
-    private ca;
-    private tlog;
-    private tsa?;
-    private tlogUpload;
-    private signer;
-    private identityProviders;
-    constructor(options: SignOptions);
-    signBlob(payload: Buffer): Promise;
-    signAttestation(payload: Buffer, payloadType: string): Promise;
-    private signWithEphemeralKey;
-    private getIdentityToken;
-}
diff --git a/deps/npm/node_modules/sigstore/dist/sign.js b/deps/npm/node_modules/sigstore/dist/sign.js
deleted file mode 100644
index 96e6272750b493..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/sign.js
+++ /dev/null
@@ -1,120 +0,0 @@
-"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 (mod) {
-    if (mod && mod.__esModule) return mod;
-    var result = {};
-    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
-    __setModuleDefault(result, mod);
-    return result;
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.Signer = void 0;
-const sigstore = __importStar(require("./types/sigstore"));
-const util_1 = require("./util");
-class Signer {
-    constructor(options) {
-        this.identityProviders = [];
-        this.ca = options.ca;
-        this.tlog = options.tlog;
-        this.tsa = options.tsa;
-        this.identityProviders = options.identityProviders;
-        this.tlogUpload = options.tlogUpload ?? true;
-        this.signer = options.signer || this.signWithEphemeralKey.bind(this);
-    }
-    async signBlob(payload) {
-        // Get signature and verification material for payload
-        const sigMaterial = await this.signer(payload);
-        // Calculate artifact digest
-        const digest = util_1.crypto.hash(payload);
-        // Create a Rekor entry (if tlogUpload is enabled)
-        const entry = this.tlogUpload
-            ? await this.tlog.createMessageSignatureEntry(digest, sigMaterial)
-            : undefined;
-        return sigstore.toMessageSignatureBundle({
-            digest,
-            signature: sigMaterial,
-            tlogEntry: entry,
-            timestamp: this.tsa
-                ? await this.tsa.createTimestamp(sigMaterial.signature)
-                : undefined,
-        });
-    }
-    async signAttestation(payload, payloadType) {
-        // Pre-authentication encoding to be signed
-        const paeBuffer = util_1.dsse.preAuthEncoding(payloadType, payload);
-        // Get signature and verification material for pae
-        const sigMaterial = await this.signer(paeBuffer);
-        const envelope = {
-            payloadType,
-            payload: payload,
-            signatures: [
-                {
-                    keyid: sigMaterial.key?.id || '',
-                    sig: sigMaterial.signature,
-                },
-            ],
-        };
-        // Create a Rekor entry (if tlogUpload is enabled)
-        const entry = this.tlogUpload
-            ? await this.tlog.createDSSEEntry(envelope, sigMaterial)
-            : undefined;
-        return sigstore.toDSSEBundle({
-            envelope,
-            signature: sigMaterial,
-            tlogEntry: entry,
-            timestamp: this.tsa
-                ? await this.tsa.createTimestamp(sigMaterial.signature)
-                : undefined,
-        });
-    }
-    async signWithEphemeralKey(payload) {
-        // Create emphemeral key pair
-        const keypair = util_1.crypto.generateKeyPair();
-        // Retrieve identity token from one of the supplied identity providers
-        const identityToken = await this.getIdentityToken();
-        // Extract challenge claim from OIDC token
-        const subject = util_1.oidc.extractJWTSubject(identityToken);
-        // Construct challenge value by encrypting subject with private key
-        const challenge = util_1.crypto.signBlob(Buffer.from(subject), keypair.privateKey);
-        // Create signing certificate
-        const certificates = await this.ca.createSigningCertificate(identityToken, keypair.publicKey, challenge);
-        // Generate artifact signature
-        const signature = util_1.crypto.signBlob(payload, keypair.privateKey);
-        return {
-            signature,
-            certificates,
-            key: undefined,
-        };
-    }
-    async getIdentityToken() {
-        const aggErrs = [];
-        for (const provider of this.identityProviders) {
-            try {
-                const token = await provider.getToken();
-                if (token) {
-                    return token;
-                }
-            }
-            catch (err) {
-                aggErrs.push(err);
-            }
-        }
-        throw new Error(`Identity token providers failed: ${aggErrs}`);
-    }
-}
-exports.Signer = Signer;
diff --git a/deps/npm/node_modules/sigstore/dist/sigstore-utils.d.ts b/deps/npm/node_modules/sigstore/dist/sigstore-utils.d.ts
deleted file mode 100644
index 38f15dc7340d29..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/sigstore-utils.d.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-/// 
-import { SignOptions } from './config';
-import { SignerFunc } from './types/signature';
-import * as sigstore from './types/sigstore';
-export declare function createDSSEEnvelope(payload: Buffer, payloadType: string, options: {
-    signer: SignerFunc;
-}): Promise;
-export declare function createRekorEntry(dsseEnvelope: sigstore.SerializedEnvelope, publicKey: string, options?: SignOptions): Promise;
diff --git a/deps/npm/node_modules/sigstore/dist/sigstore-utils.js b/deps/npm/node_modules/sigstore/dist/sigstore-utils.js
deleted file mode 100644
index dc75692f40bf02..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/sigstore-utils.js
+++ /dev/null
@@ -1,80 +0,0 @@
-"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 (mod) {
-    if (mod && mod.__esModule) return mod;
-    var result = {};
-    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
-    __setModuleDefault(result, mod);
-    return result;
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.createRekorEntry = exports.createDSSEEnvelope = void 0;
-/*
-Copyright 2022 The Sigstore Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-const config_1 = require("./config");
-const signature_1 = require("./types/signature");
-const sigstore = __importStar(require("./types/sigstore"));
-const util_1 = require("./util");
-async function createDSSEEnvelope(payload, payloadType, options) {
-    // Pre-authentication encoding to be signed
-    const paeBuffer = util_1.dsse.preAuthEncoding(payloadType, payload);
-    // Get signature and verification material for pae
-    const sigMaterial = await options.signer(paeBuffer);
-    const envelope = {
-        payloadType,
-        payload,
-        signatures: [
-            {
-                keyid: sigMaterial.key?.id || '',
-                sig: sigMaterial.signature,
-            },
-        ],
-    };
-    return sigstore.Envelope.toJSON(envelope);
-}
-exports.createDSSEEnvelope = createDSSEEnvelope;
-// Accepts a signed DSSE envelope and a PEM-encoded public key to be added to the
-// transparency log. Returns a Sigstore bundle suitable for offline verification.
-async function createRekorEntry(dsseEnvelope, publicKey, options = {}) {
-    const envelope = sigstore.Envelope.fromJSON(dsseEnvelope);
-    const tlog = (0, config_1.createTLogClient)(options);
-    const sigMaterial = (0, signature_1.extractSignatureMaterial)(envelope, publicKey);
-    const entry = await tlog.createDSSEEntry(envelope, sigMaterial, {
-        fetchOnConflict: true,
-    });
-    const bundle = sigstore.toDSSEBundle({
-        envelope,
-        signature: sigMaterial,
-        tlogEntry: entry,
-    });
-    return sigstore.bundleToJSON(bundle);
-}
-exports.createRekorEntry = createRekorEntry;
diff --git a/deps/npm/node_modules/sigstore/dist/sigstore.d.ts b/deps/npm/node_modules/sigstore/dist/sigstore.d.ts
deleted file mode 100644
index 1da5e8ecc5fe5b..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/sigstore.d.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-/// 
-import * as tuf from '@sigstore/tuf';
-import * as config from './config';
-import * as sigstore from './types/sigstore';
-export declare function sign(payload: Buffer, options?: config.SignOptions): Promise;
-export declare function attest(payload: Buffer, payloadType: string, options?: config.SignOptions): Promise;
-export declare function verify(bundle: sigstore.SerializedBundle, payload?: Buffer, options?: config.VerifyOptions): Promise;
-export interface BundleVerifier {
-    verify(bundle: sigstore.SerializedBundle): void;
-}
-export declare function createVerifier(options: config.CreateVerifierOptions): Promise;
-declare const tufUtils: {
-    client: (options?: config.TUFOptions) => Promise;
-    getTarget: (path: string, options?: config.TUFOptions) => Promise;
-};
-export type { TUF } from '@sigstore/tuf';
-export type { SignOptions, VerifyOptions } from './config';
-export { InternalError, PolicyError, ValidationError, VerificationError, } from './error';
-export * as utils from './sigstore-utils';
-export type { SerializedBundle as Bundle, SerializedEnvelope as Envelope, } from './types/sigstore';
-export { tufUtils as tuf };
-export declare const DEFAULT_FULCIO_URL = "https://fulcio.sigstore.dev";
-export declare const DEFAULT_REKOR_URL = "https://rekor.sigstore.dev";
diff --git a/deps/npm/node_modules/sigstore/dist/sigstore.js b/deps/npm/node_modules/sigstore/dist/sigstore.js
index dca476dd292030..24fff291ab2b7e 100644
--- a/deps/npm/node_modules/sigstore/dist/sigstore.js
+++ b/deps/npm/node_modules/sigstore/dist/sigstore.js
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
     return result;
 };
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.DEFAULT_REKOR_URL = exports.DEFAULT_FULCIO_URL = exports.tuf = exports.utils = exports.VerificationError = exports.ValidationError = exports.PolicyError = exports.InternalError = exports.createVerifier = exports.verify = exports.attest = exports.sign = void 0;
+exports.createVerifier = exports.verify = exports.attest = exports.sign = void 0;
 /*
 Copyright 2023 The Sigstore Authors.
 
@@ -39,60 +39,40 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */
+const bundle_1 = require("@sigstore/bundle");
 const tuf = __importStar(require("@sigstore/tuf"));
 const config = __importStar(require("./config"));
-const sign_1 = require("./sign");
-const sigstore = __importStar(require("./types/sigstore"));
 const verify_1 = require("./verify");
-async function sign(payload, options = {}) {
-    const ca = config.createCAClient(options);
-    const tlog = config.createTLogClient(options);
-    const idps = config.identityProviders(options);
-    const signer = new sign_1.Signer({
-        ca,
-        tlog,
-        identityProviders: options.identityProvider
-            ? [options.identityProvider]
-            : idps,
-        tlogUpload: options.tlogUpload,
-    });
-    const bundle = await signer.signBlob(payload);
-    return sigstore.bundleToJSON(bundle);
+async function sign(payload,
+/* istanbul ignore next */
+options = {}) {
+    const bundler = config.createBundleBuilder('messageSignature', options);
+    const bundle = await bundler.create({ data: payload });
+    return (0, bundle_1.bundleToJSON)(bundle);
 }
 exports.sign = sign;
-async function attest(payload, payloadType, options = {}) {
-    const ca = config.createCAClient(options);
-    const tlog = config.createTLogClient(options);
-    const tsa = config.createTSAClient(options);
-    const idps = config.identityProviders(options);
-    const signer = new sign_1.Signer({
-        ca,
-        tlog,
-        tsa,
-        identityProviders: options.identityProvider
-            ? [options.identityProvider]
-            : idps,
-        tlogUpload: options.tlogUpload,
-    });
-    const bundle = await signer.signAttestation(payload, payloadType);
-    return sigstore.bundleToJSON(bundle);
+async function attest(payload, payloadType,
+/* istanbul ignore next */
+options = {}) {
+    const bundler = config.createBundleBuilder('dsseEnvelope', options);
+    const bundle = await bundler.create({ data: payload, type: payloadType });
+    return (0, bundle_1.bundleToJSON)(bundle);
 }
 exports.attest = attest;
-async function verify(bundle, payload, options = {}) {
-    const trustedRoot = await tuf.getTrustedRoot({
-        mirrorURL: options.tufMirrorURL,
-        rootPath: options.tufRootPath,
-        cachePath: options.tufCachePath,
-        retry: options.retry ?? config.DEFAULT_RETRY,
-        timeout: options.timeout ?? config.DEFAULT_TIMEOUT,
-    });
-    const verifier = new verify_1.Verifier(trustedRoot, options.keySelector);
-    const deserializedBundle = sigstore.bundleFromJSON(bundle);
-    const opts = config.artifactVerificationOptions(options);
-    return verifier.verify(deserializedBundle, opts, payload);
+async function verify(bundle, dataOrOptions, options) {
+    let data;
+    if (Buffer.isBuffer(dataOrOptions)) {
+        data = dataOrOptions;
+    }
+    else {
+        options = dataOrOptions;
+    }
+    return createVerifier(options).then((verifier) => verifier.verify(bundle, data));
 }
 exports.verify = verify;
-async function createVerifier(options) {
+async function createVerifier(
+/* istanbul ignore next */
+options = {}) {
     const trustedRoot = await tuf.getTrustedRoot({
         mirrorURL: options.tufMirrorURL,
         rootPath: options.tufRootPath,
@@ -103,44 +83,10 @@ async function createVerifier(options) {
     const verifier = new verify_1.Verifier(trustedRoot, options.keySelector);
     const verifyOpts = config.artifactVerificationOptions(options);
     return {
-        verify: (bundle) => {
-            const deserializedBundle = sigstore.bundleFromJSON(bundle);
-            return verifier.verify(deserializedBundle, verifyOpts);
+        verify: (bundle, payload) => {
+            const deserializedBundle = (0, bundle_1.bundleFromJSON)(bundle);
+            return verifier.verify(deserializedBundle, verifyOpts, payload);
         },
     };
 }
 exports.createVerifier = createVerifier;
-const tufUtils = {
-    client: (options = {}) => {
-        return tuf.initTUF({
-            mirrorURL: options.tufMirrorURL,
-            rootPath: options.tufRootPath,
-            cachePath: options.tufCachePath,
-            retry: options.retry,
-            timeout: options.timeout,
-        });
-    },
-    /*
-     * @deprecated Use tufUtils.client instead.
-     */
-    getTarget: (path, options = {}) => {
-        return tuf
-            .initTUF({
-            mirrorURL: options.tufMirrorURL,
-            rootPath: options.tufRootPath,
-            cachePath: options.tufCachePath,
-            retry: options.retry,
-            timeout: options.timeout,
-        })
-            .then((t) => t.getTarget(path));
-    },
-};
-exports.tuf = tufUtils;
-var error_1 = require("./error");
-Object.defineProperty(exports, "InternalError", { enumerable: true, get: function () { return error_1.InternalError; } });
-Object.defineProperty(exports, "PolicyError", { enumerable: true, get: function () { return error_1.PolicyError; } });
-Object.defineProperty(exports, "ValidationError", { enumerable: true, get: function () { return error_1.ValidationError; } });
-Object.defineProperty(exports, "VerificationError", { enumerable: true, get: function () { return error_1.VerificationError; } });
-exports.utils = __importStar(require("./sigstore-utils"));
-exports.DEFAULT_FULCIO_URL = config.DEFAULT_FULCIO_URL;
-exports.DEFAULT_REKOR_URL = config.DEFAULT_REKOR_URL;
diff --git a/deps/npm/node_modules/sigstore/dist/tlog/format.d.ts b/deps/npm/node_modules/sigstore/dist/tlog/format.d.ts
deleted file mode 100644
index 8a00f546b874fd..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/tlog/format.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-/// 
-import { SignatureMaterial } from '../types/signature';
-import { Envelope } from '../types/sigstore';
-import type { ProposedDSSEEntry, ProposedHashedRekordEntry, ProposedIntotoEntry } from '../external/rekor';
-export declare function toProposedDSSEEntry(envelope: Envelope, signature: SignatureMaterial, apiVersion?: string): ProposedDSSEEntry;
-export declare function toProposedHashedRekordEntry(digest: Buffer, signature: SignatureMaterial): ProposedHashedRekordEntry;
-export declare function toProposedIntotoEntry(envelope: Envelope, signature: SignatureMaterial, apiVersion?: string): ProposedIntotoEntry;
diff --git a/deps/npm/node_modules/sigstore/dist/tlog/format.js b/deps/npm/node_modules/sigstore/dist/tlog/format.js
deleted file mode 100644
index b0eae95098af01..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/tlog/format.js
+++ /dev/null
@@ -1,134 +0,0 @@
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.toProposedIntotoEntry = exports.toProposedHashedRekordEntry = exports.toProposedDSSEEntry = void 0;
-const sigstore_1 = require("../types/sigstore");
-const util_1 = require("../util");
-const DEFAULT_DSSE_API_VERSION = '0.0.1';
-const DEFAULT_HASHEDREKORD_API_VERSION = '0.0.1';
-const DEFAULT_INTOTO_API_VERSION = '0.0.2';
-// Returns a properly formatted Rekor "dsse" entry for the given DSSE
-// envelope and signature
-function toProposedDSSEEntry(envelope, signature, apiVersion = DEFAULT_DSSE_API_VERSION) {
-    switch (apiVersion) {
-        case '0.0.1':
-            return toProposedDSSEV001Entry(envelope, signature);
-        default:
-            throw new Error(`Unsupported dsse kind API version: ${apiVersion}`);
-    }
-}
-exports.toProposedDSSEEntry = toProposedDSSEEntry;
-// Returns a properly formatted Rekor "hashedrekord" entry for the given digest
-// and signature
-function toProposedHashedRekordEntry(digest, signature) {
-    const hexDigest = digest.toString('hex');
-    const b64Signature = signature.signature.toString('base64');
-    const b64Key = util_1.encoding.base64Encode(toPublicKey(signature));
-    return {
-        apiVersion: DEFAULT_HASHEDREKORD_API_VERSION,
-        kind: 'hashedrekord',
-        spec: {
-            data: {
-                hash: {
-                    algorithm: 'sha256',
-                    value: hexDigest,
-                },
-            },
-            signature: {
-                content: b64Signature,
-                publicKey: {
-                    content: b64Key,
-                },
-            },
-        },
-    };
-}
-exports.toProposedHashedRekordEntry = toProposedHashedRekordEntry;
-// Returns a properly formatted Rekor "intoto" entry for the given DSSE
-// envelope and signature
-function toProposedIntotoEntry(envelope, signature, apiVersion = DEFAULT_INTOTO_API_VERSION) {
-    switch (apiVersion) {
-        case '0.0.2':
-            return toProposedIntotoV002Entry(envelope, signature);
-        default:
-            throw new Error(`Unsupported intoto kind API version: ${apiVersion}`);
-    }
-}
-exports.toProposedIntotoEntry = toProposedIntotoEntry;
-function toProposedDSSEV001Entry(envelope, signature) {
-    return {
-        apiVersion: '0.0.1',
-        kind: 'dsse',
-        spec: {
-            proposedContent: {
-                envelope: JSON.stringify(sigstore_1.Envelope.toJSON(envelope)),
-                verifiers: [util_1.encoding.base64Encode(toPublicKey(signature))],
-            },
-        },
-    };
-}
-function toProposedIntotoV002Entry(envelope, signature) {
-    // Calculate the value for the payloadHash field in the Rekor entry
-    const payloadHash = util_1.crypto.hash(envelope.payload).toString('hex');
-    // Calculate the value for the hash field in the Rekor entry
-    const envelopeHash = calculateDSSEHash(envelope, signature);
-    // Collect values for re-creating the DSSE envelope.
-    // Double-encode payload and signature cause that's what Rekor expects
-    const payload = util_1.encoding.base64Encode(envelope.payload.toString('base64'));
-    const sig = util_1.encoding.base64Encode(envelope.signatures[0].sig.toString('base64'));
-    const keyid = envelope.signatures[0].keyid;
-    const publicKey = util_1.encoding.base64Encode(toPublicKey(signature));
-    // Create the envelope portion of the entry. Note the inclusion of the
-    // publicKey in the signature struct is not a standard part of a DSSE
-    // envelope, but is required by Rekor.
-    const dsseEnv = {
-        payloadType: envelope.payloadType,
-        payload: payload,
-        signatures: [{ sig, publicKey }],
-    };
-    // If the keyid is an empty string, Rekor seems to remove it altogether. We
-    // need to do the same here so that we can properly recreate the entry for
-    // verification.
-    if (keyid.length > 0) {
-        dsseEnv.signatures[0].keyid = keyid;
-    }
-    return {
-        apiVersion: '0.0.2',
-        kind: 'intoto',
-        spec: {
-            content: {
-                envelope: dsseEnv,
-                hash: { algorithm: 'sha256', value: envelopeHash },
-                payloadHash: { algorithm: 'sha256', value: payloadHash },
-            },
-        },
-    };
-}
-// Calculates the hash of a DSSE envelope for inclusion in a Rekor entry.
-// There is no standard way to do this, so the scheme we're using as as
-// follows:
-//  * payload is base64 encoded
-//  * signature is base64 encoded (only the first signature is used)
-//  * keyid is included ONLY if it is NOT an empty string
-//  * The resulting JSON is canonicalized and hashed to a hex string
-function calculateDSSEHash(envelope, signature) {
-    const dsseEnv = {
-        payloadType: envelope.payloadType,
-        payload: envelope.payload.toString('base64'),
-        signatures: [
-            {
-                sig: envelope.signatures[0].sig.toString('base64'),
-                publicKey: toPublicKey(signature),
-            },
-        ],
-    };
-    // If the keyid is an empty string, Rekor seems to remove it altogether.
-    if (envelope.signatures[0].keyid.length > 0) {
-        dsseEnv.signatures[0].keyid = envelope.signatures[0].keyid;
-    }
-    return util_1.crypto.hash(util_1.json.canonicalize(dsseEnv)).toString('hex');
-}
-function toPublicKey(signature) {
-    return signature.certificates
-        ? signature.certificates[0]
-        : signature.key.value;
-}
diff --git a/deps/npm/node_modules/sigstore/dist/tlog/index.d.ts b/deps/npm/node_modules/sigstore/dist/tlog/index.d.ts
deleted file mode 100644
index 6bb7d42861dc2c..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/tlog/index.d.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-/// 
-import { SignatureMaterial } from '../types/signature';
-import * as sigstore from '../types/sigstore';
-import type { Entry } from '../external/rekor';
-import type { FetchOptions } from '../types/fetch';
-interface CreateEntryOptions {
-    fetchOnConflict?: boolean;
-}
-export interface TLog {
-    createMessageSignatureEntry: (digest: Buffer, sigMaterial: SignatureMaterial) => Promise;
-    createDSSEEntry: (envelope: sigstore.Envelope, sigMaterial: SignatureMaterial, options?: CreateEntryOptions) => Promise;
-}
-export type TLogClientOptions = {
-    rekorBaseURL: string;
-} & FetchOptions;
-export declare class TLogClient implements TLog {
-    private rekor;
-    constructor(options: TLogClientOptions);
-    createMessageSignatureEntry(digest: Buffer, sigMaterial: SignatureMaterial, options?: CreateEntryOptions): Promise;
-    createDSSEEntry(envelope: sigstore.Envelope, sigMaterial: SignatureMaterial, options?: CreateEntryOptions): Promise;
-    private createEntry;
-}
-export {};
diff --git a/deps/npm/node_modules/sigstore/dist/tlog/index.js b/deps/npm/node_modules/sigstore/dist/tlog/index.js
deleted file mode 100644
index 7f5f531983b37d..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/tlog/index.js
+++ /dev/null
@@ -1,75 +0,0 @@
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.TLogClient = void 0;
-/*
-Copyright 2022 The Sigstore Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-const error_1 = require("../error");
-const external_1 = require("../external");
-const format_1 = require("./format");
-class TLogClient {
-    constructor(options) {
-        this.rekor = new external_1.Rekor({
-            baseURL: options.rekorBaseURL,
-            retry: options.retry,
-            timeout: options.timeout,
-        });
-    }
-    async createMessageSignatureEntry(digest, sigMaterial, options = {}) {
-        const proposedEntry = (0, format_1.toProposedHashedRekordEntry)(digest, sigMaterial);
-        return this.createEntry(proposedEntry, options.fetchOnConflict);
-    }
-    async createDSSEEntry(envelope, sigMaterial, options = {}) {
-        const proposedEntry = (0, format_1.toProposedIntotoEntry)(envelope, sigMaterial);
-        return this.createEntry(proposedEntry, options.fetchOnConflict);
-    }
-    async createEntry(proposedEntry, fetchOnConflict = false) {
-        let entry;
-        try {
-            entry = await this.rekor.createEntry(proposedEntry);
-        }
-        catch (err) {
-            // If the entry already exists, fetch it (if enabled)
-            if (entryExistsError(err) && fetchOnConflict) {
-                // Grab the UUID of the existing entry from the location header
-                const uuid = err.location.split('/').pop() || '';
-                try {
-                    entry = await this.rekor.getEntry(uuid);
-                }
-                catch (err) {
-                    throw new error_1.InternalError({
-                        code: 'TLOG_FETCH_ENTRY_ERROR',
-                        message: 'error fetching tlog entry',
-                        cause: err,
-                    });
-                }
-            }
-            else {
-                throw new error_1.InternalError({
-                    code: 'TLOG_CREATE_ENTRY_ERROR',
-                    message: 'error creating tlog entry',
-                    cause: err,
-                });
-            }
-        }
-        return entry;
-    }
-}
-exports.TLogClient = TLogClient;
-function entryExistsError(value) {
-    return (value instanceof external_1.HTTPError &&
-        value.statusCode === 409 &&
-        value.location !== undefined);
-}
diff --git a/deps/npm/node_modules/sigstore/dist/tlog/verify/body.d.ts b/deps/npm/node_modules/sigstore/dist/tlog/verify/body.d.ts
deleted file mode 100644
index 17de4f5c9698ab..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/tlog/verify/body.d.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-import * as sigstore from '../../types/sigstore';
-export declare function verifyTLogBody(entry: sigstore.VerifiableTransparencyLogEntry, bundleContent: sigstore.Bundle['content']): boolean;
diff --git a/deps/npm/node_modules/sigstore/dist/tlog/verify/checkpoint.js b/deps/npm/node_modules/sigstore/dist/tlog/verify/checkpoint.js
new file mode 100644
index 00000000000000..f6f35a5cad64dd
--- /dev/null
+++ b/deps/npm/node_modules/sigstore/dist/tlog/verify/checkpoint.js
@@ -0,0 +1,148 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.verifyCheckpoint = void 0;
+const error_1 = require("../../error");
+const util_1 = require("../../util");
+// Separator between the note and the signatures in a checkpoint
+const CHECKPOINT_SEPARATOR = '\n\n';
+// Checkpoint signatures are of the following form:
+// "–  \n"
+// where:
+// - the prefix is an emdash (U+2014).
+// -  gives a human-readable representation of the signing ID.
+// -  is the first 4 bytes of the SHA256 hash of the
+//   associated public key followed by the signature bytes.
+const SIGNATURE_REGEX = /\u2014 (\S+) (\S+)\n/g;
+// Verifies the checkpoint value in the given tlog entry. There are two steps
+// to the verification:
+// 1. Verify that all signatures in the checkpoint can be verified against a
+//    trusted public key
+// 2. Verify that the root hash in the checkpoint matches the root hash in the
+//    inclusion proof
+// See: https://github.com/transparency-dev/formats/blob/main/log/README.md
+function verifyCheckpoint(entry, tlogs) {
+    // Filter tlog instances to just those which were valid at the time of the
+    // entry
+    const validTLogs = filterTLogInstances(tlogs, entry.integratedTime);
+    const inclusionProof = entry.inclusionProof;
+    const signedNote = SignedNote.fromString(inclusionProof.checkpoint.envelope);
+    const checkpoint = LogCheckpoint.fromString(signedNote.note);
+    // Verify that the signatures in the checkpoint are all valid, also check
+    // that the root hash from the checkpoint matches the root hash in the
+    // inclusion proof
+    return (signedNote.verify(validTLogs) &&
+        util_1.crypto.bufferEqual(checkpoint.logHash, inclusionProof.rootHash));
+}
+exports.verifyCheckpoint = verifyCheckpoint;
+// SignedNote represents a signed note from a transparency log checkpoint. Consists
+// of a body (or note) and one more signatures calculated over the body. See
+// https://github.com/transparency-dev/formats/blob/main/log/README.md#signed-envelope
+class SignedNote {
+    constructor(note, signatures) {
+        this.note = note;
+        this.signatures = signatures;
+    }
+    // Deserialize a SignedNote from a string
+    static fromString(envelope) {
+        if (!envelope.includes(CHECKPOINT_SEPARATOR)) {
+            throw new error_1.VerificationError('malformed checkpoint: no separator');
+        }
+        // Split the note into the header and the data portions at the separator
+        const split = envelope.indexOf(CHECKPOINT_SEPARATOR);
+        const header = envelope.slice(0, split + 1);
+        const data = envelope.slice(split + CHECKPOINT_SEPARATOR.length);
+        // Find all the signature lines in the data portion
+        const matches = data.matchAll(SIGNATURE_REGEX);
+        // Parse each of the matched signature lines into the name and signature.
+        // The first four bytes of the signature are the key hint (should match the
+        // first four bytes of the log ID), and the rest is the signature itself.
+        const signatures = Array.from(matches, (match) => {
+            const [, name, signature] = match;
+            const sigBytes = Buffer.from(signature, 'base64');
+            if (sigBytes.length < 5) {
+                throw new error_1.VerificationError('malformed checkpoint: invalid signature');
+            }
+            return {
+                name,
+                keyHint: sigBytes.subarray(0, 4),
+                signature: sigBytes.subarray(4),
+            };
+        });
+        if (signatures.length === 0) {
+            throw new error_1.VerificationError('malformed checkpoint: no signatures');
+        }
+        return new SignedNote(header, signatures);
+    }
+    // Verifies the signatures in the SignedNote. For each signature, the
+    // corresponding transparency log is looked up by the key hint and the
+    // signature is verified against the public key in the transparency log.
+    // Throws an error if any of the signatures are invalid.
+    verify(tlogs) {
+        const data = Buffer.from(this.note, 'utf-8');
+        return this.signatures.every((signature) => {
+            // Find the transparency log instance with the matching key hint
+            const tlog = tlogs.find((tlog) => util_1.crypto.bufferEqual(tlog.logId.keyId.subarray(0, 4), signature.keyHint));
+            if (!tlog) {
+                return false;
+            }
+            const publicKey = util_1.crypto.createPublicKey(tlog.publicKey.rawBytes);
+            return util_1.crypto.verifyBlob(data, publicKey, signature.signature);
+        });
+    }
+}
+// LogCheckpoint represents a transparency log checkpoint. Consists of the
+// following:
+//  - origin: the name of the transparency log
+//  - logSize: the size of the log at the time of the checkpoint
+//  - logHash: the root hash of the log at the time of the checkpoint
+//  - rest: the rest of the checkpoint body, which is a list of log entries
+// See:
+// https://github.com/transparency-dev/formats/blob/main/log/README.md#checkpoint-body
+class LogCheckpoint {
+    constructor(origin, logSize, logHash, rest) {
+        this.origin = origin;
+        this.logSize = logSize;
+        this.logHash = logHash;
+        this.rest = rest;
+    }
+    static fromString(note) {
+        const lines = note.trim().split('\n');
+        if (lines.length < 4) {
+            throw new error_1.VerificationError('malformed checkpoint: too few lines in header');
+        }
+        const origin = lines[0];
+        const logSize = BigInt(lines[1]);
+        const rootHash = Buffer.from(lines[2], 'base64');
+        const rest = lines.slice(3);
+        return new LogCheckpoint(origin, logSize, rootHash, rest);
+    }
+}
+// Filter the list of tlog instances to only those which have usable public
+// keys and were valid at the given time.
+function filterTLogInstances(tlogInstances, integratedTime) {
+    const targetDate = new Date(Number(integratedTime) * 1000);
+    return tlogInstances.filter((tlog) => {
+        // Must have a log ID
+        if (!tlog.logId) {
+            return false;
+        }
+        // If the tlog doesn't have a public key, we can't use it
+        const publicKey = tlog.publicKey;
+        if (publicKey === undefined) {
+            return false;
+        }
+        // If the tlog doesn't have a rawBytes field, we can't use it
+        if (publicKey.rawBytes === undefined) {
+            return false;
+        }
+        // If the tlog doesn't have a validFor field, we don't need to check it
+        const validFor = publicKey.validFor;
+        if (validFor === undefined) {
+            return true;
+        }
+        // Check that the integrated time is within the validFor range
+        return (validFor.start !== undefined &&
+            validFor.start <= targetDate &&
+            (validFor.end === undefined || targetDate <= validFor.end));
+    });
+}
diff --git a/deps/npm/node_modules/sigstore/dist/tlog/verify/index.d.ts b/deps/npm/node_modules/sigstore/dist/tlog/verify/index.d.ts
deleted file mode 100644
index 4f96f820731f03..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/tlog/verify/index.d.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-import * as sigstore from '../../types/sigstore';
-export declare function verifyTLogEntries(bundle: sigstore.Bundle, trustedRoot: sigstore.TrustedRoot, options: sigstore.ArtifactVerificationOptions_TlogOptions): void;
diff --git a/deps/npm/node_modules/sigstore/dist/tlog/verify/index.js b/deps/npm/node_modules/sigstore/dist/tlog/verify/index.js
index cbb93133c2685f..9224feffde00b0 100644
--- a/deps/npm/node_modules/sigstore/dist/tlog/verify/index.js
+++ b/deps/npm/node_modules/sigstore/dist/tlog/verify/index.js
@@ -1,27 +1,4 @@
 "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 (mod) {
-    if (mod && mod.__esModule) return mod;
-    var result = {};
-    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
-    __setModuleDefault(result, mod);
-    return result;
-};
 Object.defineProperty(exports, "__esModule", { value: true });
 exports.verifyTLogEntries = void 0;
 /*
@@ -39,31 +16,51 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */
+const bundle_1 = require("@sigstore/bundle");
 const error_1 = require("../../error");
-const sigstore = __importStar(require("../../types/sigstore"));
 const cert_1 = require("../../x509/cert");
 const body_1 = require("./body");
+const checkpoint_1 = require("./checkpoint");
+const merkle_1 = require("./merkle");
 const set_1 = require("./set");
 // Verifies that the number of tlog entries that pass offline verification
 // is greater than or equal to the threshold specified in the options.
 function verifyTLogEntries(bundle, trustedRoot, options) {
+    if (bundle.mediaType === bundle_1.BUNDLE_V01_MEDIA_TYPE) {
+        (0, bundle_1.assertBundleV01)(bundle);
+        verifyTLogEntriesForBundleV01(bundle, trustedRoot, options);
+    }
+    else {
+        (0, bundle_1.assertBundleLatest)(bundle);
+        verifyTLogEntriesForBundleLatest(bundle, trustedRoot, options);
+    }
+}
+exports.verifyTLogEntries = verifyTLogEntries;
+function verifyTLogEntriesForBundleV01(bundle, trustedRoot, options) {
     if (options.performOnlineVerification) {
         throw new error_1.VerificationError('Online verification not implemented');
     }
     // Extract the signing cert, if available
     const signingCert = signingCertificate(bundle);
     // Iterate over the tlog entries and verify each one
-    const verifiedEntries = bundle.verificationMaterial.tlogEntries.filter((entry) => verifyTLogEntryOffline(entry, bundle.content, trustedRoot.tlogs, signingCert));
+    const verifiedEntries = bundle.verificationMaterial.tlogEntries.filter((entry) => verifyTLogEntryWithInclusionPromise(entry, bundle.content, trustedRoot.tlogs, signingCert));
     if (verifiedEntries.length < options.threshold) {
         throw new error_1.VerificationError('tlog verification failed');
     }
 }
-exports.verifyTLogEntries = verifyTLogEntries;
-function verifyTLogEntryOffline(entry, bundleContent, tlogs, signingCert) {
-    // Check that the TLog entry has the fields necessary for verification
-    if (!sigstore.isVerifiableTransparencyLogEntry(entry)) {
-        return false;
+function verifyTLogEntriesForBundleLatest(bundle, trustedRoot, options) {
+    if (options.performOnlineVerification) {
+        throw new error_1.VerificationError('Online verification not implemented');
+    }
+    // Extract the signing cert, if available
+    const signingCert = signingCertificate(bundle);
+    // Iterate over the tlog entries and verify each one
+    const verifiedEntries = bundle.verificationMaterial.tlogEntries.filter((entry) => verifyTLogEntryWithInclusionProof(entry, bundle.content, trustedRoot.tlogs, signingCert));
+    if (verifiedEntries.length < options.threshold) {
+        throw new error_1.VerificationError('tlog verification failed');
     }
+}
+function verifyTLogEntryWithInclusionPromise(entry, bundleContent, tlogs, signingCert) {
     // If there is a signing certificate availble, check that the tlog integrated
     // time is within the certificate's validity period; otherwise, skip this
     // check.
@@ -74,8 +71,20 @@ function verifyTLogEntryOffline(entry, bundleContent, tlogs, signingCert) {
         (0, set_1.verifyTLogSET)(entry, tlogs) &&
         verifyTLogIntegrationTime());
 }
+function verifyTLogEntryWithInclusionProof(entry, bundleContent, tlogs, signingCert) {
+    // If there is a signing certificate availble, check that the tlog integrated
+    // time is within the certificate's validity period; otherwise, skip this
+    // check.
+    const verifyTLogIntegrationTime = signingCert
+        ? () => signingCert.validForDate(new Date(Number(entry.integratedTime) * 1000))
+        : () => true;
+    return ((0, body_1.verifyTLogBody)(entry, bundleContent) &&
+        (0, merkle_1.verifyMerkleInclusion)(entry) &&
+        (0, checkpoint_1.verifyCheckpoint)(entry, tlogs) &&
+        verifyTLogIntegrationTime());
+}
 function signingCertificate(bundle) {
-    if (!sigstore.isBundleWithCertificateChain(bundle)) {
+    if (!(0, bundle_1.isBundleWithCertificateChain)(bundle)) {
         return undefined;
     }
     const signingCert = bundle.verificationMaterial.content.x509CertificateChain.certificates[0];
diff --git a/deps/npm/node_modules/sigstore/dist/tlog/verify/merkle.d.ts b/deps/npm/node_modules/sigstore/dist/tlog/verify/merkle.d.ts
deleted file mode 100644
index a2c47626d01f84..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/tlog/verify/merkle.d.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-import * as sigstore from '../../types/sigstore';
-export declare function verifyMerkleInclusion(entry: sigstore.TransparencyLogEntry): boolean;
diff --git a/deps/npm/node_modules/sigstore/dist/tlog/verify/merkle.js b/deps/npm/node_modules/sigstore/dist/tlog/verify/merkle.js
index 90609cb73576fe..0f246af4a28a3b 100644
--- a/deps/npm/node_modules/sigstore/dist/tlog/verify/merkle.js
+++ b/deps/npm/node_modules/sigstore/dist/tlog/verify/merkle.js
@@ -25,9 +25,6 @@ const RFC6962_LEAF_HASH_PREFIX = Buffer.from([0x00]);
 const RFC6962_NODE_HASH_PREFIX = Buffer.from([0x01]);
 function verifyMerkleInclusion(entry) {
     const inclusionProof = entry.inclusionProof;
-    if (!inclusionProof) {
-        throw new error_1.VerificationError('tlog entry has no inclusion proof');
-    }
     const logIndex = BigInt(inclusionProof.logIndex);
     const treeSize = BigInt(inclusionProof.treeSize);
     if (logIndex < 0n || logIndex >= treeSize) {
@@ -76,13 +73,20 @@ function chainBorderRight(seed, hashes) {
     return hashes.reduce((acc, h) => hashChildren(h, acc), seed);
 }
 function innerProofSize(index, size) {
-    return (index ^ (size - BigInt(1))).toString(2).length;
+    return bitLength(index ^ (size - BigInt(1)));
 }
 // Counts the number of ones in the binary representation of the given number.
 // https://en.wikipedia.org/wiki/Hamming_weight
 function onesCount(x) {
     return x.toString(2).split('1').length - 1;
 }
+// Returns the number of bits necessary to represent an integer in binary.
+function bitLength(n) {
+    if (n === 0n) {
+        return 0;
+    }
+    return n.toString(2).length;
+}
 // Hashing logic according to RFC6962.
 // https://datatracker.ietf.org/doc/html/rfc6962#section-2
 function hashChildren(left, right) {
diff --git a/deps/npm/node_modules/sigstore/dist/tlog/verify/set.d.ts b/deps/npm/node_modules/sigstore/dist/tlog/verify/set.d.ts
deleted file mode 100644
index 278317489a7e49..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/tlog/verify/set.d.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-import * as sigstore from '../../types/sigstore';
-export declare function verifyTLogSET(entry: sigstore.VerifiableTransparencyLogEntry, tlogs: sigstore.TransparencyLogInstance[]): boolean;
diff --git a/deps/npm/node_modules/sigstore/dist/tlog/verify/set.js b/deps/npm/node_modules/sigstore/dist/tlog/verify/set.js
index 89a544283d73d9..959cd5883f1cad 100644
--- a/deps/npm/node_modules/sigstore/dist/tlog/verify/set.js
+++ b/deps/npm/node_modules/sigstore/dist/tlog/verify/set.js
@@ -11,9 +11,6 @@ function verifyTLogSET(entry, tlogs) {
     const validTLogs = filterTLogInstances(tlogs, entry.logId.keyId, entry.integratedTime);
     // Check to see if we can verify the SET against any of the valid tlogs
     return validTLogs.some((tlog) => {
-        if (!tlog.publicKey?.rawBytes) {
-            return false;
-        }
         const publicKey = util_1.crypto.createPublicKey(tlog.publicKey.rawBytes);
         // Re-create the original Rekor verification payload
         const payload = toVerificationPayload(entry);
@@ -60,7 +57,7 @@ function filterTLogInstances(tlogInstances, logID, integratedTime) {
             return true;
         }
         // Check that the integrated time is within the validFor range
-        return (publicKey.validFor.start &&
+        return (publicKey.validFor.start !== undefined &&
             publicKey.validFor.start <= targetDate &&
             (!publicKey.validFor.end || targetDate <= publicKey.validFor.end));
     });
diff --git a/deps/npm/node_modules/sigstore/dist/tsa/index.d.ts b/deps/npm/node_modules/sigstore/dist/tsa/index.d.ts
deleted file mode 100644
index e94b20c075e557..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/tsa/index.d.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-/// 
-import type { FetchOptions } from '../types/fetch';
-export interface TSA {
-    createTimestamp: (signature: Buffer) => Promise;
-}
-export type TSAClientOptions = {
-    tsaBaseURL: string;
-} & FetchOptions;
-export declare class TSAClient implements TSA {
-    private tsa;
-    constructor(options: TSAClientOptions);
-    createTimestamp(signature: Buffer): Promise;
-}
diff --git a/deps/npm/node_modules/sigstore/dist/tsa/index.js b/deps/npm/node_modules/sigstore/dist/tsa/index.js
deleted file mode 100644
index 4951b24a93f4fe..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/tsa/index.js
+++ /dev/null
@@ -1,47 +0,0 @@
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.TSAClient = void 0;
-/*
-Copyright 2022 The Sigstore Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-const error_1 = require("../error");
-const external_1 = require("../external");
-const util_1 = require("../util");
-class TSAClient {
-    constructor(options) {
-        this.tsa = new external_1.TimestampAuthority({
-            baseURL: options.tsaBaseURL,
-            retry: options.retry,
-            timeout: options.timeout,
-        });
-    }
-    async createTimestamp(signature) {
-        const request = {
-            artifactHash: util_1.crypto.hash(signature).toString('base64'),
-            hashAlgorithm: 'sha256',
-        };
-        try {
-            return await this.tsa.createTimestamp(request);
-        }
-        catch (err) {
-            throw new error_1.InternalError({
-                code: 'TSA_CREATE_TIMESTAMP_ERROR',
-                message: 'error creating timestamp',
-                cause: err,
-            });
-        }
-    }
-}
-exports.TSAClient = TSAClient;
diff --git a/deps/npm/node_modules/sigstore/dist/types/fetch.d.ts b/deps/npm/node_modules/sigstore/dist/types/fetch.d.ts
deleted file mode 100644
index 510aeee6a37d72..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/types/fetch.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import type { MakeFetchHappenOptions } from 'make-fetch-happen';
-export type Retry = MakeFetchHappenOptions['retry'];
-export type FetchOptions = {
-    retry?: Retry;
-    timeout?: number | undefined;
-};
diff --git a/deps/npm/node_modules/sigstore/dist/types/signature.d.ts b/deps/npm/node_modules/sigstore/dist/types/signature.d.ts
deleted file mode 100644
index 40b4fbe6339ca6..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/types/signature.d.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-/// 
-import { Envelope } from './sigstore';
-import { OneOf } from './utility';
-interface VerificationMaterial {
-    certificates: string[];
-    key: {
-        id?: string;
-        value: string;
-    };
-}
-export type SignatureMaterial = {
-    signature: Buffer;
-} & OneOf;
-export type SignerFunc = (payload: Buffer) => Promise;
-export declare function extractSignatureMaterial(dsseEnvelope: Envelope, publicKey: string): SignatureMaterial;
-export {};
diff --git a/deps/npm/node_modules/sigstore/dist/types/signature.js b/deps/npm/node_modules/sigstore/dist/types/signature.js
deleted file mode 100644
index 339e2a2731b413..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/types/signature.js
+++ /dev/null
@@ -1,15 +0,0 @@
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.extractSignatureMaterial = void 0;
-function extractSignatureMaterial(dsseEnvelope, publicKey) {
-    const signature = dsseEnvelope.signatures[0];
-    return {
-        signature: signature.sig,
-        key: {
-            id: signature.keyid,
-            value: publicKey,
-        },
-        certificates: undefined,
-    };
-}
-exports.extractSignatureMaterial = extractSignatureMaterial;
diff --git a/deps/npm/node_modules/sigstore/dist/types/sigstore.js b/deps/npm/node_modules/sigstore/dist/types/sigstore.js
new file mode 100644
index 00000000000000..36efb67e38a5eb
--- /dev/null
+++ b/deps/npm/node_modules/sigstore/dist/types/sigstore.js
@@ -0,0 +1,27 @@
+"use strict";
+/*
+Copyright 2023 The Sigstore Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.isCAVerificationOptions = exports.SubjectAlternativeNameType = void 0;
+// Enums from protobuf-specs
+var protobuf_specs_1 = require("@sigstore/protobuf-specs");
+Object.defineProperty(exports, "SubjectAlternativeNameType", { enumerable: true, get: function () { return protobuf_specs_1.SubjectAlternativeNameType; } });
+function isCAVerificationOptions(options) {
+    return (options.ctlogOptions !== undefined &&
+        (options.signers === undefined ||
+            options.signers.$case === 'certificateIdentities'));
+}
+exports.isCAVerificationOptions = isCAVerificationOptions;
diff --git a/deps/npm/node_modules/sigstore/dist/types/sigstore/index.d.ts b/deps/npm/node_modules/sigstore/dist/types/sigstore/index.d.ts
deleted file mode 100644
index 2be598d923048f..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/types/sigstore/index.d.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-/// 
-import { SignatureMaterial } from '../signature';
-import { ValidBundle } from './validate';
-import type { ArtifactVerificationOptions, Envelope, TransparencyLogEntry, VerificationMaterial } from '@sigstore/protobuf-specs';
-import type { Entry } from '../../external/rekor';
-import type { WithRequired } from '../utility';
-import type { SerializedBundle } from './serialized';
-export { Envelope, HashAlgorithm, PublicKeyDetails, SubjectAlternativeNameType, } from '@sigstore/protobuf-specs';
-export type { ArtifactVerificationOptions, ArtifactVerificationOptions_CtlogOptions, ArtifactVerificationOptions_TlogOptions, CertificateAuthority, CertificateIdentities, CertificateIdentity, MessageSignature, ObjectIdentifierValuePair, PublicKey, PublicKeyIdentifier, RFC3161SignedTimestamp, Signature, SubjectAlternativeName, TimestampVerificationData, TransparencyLogEntry, TransparencyLogInstance, TrustedRoot, X509Certificate, X509CertificateChain, } from '@sigstore/protobuf-specs';
-export type { SerializedBundle, SerializedEnvelope } from './serialized';
-export type { ValidBundle as Bundle };
-export declare const bundleFromJSON: (obj: any) => ValidBundle;
-export declare const bundleToJSON: (bundle: ValidBundle) => SerializedBundle;
-export type BundleWithCertificateChain = ValidBundle & {
-    verificationMaterial: VerificationMaterial & {
-        content: Extract;
-    };
-};
-export declare function isBundleWithCertificateChain(bundle: ValidBundle): bundle is BundleWithCertificateChain;
-export type RequiredArtifactVerificationOptions = WithRequired;
-export type CAArtifactVerificationOptions = WithRequired & {
-    signers?: Extract;
-};
-export declare function isCAVerificationOptions(options: ArtifactVerificationOptions): options is CAArtifactVerificationOptions;
-export type VerifiableTransparencyLogEntry = WithRequired;
-export declare function isVerifiableTransparencyLogEntry(entry: TransparencyLogEntry): entry is VerifiableTransparencyLogEntry;
-export declare function toDSSEBundle({ envelope, signature, tlogEntry, timestamp, }: {
-    envelope: Envelope;
-    signature: SignatureMaterial;
-    tlogEntry?: Entry;
-    timestamp?: Buffer;
-}): ValidBundle;
-export declare function toMessageSignatureBundle({ digest, signature, tlogEntry, timestamp, }: {
-    digest: Buffer;
-    signature: SignatureMaterial;
-    tlogEntry?: Entry;
-    timestamp?: Buffer;
-}): ValidBundle;
diff --git a/deps/npm/node_modules/sigstore/dist/types/sigstore/index.js b/deps/npm/node_modules/sigstore/dist/types/sigstore/index.js
deleted file mode 100644
index 2c240c865cf37a..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/types/sigstore/index.js
+++ /dev/null
@@ -1,162 +0,0 @@
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.toMessageSignatureBundle = exports.toDSSEBundle = exports.isVerifiableTransparencyLogEntry = exports.isCAVerificationOptions = exports.isBundleWithCertificateChain = exports.bundleToJSON = exports.bundleFromJSON = exports.SubjectAlternativeNameType = exports.PublicKeyDetails = exports.HashAlgorithm = exports.Envelope = void 0;
-/*
-Copyright 2023 The Sigstore Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-const protobuf_specs_1 = require("@sigstore/protobuf-specs");
-const util_1 = require("../../util");
-const validate_1 = require("./validate");
-// Enums from protobuf-specs
-// TODO: Move Envelope to "type" export once @sigstore/sign is a thing
-var protobuf_specs_2 = require("@sigstore/protobuf-specs");
-Object.defineProperty(exports, "Envelope", { enumerable: true, get: function () { return protobuf_specs_2.Envelope; } });
-Object.defineProperty(exports, "HashAlgorithm", { enumerable: true, get: function () { return protobuf_specs_2.HashAlgorithm; } });
-Object.defineProperty(exports, "PublicKeyDetails", { enumerable: true, get: function () { return protobuf_specs_2.PublicKeyDetails; } });
-Object.defineProperty(exports, "SubjectAlternativeNameType", { enumerable: true, get: function () { return protobuf_specs_2.SubjectAlternativeNameType; } });
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-const bundleFromJSON = (obj) => {
-    const bundle = protobuf_specs_1.Bundle.fromJSON(obj);
-    (0, validate_1.assertValidBundle)(bundle);
-    return bundle;
-};
-exports.bundleFromJSON = bundleFromJSON;
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-const bundleToJSON = (bundle) => {
-    return protobuf_specs_1.Bundle.toJSON(bundle);
-};
-exports.bundleToJSON = bundleToJSON;
-const BUNDLE_MEDIA_TYPE = 'application/vnd.dev.sigstore.bundle+json;version=0.1';
-// Type guard for narrowing a Bundle to a BundleWithCertificateChain
-function isBundleWithCertificateChain(bundle) {
-    return (bundle.verificationMaterial.content !== undefined &&
-        bundle.verificationMaterial.content.$case === 'x509CertificateChain');
-}
-exports.isBundleWithCertificateChain = isBundleWithCertificateChain;
-function isCAVerificationOptions(options) {
-    return (options.ctlogOptions !== undefined &&
-        (options.signers === undefined ||
-            options.signers.$case === 'certificateIdentities'));
-}
-exports.isCAVerificationOptions = isCAVerificationOptions;
-function isVerifiableTransparencyLogEntry(entry) {
-    return (entry.logId !== undefined &&
-        entry.inclusionPromise !== undefined &&
-        entry.kindVersion !== undefined);
-}
-exports.isVerifiableTransparencyLogEntry = isVerifiableTransparencyLogEntry;
-// All of the following functions are used to construct a ValidBundle
-// from various types of input. When this code moves into the
-// @sigstore/sign package, these functions will be exported from there.
-function toDSSEBundle({ envelope, signature, tlogEntry, timestamp, }) {
-    return {
-        mediaType: BUNDLE_MEDIA_TYPE,
-        content: { $case: 'dsseEnvelope', dsseEnvelope: envelope },
-        verificationMaterial: toVerificationMaterial({
-            signature,
-            tlogEntry,
-            timestamp,
-        }),
-    };
-}
-exports.toDSSEBundle = toDSSEBundle;
-function toMessageSignatureBundle({ digest, signature, tlogEntry, timestamp, }) {
-    return {
-        mediaType: BUNDLE_MEDIA_TYPE,
-        content: {
-            $case: 'messageSignature',
-            messageSignature: {
-                messageDigest: {
-                    algorithm: protobuf_specs_1.HashAlgorithm.SHA2_256,
-                    digest: digest,
-                },
-                signature: signature.signature,
-            },
-        },
-        verificationMaterial: toVerificationMaterial({
-            signature,
-            tlogEntry,
-            timestamp,
-        }),
-    };
-}
-exports.toMessageSignatureBundle = toMessageSignatureBundle;
-function toTransparencyLogEntry(entry) {
-    const b64SET = entry.verification?.signedEntryTimestamp || '';
-    const set = Buffer.from(b64SET, 'base64');
-    const logID = Buffer.from(entry.logID, 'hex');
-    const proof = entry.verification?.inclusionProof
-        ? toInclusionProof(entry.verification.inclusionProof)
-        : undefined;
-    // Parse entry body so we can extract the kind and version.
-    const bodyJSON = util_1.encoding.base64Decode(entry.body);
-    const entryBody = JSON.parse(bodyJSON);
-    return {
-        inclusionPromise: {
-            signedEntryTimestamp: set,
-        },
-        logIndex: entry.logIndex.toString(),
-        logId: {
-            keyId: logID,
-        },
-        integratedTime: entry.integratedTime.toString(),
-        kindVersion: {
-            kind: entryBody.kind,
-            version: entryBody.apiVersion,
-        },
-        inclusionProof: proof,
-        canonicalizedBody: Buffer.from(entry.body, 'base64'),
-    };
-}
-function toInclusionProof(proof) {
-    return {
-        logIndex: proof.logIndex.toString(),
-        rootHash: Buffer.from(proof.rootHash, 'hex'),
-        treeSize: proof.treeSize.toString(),
-        checkpoint: {
-            envelope: proof.checkpoint,
-        },
-        hashes: proof.hashes.map((h) => Buffer.from(h, 'hex')),
-    };
-}
-function toVerificationMaterial({ signature, tlogEntry, timestamp, }) {
-    return {
-        content: signature.certificates
-            ? toVerificationMaterialx509CertificateChain(signature.certificates)
-            : toVerificationMaterialPublicKey(signature.key.id || ''),
-        tlogEntries: tlogEntry ? [toTransparencyLogEntry(tlogEntry)] : [],
-        timestampVerificationData: timestamp
-            ? toTimestampVerificationData(timestamp)
-            : undefined,
-    };
-}
-function toVerificationMaterialx509CertificateChain(certificates) {
-    return {
-        $case: 'x509CertificateChain',
-        x509CertificateChain: {
-            certificates: certificates.map((c) => ({
-                rawBytes: util_1.pem.toDER(c),
-            })),
-        },
-    };
-}
-function toVerificationMaterialPublicKey(hint) {
-    return { $case: 'publicKey', publicKey: { hint } };
-}
-function toTimestampVerificationData(timestamp) {
-    return {
-        rfc3161Timestamps: [{ signedTimestamp: timestamp }],
-    };
-}
diff --git a/deps/npm/node_modules/sigstore/dist/types/sigstore/serialized.d.ts b/deps/npm/node_modules/sigstore/dist/types/sigstore/serialized.d.ts
deleted file mode 100644
index 8ea3b5cff35ee9..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/types/sigstore/serialized.d.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import { OneOf } from '../utility';
-type SerializedTLogEntry = {
-    logIndex: string;
-    logId: {
-        keyId: string;
-    };
-    kindVersion: {
-        kind: string;
-        version: string;
-    } | undefined;
-    integratedTime: string;
-    inclusionPromise: {
-        signedEntryTimestamp: string;
-    };
-    inclusionProof: {
-        logIndex: string;
-        rootHash: string;
-        treeSize: string;
-        hashes: string[];
-        checkpoint: {
-            envelope: string;
-        };
-    } | undefined;
-    canonicalizedBody: string;
-};
-type SerializedTimestampVerificationData = {
-    rfc3161Timestamps: {
-        signedTimestamp: string;
-    }[];
-};
-type SerializedMessageSignature = {
-    messageDigest: {
-        algorithm: string;
-        digest: string;
-    } | undefined;
-    signature: string;
-};
-type SerializedDSSEEnvelope = {
-    payload: string;
-    payloadType: string;
-    signatures: {
-        sig: string;
-        keyid: string;
-    }[];
-};
-export type { SerializedDSSEEnvelope as SerializedEnvelope };
-export type SerializedBundle = {
-    mediaType: string;
-    verificationMaterial: (OneOf<{
-        x509CertificateChain: {
-            certificates: {
-                rawBytes: string;
-            }[];
-        };
-        publicKey: {
-            hint: string;
-        };
-    }> | undefined) & {
-        tlogEntries: SerializedTLogEntry[];
-        timestampVerificationData: SerializedTimestampVerificationData | undefined;
-    };
-} & OneOf<{
-    dsseEnvelope: SerializedDSSEEnvelope;
-    messageSignature: SerializedMessageSignature;
-}>;
diff --git a/deps/npm/node_modules/sigstore/dist/types/sigstore/validate.d.ts b/deps/npm/node_modules/sigstore/dist/types/sigstore/validate.d.ts
deleted file mode 100644
index a6c33b3c7c0f28..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/types/sigstore/validate.d.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { WithRequired } from '../utility';
-import type { Bundle, MessageSignature, VerificationMaterial } from '@sigstore/protobuf-specs';
-export type ValidBundle = Bundle & {
-    verificationMaterial: VerificationMaterial & {
-        content: NonNullable;
-    };
-    content: (Extract & {
-        messageSignature: WithRequired;
-    }) | Extract;
-};
-export declare function assertValidBundle(b: Bundle): asserts b is ValidBundle;
diff --git a/deps/npm/node_modules/sigstore/dist/types/sigstore/validate.js b/deps/npm/node_modules/sigstore/dist/types/sigstore/validate.js
deleted file mode 100644
index a19d8ad3ec7021..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/types/sigstore/validate.js
+++ /dev/null
@@ -1,88 +0,0 @@
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.assertValidBundle = void 0;
-/*
-Copyright 2023 The Sigstore Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-const error_1 = require("../../error");
-// Performs basic validation of a Sigstore bundle to ensure that all required
-// fields are populated. This is not a complete validation of the bundle, but
-// rather a check that the bundle is in a valid state to be processed by the
-// rest of the code.
-function assertValidBundle(b) {
-    const invalidValues = [];
-    // Content-related validation
-    if (b.content === undefined) {
-        invalidValues.push('content');
-    }
-    else {
-        switch (b.content.$case) {
-            case 'messageSignature':
-                if (b.content.messageSignature.messageDigest === undefined) {
-                    invalidValues.push('content.messageSignature.messageDigest');
-                }
-                else {
-                    if (b.content.messageSignature.messageDigest.digest.length === 0) {
-                        invalidValues.push('content.messageSignature.messageDigest.digest');
-                    }
-                }
-                if (b.content.messageSignature.signature.length === 0) {
-                    invalidValues.push('content.messageSignature.signature');
-                }
-                break;
-            case 'dsseEnvelope':
-                if (b.content.dsseEnvelope.payload.length === 0) {
-                    invalidValues.push('content.dsseEnvelope.payload');
-                }
-                if (b.content.dsseEnvelope.signatures.length !== 1) {
-                    invalidValues.push('content.dsseEnvelope.signatures');
-                }
-                else {
-                    if (b.content.dsseEnvelope.signatures[0].sig.length === 0) {
-                        invalidValues.push('content.dsseEnvelope.signatures[0].sig');
-                    }
-                }
-                break;
-        }
-    }
-    // Verification material-related validation
-    if (b.verificationMaterial === undefined) {
-        invalidValues.push('verificationMaterial');
-    }
-    else {
-        if (b.verificationMaterial.content === undefined) {
-            invalidValues.push('verificationMaterial.content');
-        }
-        else {
-            switch (b.verificationMaterial.content.$case) {
-                case 'x509CertificateChain':
-                    if (b.verificationMaterial.content.x509CertificateChain.certificates
-                        .length === 0) {
-                        invalidValues.push('verificationMaterial.content.x509CertificateChain.certificates');
-                    }
-                    b.verificationMaterial.content.x509CertificateChain.certificates.forEach((cert, i) => {
-                        if (cert.rawBytes.length === 0) {
-                            invalidValues.push(`verificationMaterial.content.x509CertificateChain.certificates[${i}].rawBytes`);
-                        }
-                    });
-                    break;
-            }
-        }
-    }
-    if (invalidValues.length > 0) {
-        throw new error_1.ValidationError(`invalid/missing bundle values: ${invalidValues.join(', ')}`);
-    }
-}
-exports.assertValidBundle = assertValidBundle;
diff --git a/deps/npm/node_modules/sigstore/dist/types/utility.d.ts b/deps/npm/node_modules/sigstore/dist/types/utility.d.ts
deleted file mode 100644
index df993d503f8ea1..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/types/utility.d.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-type ValueOf = Obj[keyof Obj];
-type OneOnly = {
-    [key in Exclude]: undefined;
-} & {
-    [key in K]: Obj[K];
-};
-type OneOfByKey = {
-    [key in keyof Obj]: OneOnly;
-};
-export type OneOf = ValueOf>;
-export type WithRequired = T & {
-    [P in K]-?: NonNullable;
-};
-export {};
diff --git a/deps/npm/node_modules/sigstore/dist/types/utility.js b/deps/npm/node_modules/sigstore/dist/types/utility.js
index 132848cd7587e7..77c91b1923ca08 100644
--- a/deps/npm/node_modules/sigstore/dist/types/utility.js
+++ b/deps/npm/node_modules/sigstore/dist/types/utility.js
@@ -14,5 +14,4 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */
-// https://dev.to/maxime1992/implement-a-generic-oneof-type-with-typescript-22em
 Object.defineProperty(exports, "__esModule", { value: true });
diff --git a/deps/npm/node_modules/sigstore/dist/util/asn1/dump.d.ts b/deps/npm/node_modules/sigstore/dist/util/asn1/dump.d.ts
deleted file mode 100644
index 3f192dea45445c..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/util/asn1/dump.d.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-import { ASN1Obj } from './obj';
-export declare function dump(obj: ASN1Obj, indent?: number): void;
diff --git a/deps/npm/node_modules/sigstore/dist/util/asn1/error.d.ts b/deps/npm/node_modules/sigstore/dist/util/asn1/error.d.ts
deleted file mode 100644
index fcd908f47036ac..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/util/asn1/error.d.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export declare class ASN1ParseError extends Error {
-}
-export declare class ASN1TypeError extends Error {
-}
diff --git a/deps/npm/node_modules/sigstore/dist/util/asn1/index.d.ts b/deps/npm/node_modules/sigstore/dist/util/asn1/index.d.ts
deleted file mode 100644
index da45453d4eab7b..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/util/asn1/index.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { ASN1Obj } from './obj';
diff --git a/deps/npm/node_modules/sigstore/dist/util/asn1/length.d.ts b/deps/npm/node_modules/sigstore/dist/util/asn1/length.d.ts
deleted file mode 100644
index 97c7114af29091..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/util/asn1/length.d.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-/// 
-import { ByteStream } from '../stream';
-export declare function decodeLength(stream: ByteStream): number;
-export declare function encodeLength(len: number): Buffer;
diff --git a/deps/npm/node_modules/sigstore/dist/util/asn1/obj.d.ts b/deps/npm/node_modules/sigstore/dist/util/asn1/obj.d.ts
deleted file mode 100644
index de54996c87faac..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/util/asn1/obj.d.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-/// 
-import { ASN1Tag } from './tag';
-export declare class ASN1Obj {
-    readonly tag: ASN1Tag;
-    readonly subs: ASN1Obj[];
-    readonly value: Buffer;
-    constructor(tag: ASN1Tag, value: Buffer, subs: ASN1Obj[]);
-    static parseBuffer(buf: Buffer): ASN1Obj;
-    toDER(): Buffer;
-    toBoolean(): boolean;
-    toInteger(): bigint;
-    toOID(): string;
-    toDate(): Date;
-    toBitString(): number[];
-}
diff --git a/deps/npm/node_modules/sigstore/dist/util/asn1/parse.d.ts b/deps/npm/node_modules/sigstore/dist/util/asn1/parse.d.ts
deleted file mode 100644
index 35989d5510e26b..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/util/asn1/parse.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-/// 
-export declare function parseInteger(buf: Buffer): bigint;
-export declare function parseStringASCII(buf: Buffer): string;
-export declare function parseTime(buf: Buffer, shortYear: boolean): Date;
-export declare function parseOID(buf: Buffer): string;
-export declare function parseBoolean(buf: Buffer): boolean;
-export declare function parseBitString(buf: Buffer): number[];
diff --git a/deps/npm/node_modules/sigstore/dist/util/asn1/tag.d.ts b/deps/npm/node_modules/sigstore/dist/util/asn1/tag.d.ts
deleted file mode 100644
index cdc9a69097b380..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/util/asn1/tag.d.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-export declare const UNIVERSAL_TAG: {
-    BOOLEAN: number;
-    INTEGER: number;
-    BIT_STRING: number;
-    OCTET_STRING: number;
-    OBJECT_IDENTIFIER: number;
-    SEQUENCE: number;
-    SET: number;
-    PRINTABLE_STRING: number;
-    UTC_TIME: number;
-    GENERALIZED_TIME: number;
-};
-export declare class ASN1Tag {
-    readonly number: number;
-    readonly constructed: boolean;
-    readonly class: number;
-    constructor(enc: number);
-    isUniversal(): boolean;
-    isContextSpecific(num?: number): boolean;
-    isBoolean(): boolean;
-    isInteger(): boolean;
-    isBitString(): boolean;
-    isOctetString(): boolean;
-    isOID(): boolean;
-    isUTCTime(): boolean;
-    isGeneralizedTime(): boolean;
-    toDER(): number;
-}
diff --git a/deps/npm/node_modules/sigstore/dist/util/crypto.d.ts b/deps/npm/node_modules/sigstore/dist/util/crypto.d.ts
deleted file mode 100644
index a726dd260750c3..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/util/crypto.d.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-/// 
-/// 
-/// 
-import { BinaryLike, KeyLike, KeyPairKeyObjectResult } from 'crypto';
-export declare function generateKeyPair(): KeyPairKeyObjectResult;
-export declare function createPublicKey(key: string | Buffer): KeyLike;
-export declare function signBlob(data: NodeJS.ArrayBufferView, privateKey: KeyLike): Buffer;
-export declare function verifyBlob(data: Buffer, key: KeyLike, signature: Buffer, algorithm?: string): boolean;
-export declare function hash(data: BinaryLike): Buffer;
-export declare function randomBytes(count: number): Buffer;
diff --git a/deps/npm/node_modules/sigstore/dist/util/crypto.js b/deps/npm/node_modules/sigstore/dist/util/crypto.js
index 0b1e0bc62d8abb..c26de091ecdb62 100644
--- a/deps/npm/node_modules/sigstore/dist/util/crypto.js
+++ b/deps/npm/node_modules/sigstore/dist/util/crypto.js
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
     return (mod && mod.__esModule) ? mod : { "default": mod };
 };
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.randomBytes = exports.hash = exports.verifyBlob = exports.signBlob = exports.createPublicKey = exports.generateKeyPair = void 0;
+exports.bufferEqual = exports.randomBytes = exports.hash = exports.verifyBlob = exports.createPublicKey = void 0;
 /*
 Copyright 2022 The Sigstore Authors.
 
@@ -20,15 +20,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 const crypto_1 = __importDefault(require("crypto"));
-const EC_KEYPAIR_TYPE = 'ec';
-const P256_CURVE = 'P-256';
 const SHA256_ALGORITHM = 'sha256';
-function generateKeyPair() {
-    return crypto_1.default.generateKeyPairSync(EC_KEYPAIR_TYPE, {
-        namedCurve: P256_CURVE,
-    });
-}
-exports.generateKeyPair = generateKeyPair;
 function createPublicKey(key) {
     if (typeof key === 'string') {
         return crypto_1.default.createPublicKey(key);
@@ -38,10 +30,6 @@ function createPublicKey(key) {
     }
 }
 exports.createPublicKey = createPublicKey;
-function signBlob(data, privateKey) {
-    return crypto_1.default.sign(null, data, privateKey);
-}
-exports.signBlob = signBlob;
 function verifyBlob(data, key, signature, algorithm) {
     // The try/catch is to work around an issue in Node 14.x where verify throws
     // an error in some scenarios if the signature is invalid.
@@ -49,6 +37,7 @@ function verifyBlob(data, key, signature, algorithm) {
         return crypto_1.default.verify(algorithm, data, key, signature);
     }
     catch (e) {
+        /* istanbul ignore next */
         return false;
     }
 }
@@ -62,3 +51,13 @@ function randomBytes(count) {
     return crypto_1.default.randomBytes(count);
 }
 exports.randomBytes = randomBytes;
+function bufferEqual(a, b) {
+    try {
+        return crypto_1.default.timingSafeEqual(a, b);
+    }
+    catch {
+        /* istanbul ignore next */
+        return false;
+    }
+}
+exports.bufferEqual = bufferEqual;
diff --git a/deps/npm/node_modules/sigstore/dist/util/dsse.d.ts b/deps/npm/node_modules/sigstore/dist/util/dsse.d.ts
deleted file mode 100644
index 839b9c03ce38c7..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/util/dsse.d.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-/// 
-export declare function preAuthEncoding(payloadType: string, payload: Buffer): Buffer;
diff --git a/deps/npm/node_modules/sigstore/dist/util/encoding.d.ts b/deps/npm/node_modules/sigstore/dist/util/encoding.d.ts
deleted file mode 100644
index f1347c241ed0c4..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/util/encoding.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export declare function base64Encode(str: string): string;
-export declare function base64Decode(str: string): string;
-export declare function base64URLEncode(str: string): string;
-export declare function base64URLDecode(str: string): string;
-export declare function base64URLEscape(str: string): string;
-export declare function base64URLUnescape(str: string): string;
diff --git a/deps/npm/node_modules/sigstore/dist/util/index.d.ts b/deps/npm/node_modules/sigstore/dist/util/index.d.ts
deleted file mode 100644
index f062a1c9d3c57d..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/util/index.d.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-export * as asn1 from './asn1';
-export * as crypto from './crypto';
-export * as dsse from './dsse';
-export * as encoding from './encoding';
-export * as json from './json';
-export * as oidc from './oidc';
-export * as pem from './pem';
-export * as promise from './promise';
-export * as ua from './ua';
diff --git a/deps/npm/node_modules/sigstore/dist/util/index.js b/deps/npm/node_modules/sigstore/dist/util/index.js
index b7d6ce21aafd3b..ff4cec375af8f8 100644
--- a/deps/npm/node_modules/sigstore/dist/util/index.js
+++ b/deps/npm/node_modules/sigstore/dist/util/index.js
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
     return result;
 };
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.ua = exports.promise = exports.pem = exports.oidc = exports.json = exports.encoding = exports.dsse = exports.crypto = exports.asn1 = void 0;
+exports.pem = exports.json = exports.encoding = exports.dsse = exports.crypto = exports.asn1 = void 0;
 /*
 Copyright 2022 The Sigstore Authors.
 
@@ -44,7 +44,4 @@ exports.crypto = __importStar(require("./crypto"));
 exports.dsse = __importStar(require("./dsse"));
 exports.encoding = __importStar(require("./encoding"));
 exports.json = __importStar(require("./json"));
-exports.oidc = __importStar(require("./oidc"));
 exports.pem = __importStar(require("./pem"));
-exports.promise = __importStar(require("./promise"));
-exports.ua = __importStar(require("./ua"));
diff --git a/deps/npm/node_modules/sigstore/dist/util/json.d.ts b/deps/npm/node_modules/sigstore/dist/util/json.d.ts
deleted file mode 100644
index ed331817ef2360..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/util/json.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-export declare function canonicalize(object: any): string;
diff --git a/deps/npm/node_modules/sigstore/dist/util/oidc.d.ts b/deps/npm/node_modules/sigstore/dist/util/oidc.d.ts
deleted file mode 100644
index b4513891a3527f..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/util/oidc.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-export declare function extractJWTSubject(jwt: string): string;
diff --git a/deps/npm/node_modules/sigstore/dist/util/pem.d.ts b/deps/npm/node_modules/sigstore/dist/util/pem.d.ts
deleted file mode 100644
index 6910679cae0654..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/util/pem.d.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-/// 
-export declare function toDER(certificate: string): Buffer;
-export declare function fromDER(certificate: Buffer, type?: string): string;
diff --git a/deps/npm/node_modules/sigstore/dist/util/promise.d.ts b/deps/npm/node_modules/sigstore/dist/util/promise.d.ts
deleted file mode 100644
index bbc501a85a7c60..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/util/promise.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-export declare const promiseAny: (values: Iterable>) => Promise;
diff --git a/deps/npm/node_modules/sigstore/dist/util/promise.js b/deps/npm/node_modules/sigstore/dist/util/promise.js
deleted file mode 100644
index 8101dd47afe026..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/util/promise.js
+++ /dev/null
@@ -1,27 +0,0 @@
-"use strict";
-/*
-Copyright 2022 The Sigstore Authors.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.promiseAny = void 0;
-// Implementation of Promise.any (not available until Node v15).
-// We're basically inverting the logic of Promise.all and taking advantage
-// of the fact that Promise.all will return early on the first rejection.
-// By reversing the resolve/reject logic we can use this to return early
-// on the first resolved promise.
-const promiseAny = async (values) => {
-    return Promise.all([...values].map((promise) => new Promise((resolve, reject) => promise.then(reject, resolve)))).then((errors) => Promise.reject(errors), (value) => Promise.resolve(value));
-};
-exports.promiseAny = promiseAny;
diff --git a/deps/npm/node_modules/sigstore/dist/util/stream.d.ts b/deps/npm/node_modules/sigstore/dist/util/stream.d.ts
deleted file mode 100644
index 4d509565942e14..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/util/stream.d.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-/// 
-export declare class StreamError extends Error {
-}
-export declare class ByteStream {
-    private static BLOCK_SIZE;
-    private buf;
-    private view;
-    private start;
-    constructor(buffer?: ArrayBuffer);
-    get buffer(): Buffer;
-    get length(): number;
-    get position(): number;
-    seek(position: number): void;
-    slice(start: number, len: number): Buffer;
-    appendChar(char: number): void;
-    appendUint16(num: number): void;
-    appendUint24(num: number): void;
-    appendView(view: Uint8Array): void;
-    getBlock(size: number): Buffer;
-    getUint8(): number;
-    getUint16(): number;
-    private ensureCapacity;
-    private realloc;
-}
diff --git a/deps/npm/node_modules/sigstore/dist/util/ua.d.ts b/deps/npm/node_modules/sigstore/dist/util/ua.d.ts
deleted file mode 100644
index b60e2e9c3e5374..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/util/ua.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-export declare const getUserAgent: () => string;
diff --git a/deps/npm/node_modules/sigstore/dist/verify.d.ts b/deps/npm/node_modules/sigstore/dist/verify.d.ts
deleted file mode 100644
index 850d0f37f09817..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/verify.d.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-/// 
-import * as sigstore from './types/sigstore';
-export type KeySelector = (hint: string) => string | Buffer | undefined;
-export declare class Verifier {
-    private trustedRoot;
-    private keySelector;
-    constructor(trustedRoot: sigstore.TrustedRoot, keySelector?: KeySelector);
-    verify(bundle: sigstore.Bundle, options: sigstore.RequiredArtifactVerificationOptions, data?: Buffer): void;
-    private verifyArtifactSignature;
-    private verifySigningCertificate;
-    private verifyTLogEntries;
-    private getPublicKey;
-}
diff --git a/deps/npm/node_modules/sigstore/dist/verify.js b/deps/npm/node_modules/sigstore/dist/verify.js
index 49f63d93abb268..a3dc4b307e4953 100644
--- a/deps/npm/node_modules/sigstore/dist/verify.js
+++ b/deps/npm/node_modules/sigstore/dist/verify.js
@@ -24,6 +24,22 @@ var __importStar = (this && this.__importStar) || function (mod) {
 };
 Object.defineProperty(exports, "__esModule", { value: true });
 exports.Verifier = void 0;
+/*
+Copyright 2023 The Sigstore Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+const bundle_1 = require("@sigstore/bundle");
 const ca = __importStar(require("./ca/verify"));
 const error_1 = require("./error");
 const tlog = __importStar(require("./tlog/verify"));
@@ -38,7 +54,7 @@ class Verifier {
     // and the bundle's transparency log entries.
     verify(bundle, options, data) {
         this.verifyArtifactSignature(bundle, data);
-        if (sigstore.isBundleWithCertificateChain(bundle)) {
+        if ((0, bundle_1.isBundleWithCertificateChain)(bundle)) {
             this.verifySigningCertificate(bundle, options);
         }
         if (options.tlogOptions.disable === false) {
diff --git a/deps/npm/node_modules/sigstore/dist/x509/cert.d.ts b/deps/npm/node_modules/sigstore/dist/x509/cert.d.ts
deleted file mode 100644
index 216dbd39cb1f7d..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/x509/cert.d.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-/// 
-import * as sigstore from '../types/sigstore';
-import { ASN1Obj } from '../util/asn1';
-import { x509AuthorityKeyIDExtension, x509BasicConstraintsExtension, x509Extension, x509KeyUsageExtension, x509SCTExtension, x509SubjectAlternativeNameExtension, x509SubjectKeyIDExtension } from './ext';
-interface SCTVerificationResult {
-    verified: boolean;
-    logID: Buffer;
-}
-export declare class x509Certificate {
-    root: ASN1Obj;
-    constructor(asn1: ASN1Obj);
-    static parse(cert: Buffer | string): x509Certificate;
-    get tbsCertificate(): ASN1Obj;
-    get version(): string;
-    get notBefore(): Date;
-    get notAfter(): Date;
-    get issuer(): Buffer;
-    get subject(): Buffer;
-    get publicKey(): Buffer;
-    get signatureAlgorithm(): string;
-    get signatureValue(): Buffer;
-    get extensions(): ASN1Obj[];
-    get extKeyUsage(): x509KeyUsageExtension | undefined;
-    get extBasicConstraints(): x509BasicConstraintsExtension | undefined;
-    get extSubjectAltName(): x509SubjectAlternativeNameExtension | undefined;
-    get extAuthorityKeyID(): x509AuthorityKeyIDExtension | undefined;
-    get extSubjectKeyID(): x509SubjectKeyIDExtension | undefined;
-    get extSCT(): x509SCTExtension | undefined;
-    get isCA(): boolean;
-    extension(oid: string): x509Extension | undefined;
-    verify(issuerCertificate?: x509Certificate): boolean;
-    validForDate(date: Date): boolean;
-    equals(other: x509Certificate): boolean;
-    verifySCTs(issuer: x509Certificate, logs: sigstore.TransparencyLogInstance[]): SCTVerificationResult[];
-    private clone;
-    private findExtension;
-    private checkRecognizedExtensions;
-    private get tbsCertificateObj();
-    private get signatureAlgorithmObj();
-    private get signatureValueObj();
-    private get versionObj();
-    private get issuerObj();
-    private get validityObj();
-    private get subjectObj();
-    private get subjectPublicKeyInfoObj();
-    private get extensionsObj();
-}
-export {};
diff --git a/deps/npm/node_modules/sigstore/dist/x509/ext.d.ts b/deps/npm/node_modules/sigstore/dist/x509/ext.d.ts
deleted file mode 100644
index d6285f306f6adc..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/x509/ext.d.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-/// 
-import { ASN1Obj } from '../util/asn1';
-import { SignedCertificateTimestamp } from './sct';
-export declare class x509Extension {
-    protected root: ASN1Obj;
-    constructor(asn1: ASN1Obj);
-    get oid(): string;
-    get critical(): boolean;
-    get value(): Buffer;
-    get valueObj(): ASN1Obj;
-    protected get extnValueObj(): ASN1Obj;
-}
-export declare class x509BasicConstraintsExtension extends x509Extension {
-    get isCA(): boolean;
-    get pathLenConstraint(): bigint | undefined;
-    private get sequence();
-}
-export declare class x509KeyUsageExtension extends x509Extension {
-    get digitalSignature(): boolean;
-    get keyCertSign(): boolean;
-    get crlSign(): boolean;
-    private get bitString();
-}
-export declare class x509SubjectAlternativeNameExtension extends x509Extension {
-    get rfc822Name(): string | undefined;
-    get uri(): string | undefined;
-    otherName(oid: string): string | undefined;
-    private findGeneralName;
-    private get generalNames();
-}
-export declare class x509AuthorityKeyIDExtension extends x509Extension {
-    get keyIdentifier(): Buffer | undefined;
-    private findSequenceMember;
-    private get sequence();
-}
-export declare class x509SubjectKeyIDExtension extends x509Extension {
-    get keyIdentifier(): Buffer;
-}
-export declare class x509SCTExtension extends x509Extension {
-    constructor(asn1: ASN1Obj);
-    get signedCertificateTimestamps(): SignedCertificateTimestamp[];
-}
diff --git a/deps/npm/node_modules/sigstore/dist/x509/sct.d.ts b/deps/npm/node_modules/sigstore/dist/x509/sct.d.ts
deleted file mode 100644
index 076a532984c6b8..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/x509/sct.d.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-/// 
-import * as sigstore from '../types/sigstore';
-interface SCTOptions {
-    version: number;
-    logID: Buffer;
-    timestamp: Buffer;
-    extensions: Buffer;
-    hashAlgorithm: number;
-    signatureAlgorithm: number;
-    signature: Buffer;
-}
-export declare class SignedCertificateTimestamp {
-    readonly version: number;
-    readonly logID: Buffer;
-    readonly timestamp: Buffer;
-    readonly extensions: Buffer;
-    readonly hashAlgorithm: number;
-    readonly signatureAlgorithm: number;
-    readonly signature: Buffer;
-    constructor(options: SCTOptions);
-    get datetime(): Date;
-    get algorithm(): string;
-    verify(preCert: Buffer, logs: sigstore.TransparencyLogInstance[]): boolean;
-    static parse(buf: Buffer): SignedCertificateTimestamp;
-}
-export {};
diff --git a/deps/npm/node_modules/sigstore/dist/x509/verify.d.ts b/deps/npm/node_modules/sigstore/dist/x509/verify.d.ts
deleted file mode 100644
index b12594adb2ea88..00000000000000
--- a/deps/npm/node_modules/sigstore/dist/x509/verify.d.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { x509Certificate } from './cert';
-interface VerifyCertificateChainOptions {
-    trustedCerts: x509Certificate[];
-    untrustedCert: x509Certificate;
-    validAt?: Date;
-}
-export declare function verifyCertificateChain(opts: VerifyCertificateChainOptions): x509Certificate[];
-export {};
diff --git a/deps/npm/node_modules/sigstore/package.json b/deps/npm/node_modules/sigstore/package.json
index 02655a6c79bc81..daf50ba601884c 100644
--- a/deps/npm/node_modules/sigstore/package.json
+++ b/deps/npm/node_modules/sigstore/package.json
@@ -1,6 +1,6 @@
 {
   "name": "sigstore",
-  "version": "1.7.0",
+  "version": "2.1.0",
   "description": "code-signing for npm packages",
   "main": "dist/index.js",
   "types": "dist/index.d.ts",
@@ -9,9 +9,6 @@
     "build": "tsc --build",
     "test": "jest"
   },
-  "bin": {
-    "sigstore": "bin/sigstore.js"
-  },
   "files": [
     "dist",
     "store"
@@ -30,17 +27,19 @@
     "provenance": true
   },
   "devDependencies": {
-    "@sigstore/rekor-types": "^1.0.0",
+    "@sigstore/rekor-types": "^2.0.0",
     "@sigstore/jest": "^0.0.0",
-    "@tufjs/repo-mock": "^1.1.0",
+    "@sigstore/mock": "^0.4.0",
+    "@tufjs/repo-mock": "^2.0.0",
     "@types/make-fetch-happen": "^10.0.0"
   },
   "dependencies": {
-    "@sigstore/protobuf-specs": "^0.1.0",
-    "@sigstore/tuf": "^1.0.1",
-    "make-fetch-happen": "^11.0.1"
+    "@sigstore/bundle": "^2.1.0",
+    "@sigstore/protobuf-specs": "^0.2.1",
+    "@sigstore/sign": "^2.1.0",
+    "@sigstore/tuf": "^2.1.0"
   },
   "engines": {
-    "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+    "node": "^16.14.0 || >=18.0.0"
   }
 }
diff --git a/deps/npm/node_modules/socks-proxy-agent/dist/index.js b/deps/npm/node_modules/socks-proxy-agent/dist/index.js
deleted file mode 100644
index 55b598b7f5ca73..00000000000000
--- a/deps/npm/node_modules/socks-proxy-agent/dist/index.js
+++ /dev/null
@@ -1,197 +0,0 @@
-"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());
-    });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
-    return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.SocksProxyAgent = void 0;
-const socks_1 = require("socks");
-const agent_base_1 = require("agent-base");
-const debug_1 = __importDefault(require("debug"));
-const dns_1 = __importDefault(require("dns"));
-const tls_1 = __importDefault(require("tls"));
-const debug = (0, debug_1.default)('socks-proxy-agent');
-function parseSocksProxy(opts) {
-    var _a;
-    let port = 0;
-    let lookup = false;
-    let type = 5;
-    const host = opts.hostname;
-    if (host == null) {
-        throw new TypeError('No "host"');
-    }
-    if (typeof opts.port === 'number') {
-        port = opts.port;
-    }
-    else if (typeof opts.port === 'string') {
-        port = parseInt(opts.port, 10);
-    }
-    // From RFC 1928, Section 3: https://tools.ietf.org/html/rfc1928#section-3
-    // "The SOCKS service is conventionally located on TCP port 1080"
-    if (port == null) {
-        port = 1080;
-    }
-    // figure out if we want socks v4 or v5, based on the "protocol" used.
-    // Defaults to 5.
-    if (opts.protocol != null) {
-        switch (opts.protocol.replace(':', '')) {
-            case 'socks4':
-                lookup = true;
-            // pass through
-            case 'socks4a':
-                type = 4;
-                break;
-            case 'socks5':
-                lookup = true;
-            // pass through
-            case 'socks': // no version specified, default to 5h
-            case 'socks5h':
-                type = 5;
-                break;
-            default:
-                throw new TypeError(`A "socks" protocol must be specified! Got: ${String(opts.protocol)}`);
-        }
-    }
-    if (typeof opts.type !== 'undefined') {
-        if (opts.type === 4 || opts.type === 5) {
-            type = opts.type;
-        }
-        else {
-            throw new TypeError(`"type" must be 4 or 5, got: ${String(opts.type)}`);
-        }
-    }
-    const proxy = {
-        host,
-        port,
-        type
-    };
-    let userId = (_a = opts.userId) !== null && _a !== void 0 ? _a : opts.username;
-    let password = opts.password;
-    if (opts.auth != null) {
-        const auth = opts.auth.split(':');
-        userId = auth[0];
-        password = auth[1];
-    }
-    if (userId != null) {
-        Object.defineProperty(proxy, 'userId', {
-            value: userId,
-            enumerable: false
-        });
-    }
-    if (password != null) {
-        Object.defineProperty(proxy, 'password', {
-            value: password,
-            enumerable: false
-        });
-    }
-    return { lookup, proxy };
-}
-const normalizeProxyOptions = (input) => {
-    let proxyOptions;
-    if (typeof input === 'string') {
-        proxyOptions = new URL(input);
-    }
-    else {
-        proxyOptions = input;
-    }
-    if (proxyOptions == null) {
-        throw new TypeError('a SOCKS proxy server `host` and `port` must be specified!');
-    }
-    return proxyOptions;
-};
-class SocksProxyAgent extends agent_base_1.Agent {
-    constructor(input, options) {
-        var _a;
-        const proxyOptions = normalizeProxyOptions(input);
-        super(proxyOptions);
-        const parsedProxy = parseSocksProxy(proxyOptions);
-        this.shouldLookup = parsedProxy.lookup;
-        this.proxy = parsedProxy.proxy;
-        this.tlsConnectionOptions = proxyOptions.tls != null ? proxyOptions.tls : {};
-        this.timeout = (_a = options === null || options === void 0 ? void 0 : options.timeout) !== null && _a !== void 0 ? _a : null;
-    }
-    /**
-     * Initiates a SOCKS connection to the specified SOCKS proxy server,
-     * which in turn connects to the specified remote host and port.
-     *
-     * @api protected
-     */
-    callback(req, opts) {
-        var _a;
-        return __awaiter(this, void 0, void 0, function* () {
-            const { shouldLookup, proxy, timeout } = this;
-            let { host, port, lookup: lookupCallback } = opts;
-            if (host == null) {
-                throw new Error('No `host` defined!');
-            }
-            if (shouldLookup) {
-                // Client-side DNS resolution for "4" and "5" socks proxy versions.
-                host = yield new Promise((resolve, reject) => {
-                    // Use the request's custom lookup, if one was configured:
-                    const lookupFn = lookupCallback !== null && lookupCallback !== void 0 ? lookupCallback : dns_1.default.lookup;
-                    lookupFn(host, {}, (err, res) => {
-                        if (err) {
-                            reject(err);
-                        }
-                        else {
-                            resolve(res);
-                        }
-                    });
-                });
-            }
-            const socksOpts = {
-                proxy,
-                destination: { host, port },
-                command: 'connect',
-                timeout: timeout !== null && timeout !== void 0 ? timeout : undefined
-            };
-            const cleanup = (tlsSocket) => {
-                req.destroy();
-                socket.destroy();
-                if (tlsSocket)
-                    tlsSocket.destroy();
-            };
-            debug('Creating socks proxy connection: %o', socksOpts);
-            const { socket } = yield socks_1.SocksClient.createConnection(socksOpts);
-            debug('Successfully created socks proxy connection');
-            if (timeout !== null) {
-                socket.setTimeout(timeout);
-                socket.on('timeout', () => cleanup());
-            }
-            if (opts.secureEndpoint) {
-                // The proxy is connecting to a TLS server, so upgrade
-                // this socket connection to a TLS connection.
-                debug('Upgrading socket connection to TLS');
-                const servername = (_a = opts.servername) !== null && _a !== void 0 ? _a : opts.host;
-                const tlsSocket = tls_1.default.connect(Object.assign(Object.assign(Object.assign({}, omit(opts, 'host', 'hostname', 'path', 'port')), { socket,
-                    servername }), this.tlsConnectionOptions));
-                tlsSocket.once('error', (error) => {
-                    debug('socket TLS error', error.message);
-                    cleanup(tlsSocket);
-                });
-                return tlsSocket;
-            }
-            return socket;
-        });
-    }
-}
-exports.SocksProxyAgent = SocksProxyAgent;
-function omit(obj, ...keys) {
-    const ret = {};
-    let key;
-    for (key in obj) {
-        if (!keys.includes(key)) {
-            ret[key] = obj[key];
-        }
-    }
-    return ret;
-}
-//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/deps/npm/node_modules/socks-proxy-agent/package.json b/deps/npm/node_modules/socks-proxy-agent/package.json
deleted file mode 100644
index aa2999969c1743..00000000000000
--- a/deps/npm/node_modules/socks-proxy-agent/package.json
+++ /dev/null
@@ -1,181 +0,0 @@
-{
-  "name": "socks-proxy-agent",
-  "description": "A SOCKS proxy `http.Agent` implementation for HTTP and HTTPS",
-  "homepage": "https://github.com/TooTallNate/node-socks-proxy-agent#readme",
-  "version": "7.0.0",
-  "main": "dist/index.js",
-  "author": {
-    "email": "nathan@tootallnate.net",
-    "name": "Nathan Rajlich",
-    "url": "http://n8.io/"
-  },
-  "contributors": [
-    {
-      "name": "Kiko Beats",
-      "email": "josefrancisco.verdu@gmail.com"
-    },
-    {
-      "name": "Josh Glazebrook",
-      "email": "josh@joshglazebrook.com"
-    },
-    {
-      "name": "talmobi",
-      "email": "talmobi@users.noreply.github.com"
-    },
-    {
-      "name": "Indospace.io",
-      "email": "justin@indospace.io"
-    },
-    {
-      "name": "Kilian von Pflugk",
-      "email": "github@jumoog.io"
-    },
-    {
-      "name": "Kyle",
-      "email": "admin@hk1229.cn"
-    },
-    {
-      "name": "Matheus Fernandes",
-      "email": "matheus.frndes@gmail.com"
-    },
-    {
-      "name": "Ricky Miller",
-      "email": "richardkazuomiller@gmail.com"
-    },
-    {
-      "name": "Shantanu Sharma",
-      "email": "shantanu34@outlook.com"
-    },
-    {
-      "name": "Tim Perry",
-      "email": "pimterry@gmail.com"
-    },
-    {
-      "name": "Vadim Baryshev",
-      "email": "vadimbaryshev@gmail.com"
-    },
-    {
-      "name": "jigu",
-      "email": "luo1257857309@gmail.com"
-    },
-    {
-      "name": "Alba Mendez",
-      "email": "me@jmendeth.com"
-    },
-    {
-      "name": "Дмитрий Гуденков",
-      "email": "Dimangud@rambler.ru"
-    },
-    {
-      "name": "Andrei Bitca",
-      "email": "63638922+andrei-bitca-dc@users.noreply.github.com"
-    },
-    {
-      "name": "Andrew Casey",
-      "email": "amcasey@users.noreply.github.com"
-    },
-    {
-      "name": "Brandon Ros",
-      "email": "brandonros1@gmail.com"
-    },
-    {
-      "name": "Dang Duy Thanh",
-      "email": "thanhdd.it@gmail.com"
-    },
-    {
-      "name": "Dimitar Nestorov",
-      "email": "8790386+dimitarnestorov@users.noreply.github.com"
-    }
-  ],
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/TooTallNate/node-socks-proxy-agent.git"
-  },
-  "bugs": {
-    "url": "https://github.com/TooTallNate/node-socks-proxy-agent/issues"
-  },
-  "keywords": [
-    "agent",
-    "http",
-    "https",
-    "proxy",
-    "socks",
-    "socks4",
-    "socks4a",
-    "socks5",
-    "socks5h"
-  ],
-  "dependencies": {
-    "agent-base": "^6.0.2",
-    "debug": "^4.3.3",
-    "socks": "^2.6.2"
-  },
-  "devDependencies": {
-    "@commitlint/cli": "latest",
-    "@commitlint/config-conventional": "latest",
-    "@types/debug": "latest",
-    "@types/node": "latest",
-    "cacheable-lookup": "latest",
-    "conventional-github-releaser": "latest",
-    "dns2": "latest",
-    "finepack": "latest",
-    "git-authors-cli": "latest",
-    "mocha": "9",
-    "nano-staged": "latest",
-    "npm-check-updates": "latest",
-    "prettier-standard": "latest",
-    "raw-body": "latest",
-    "rimraf": "latest",
-    "simple-git-hooks": "latest",
-    "socksv5": "github:TooTallNate/socksv5#fix/dstSock-close-event",
-    "standard": "latest",
-    "standard-markdown": "latest",
-    "standard-version": "latest",
-    "ts-standard": "latest",
-    "typescript": "latest"
-  },
-  "engines": {
-    "node": ">= 10"
-  },
-  "files": [
-    "dist"
-  ],
-  "scripts": {
-    "build": "tsc",
-    "clean": "rimraf node_modules",
-    "contributors": "(git-authors-cli && finepack && git add package.json && git commit -m 'build: contributors' --no-verify) || true",
-    "lint": "ts-standard",
-    "postrelease": "npm run release:tags && npm run release:github && (ci-publish || npm publish --access=public)",
-    "prebuild": "rimraf dist",
-    "prepublishOnly": "npm run build",
-    "prerelease": "npm run update:check && npm run contributors",
-    "release": "standard-version -a",
-    "release:github": "conventional-github-releaser -p angular",
-    "release:tags": "git push --follow-tags origin HEAD:master",
-    "test": "mocha --reporter spec",
-    "update": "ncu -u",
-    "update:check": "ncu -- --error-level 2"
-  },
-  "license": "MIT",
-  "commitlint": {
-    "extends": [
-      "@commitlint/config-conventional"
-    ]
-  },
-  "nano-staged": {
-    "*.js": [
-      "prettier-standard"
-    ],
-    "*.md": [
-      "standard-markdown"
-    ],
-    "package.json": [
-      "finepack"
-    ]
-  },
-  "simple-git-hooks": {
-    "commit-msg": "npx commitlint --edit",
-    "pre-commit": "npx nano-staged"
-  },
-  "typings": "dist/index.d.ts"
-}
diff --git a/deps/npm/node_modules/spdx-license-ids/deprecated.json b/deps/npm/node_modules/spdx-license-ids/deprecated.json
index 278531e40c613d..a877dc3efd8bd2 100644
--- a/deps/npm/node_modules/spdx-license-ids/deprecated.json
+++ b/deps/npm/node_modules/spdx-license-ids/deprecated.json
@@ -7,18 +7,24 @@
 	"GFDL-1.2",
 	"GFDL-1.3",
 	"GPL-1.0",
+	"GPL-1.0+",
 	"GPL-2.0",
+	"GPL-2.0+",
 	"GPL-2.0-with-GCC-exception",
 	"GPL-2.0-with-autoconf-exception",
 	"GPL-2.0-with-bison-exception",
 	"GPL-2.0-with-classpath-exception",
 	"GPL-2.0-with-font-exception",
 	"GPL-3.0",
+	"GPL-3.0+",
 	"GPL-3.0-with-GCC-exception",
 	"GPL-3.0-with-autoconf-exception",
 	"LGPL-2.0",
+	"LGPL-2.0+",
 	"LGPL-2.1",
+	"LGPL-2.1+",
 	"LGPL-3.0",
+	"LGPL-3.0+",
 	"Nunit",
 	"StandardML-NJ",
 	"bzip2-1.0.5",
diff --git a/deps/npm/node_modules/spdx-license-ids/index.json b/deps/npm/node_modules/spdx-license-ids/index.json
index 04c03126d98eb8..a7b98b24b6273e 100644
--- a/deps/npm/node_modules/spdx-license-ids/index.json
+++ b/deps/npm/node_modules/spdx-license-ids/index.json
@@ -22,10 +22,13 @@
 	"APSL-1.1",
 	"APSL-1.2",
 	"APSL-2.0",
+	"ASWF-Digital-Assets-1.0",
+	"ASWF-Digital-Assets-1.1",
 	"Abstyles",
 	"AdaCore-doc",
 	"Adobe-2006",
 	"Adobe-Glyph",
+	"Adobe-Utopia",
 	"Afmparse",
 	"Aladdin",
 	"Apache-1.0",
@@ -44,6 +47,7 @@
 	"BSD-3-Clause",
 	"BSD-3-Clause-Attribution",
 	"BSD-3-Clause-Clear",
+	"BSD-3-Clause-HP",
 	"BSD-3-Clause-LBNL",
 	"BSD-3-Clause-Modification",
 	"BSD-3-Clause-No-Military-License",
@@ -51,6 +55,8 @@
 	"BSD-3-Clause-No-Nuclear-License-2014",
 	"BSD-3-Clause-No-Nuclear-Warranty",
 	"BSD-3-Clause-Open-MPI",
+	"BSD-3-Clause-Sun",
+	"BSD-3-Clause-flex",
 	"BSD-4-Clause",
 	"BSD-4-Clause-Shortened",
 	"BSD-4-Clause-UC",
@@ -58,8 +64,10 @@
 	"BSD-4.3TAHOE",
 	"BSD-Advertising-Acknowledgement",
 	"BSD-Attribution-HPND-disclaimer",
+	"BSD-Inferno-Nettverk",
 	"BSD-Protection",
 	"BSD-Source-Code",
+	"BSD-Systemics",
 	"BSL-1.0",
 	"BUSL-1.1",
 	"Baekmuk",
@@ -71,6 +79,7 @@
 	"Bitstream-Charter",
 	"Bitstream-Vera",
 	"BlueOak-1.0.0",
+	"Boehm-GC",
 	"Borceux",
 	"Brian-Gladman-3-Clause",
 	"C-UDA-1.0",
@@ -125,6 +134,7 @@
 	"CC-BY-SA-3.0",
 	"CC-BY-SA-3.0-AT",
 	"CC-BY-SA-3.0-DE",
+	"CC-BY-SA-3.0-IGO",
 	"CC-BY-SA-4.0",
 	"CC-PDDC",
 	"CC0-1.0",
@@ -161,11 +171,13 @@
 	"Community-Spec-1.0",
 	"Condor-1.1",
 	"Cornell-Lossless-JPEG",
+	"Cronyx",
 	"Crossword",
 	"CrystalStacker",
 	"Cube",
 	"D-FSL-1.0",
 	"DL-DE-BY-2.0",
+	"DL-DE-ZERO-2.0",
 	"DOC",
 	"DRL-1.0",
 	"DSDP",
@@ -185,6 +197,7 @@
 	"Entessa",
 	"ErlPL-1.1",
 	"Eurosym",
+	"FBM",
 	"FDK-AAC",
 	"FSFAP",
 	"FSFUL",
@@ -192,9 +205,11 @@
 	"FSFULLRWD",
 	"FTL",
 	"Fair",
+	"Ferguson-Twofish",
 	"Frameworx-1.0",
 	"FreeBSD-DOC",
 	"FreeImage",
+	"Furuseth",
 	"GD",
 	"GFDL-1.1-invariants-only",
 	"GFDL-1.1-invariants-or-later",
@@ -227,9 +242,17 @@
 	"Glulxe",
 	"Graphics-Gems",
 	"HP-1986",
+	"HP-1989",
 	"HPND",
+	"HPND-DEC",
 	"HPND-Markus-Kuhn",
+	"HPND-Pbmplus",
+	"HPND-UC",
+	"HPND-doc",
+	"HPND-doc-sell",
 	"HPND-export-US",
+	"HPND-export-US-modify",
+	"HPND-sell-regexpr",
 	"HPND-sell-variant",
 	"HPND-sell-variant-MIT-disclaimer",
 	"HTMLTIDY",
@@ -246,6 +269,7 @@
 	"ImageMagick",
 	"Imlib2",
 	"Info-ZIP",
+	"Inner-Net-2.0",
 	"Intel",
 	"Intel-ACPI",
 	"Interbase-1.0",
@@ -254,6 +278,7 @@
 	"JSON",
 	"Jam",
 	"JasPer-2.0",
+	"Kastrup",
 	"Kazlib",
 	"Knuth-CTAN",
 	"LAL-1.2",
@@ -276,23 +301,32 @@
 	"LZMA-SDK-9.11-to-9.20",
 	"LZMA-SDK-9.22",
 	"Latex2e",
+	"Latex2e-translated-notice",
 	"Leptonica",
 	"LiLiQ-P-1.1",
 	"LiLiQ-R-1.1",
 	"LiLiQ-Rplus-1.1",
 	"Libpng",
 	"Linux-OpenIB",
+	"Linux-man-pages-1-para",
 	"Linux-man-pages-copyleft",
+	"Linux-man-pages-copyleft-2-para",
+	"Linux-man-pages-copyleft-var",
+	"Lucida-Bitmap-Fonts",
 	"MIT",
 	"MIT-0",
 	"MIT-CMU",
+	"MIT-Festival",
 	"MIT-Modern-Variant",
 	"MIT-Wu",
 	"MIT-advertising",
 	"MIT-enna",
 	"MIT-feh",
 	"MIT-open-group",
+	"MIT-testregex",
 	"MITNFA",
+	"MMIXware",
+	"MPEG-SSG",
 	"MPL-1.0",
 	"MPL-1.1",
 	"MPL-2.0",
@@ -303,6 +337,7 @@
 	"MTLL",
 	"MakeIndex",
 	"Martin-Birgmeier",
+	"McPhee-slideshow",
 	"Minpack",
 	"MirOS",
 	"Motosoto",
@@ -319,6 +354,7 @@
 	"NICTA-1.0",
 	"NIST-PD",
 	"NIST-PD-fallback",
+	"NIST-Software",
 	"NLOD-1.0",
 	"NLOD-2.0",
 	"NLPL",
@@ -370,8 +406,10 @@
 	"OLDAP-2.6",
 	"OLDAP-2.7",
 	"OLDAP-2.8",
+	"OLFL-1.3",
 	"OML",
 	"OPL-1.0",
+	"OPL-UK-3.0",
 	"OPUBL-1.0",
 	"OSET-PL-2.1",
 	"OSL-1.0",
@@ -381,6 +419,7 @@
 	"OSL-3.0",
 	"OpenPBS-2.3",
 	"OpenSSL",
+	"PADL",
 	"PDDL-1.0",
 	"PHP-3.0",
 	"PHP-3.01",
@@ -409,10 +448,13 @@
 	"SGI-B-1.0",
 	"SGI-B-1.1",
 	"SGI-B-2.0",
+	"SGI-OpenGL",
+	"SGP4",
 	"SHL-0.5",
 	"SHL-0.51",
 	"SISSL",
 	"SISSL-1.2",
+	"SL",
 	"SMLNJ",
 	"SMPPL",
 	"SNIA",
@@ -427,6 +469,7 @@
 	"Sendmail-8.23",
 	"SimPL-2.0",
 	"Sleepycat",
+	"Soundex",
 	"Spencer-86",
 	"Spencer-94",
 	"Spencer-99",
@@ -442,14 +485,18 @@
 	"TPDL",
 	"TPL-1.0",
 	"TTWL",
+	"TTYP0",
 	"TU-Berlin-1.0",
 	"TU-Berlin-2.0",
+	"TermReadKey",
 	"UCAR",
 	"UCL-1.0",
 	"UPL-1.0",
+	"URT-RLE",
 	"Unicode-DFS-2015",
 	"Unicode-DFS-2016",
 	"Unicode-TOU",
+	"UnixCrypt",
 	"Unlicense",
 	"VOSTROM",
 	"VSL-1.0",
@@ -459,12 +506,15 @@
 	"W3C-20150513",
 	"WTFPL",
 	"Watcom-1.0",
+	"Widget-Workshop",
 	"Wsuipa",
 	"X11",
 	"X11-distribute-modifications-variant",
 	"XFree86-1.1",
 	"XSkat",
+	"Xdebug-1.03",
 	"Xerox",
+	"Xfig",
 	"Xnet",
 	"YPL-1.0",
 	"YPL-1.1",
@@ -472,20 +522,24 @@
 	"ZPL-2.0",
 	"ZPL-2.1",
 	"Zed",
+	"Zeeff",
 	"Zend-2.0",
 	"Zimbra-1.3",
 	"Zimbra-1.4",
 	"Zlib",
 	"blessing",
 	"bzip2-1.0.6",
+	"check-cvs",
 	"checkmk",
 	"copyleft-next-0.3.0",
 	"copyleft-next-0.3.1",
 	"curl",
 	"diffmark",
+	"dtoa",
 	"dvipdfm",
 	"eGenix",
 	"etalab-2.0",
+	"fwlw",
 	"gSOAP-1.3b",
 	"gnuplot",
 	"iMatix",
@@ -493,12 +547,20 @@
 	"libselinux-1.0",
 	"libtiff",
 	"libutil-David-Nugent",
+	"lsof",
+	"magaz",
+	"metamail",
 	"mpi-permissive",
 	"mpich2",
 	"mplus",
+	"pnmstitch",
 	"psfrag",
 	"psutils",
+	"python-ldap",
 	"snprintf",
+	"ssh-keyscan",
+	"swrule",
+	"ulem",
 	"w3m",
 	"xinetd",
 	"xlock",
diff --git a/deps/npm/node_modules/spdx-license-ids/package.json b/deps/npm/node_modules/spdx-license-ids/package.json
index ea060776d9cf76..196b02705769a9 100644
--- a/deps/npm/node_modules/spdx-license-ids/package.json
+++ b/deps/npm/node_modules/spdx-license-ids/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "spdx-license-ids",
-	"version": "3.0.13",
+	"version": "3.0.16",
 	"description": "A list of SPDX license identifiers",
 	"repository": "jslicense/spdx-license-ids",
 	"author": "Shinnosuke Watanabe (https://github.com/shinnn)",
@@ -28,10 +28,10 @@
 	],
 	"devDependencies": {
 		"@shinnn/eslint-config": "^7.0.0",
-		"eslint": "^8.2.0",
+		"eslint": "^8.49.0",
 		"eslint-formatter-codeframe": "^7.32.1",
 		"rmfr": "^2.0.0",
-		"tape": "^5.3.1"
+		"tape": "^5.6.6"
 	},
 	"eslintConfig": {
 		"extends": "@shinnn"
diff --git a/deps/npm/node_modules/ssri/package.json b/deps/npm/node_modules/ssri/package.json
index 815c7f3ed03ae9..8750bd744d28bd 100644
--- a/deps/npm/node_modules/ssri/package.json
+++ b/deps/npm/node_modules/ssri/package.json
@@ -1,6 +1,6 @@
 {
   "name": "ssri",
-  "version": "10.0.4",
+  "version": "10.0.5",
   "description": "Standard Subresource Integrity library -- parses, serializes, generates, and verifies integrity metadata according to the SRI spec.",
   "main": "lib/index.js",
   "files": [
@@ -47,11 +47,11 @@
   "author": "GitHub Inc.",
   "license": "ISC",
   "dependencies": {
-    "minipass": "^5.0.0"
+    "minipass": "^7.0.3"
   },
   "devDependencies": {
     "@npmcli/eslint-config": "^4.0.0",
-    "@npmcli/template-oss": "4.14.1",
+    "@npmcli/template-oss": "4.18.0",
     "tap": "^16.0.1"
   },
   "engines": {
@@ -59,7 +59,7 @@
   },
   "templateOSS": {
     "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
-    "version": "4.14.1",
+    "version": "4.18.0",
     "publish": "true"
   }
 }
diff --git a/deps/npm/node_modules/tar/lib/pack.js b/deps/npm/node_modules/tar/lib/pack.js
index 938ece8e731458..d533a068f579f7 100644
--- a/deps/npm/node_modules/tar/lib/pack.js
+++ b/deps/npm/node_modules/tar/lib/pack.js
@@ -79,14 +79,26 @@ const Pack = warner(class Pack extends Minipass {
 
     this.portable = !!opt.portable
     this.zip = null
-    if (opt.gzip) {
-      if (typeof opt.gzip !== 'object') {
-        opt.gzip = {}
+
+    if (opt.gzip || opt.brotli) {
+      if (opt.gzip && opt.brotli) {
+        throw new TypeError('gzip and brotli are mutually exclusive')
       }
-      if (this.portable) {
-        opt.gzip.portable = true
+      if (opt.gzip) {
+        if (typeof opt.gzip !== 'object') {
+          opt.gzip = {}
+        }
+        if (this.portable) {
+          opt.gzip.portable = true
+        }
+        this.zip = new zlib.Gzip(opt.gzip)
+      }
+      if (opt.brotli) {
+        if (typeof opt.brotli !== 'object') {
+          opt.brotli = {}
+        }
+        this.zip = new zlib.BrotliCompress(opt.brotli)
       }
-      this.zip = new zlib.Gzip(opt.gzip)
       this.zip.on('data', chunk => super.write(chunk))
       this.zip.on('end', _ => super.end())
       this.zip.on('drain', _ => this[ONDRAIN]())
diff --git a/deps/npm/node_modules/tar/lib/parse.js b/deps/npm/node_modules/tar/lib/parse.js
index 4b85915cbe01ee..94e53042fad560 100644
--- a/deps/npm/node_modules/tar/lib/parse.js
+++ b/deps/npm/node_modules/tar/lib/parse.js
@@ -97,6 +97,16 @@ module.exports = warner(class Parser extends EE {
     this.strict = !!opt.strict
     this.maxMetaEntrySize = opt.maxMetaEntrySize || maxMetaEntrySize
     this.filter = typeof opt.filter === 'function' ? opt.filter : noop
+    // Unlike gzip, brotli doesn't have any magic bytes to identify it
+    // Users need to explicitly tell us they're extracting a brotli file
+    // Or we infer from the file extension
+    const isTBR = (opt.file && (
+        opt.file.endsWith('.tar.br') || opt.file.endsWith('.tbr')))
+    // if it's a tbr file it MIGHT be brotli, but we don't know until
+    // we look at it and verify it's not a valid tar file.
+    this.brotli = !opt.gzip && opt.brotli !== undefined ? opt.brotli
+      : isTBR ? undefined
+      : false
 
     // have to set this so that streams are ok piping into it
     this.writable = true
@@ -347,7 +357,9 @@ module.exports = warner(class Parser extends EE {
     }
 
     // first write, might be gzipped
-    if (this[UNZIP] === null && chunk) {
+    const needSniff = this[UNZIP] === null ||
+      this.brotli === undefined && this[UNZIP] === false
+    if (needSniff && chunk) {
       if (this[BUFFER]) {
         chunk = Buffer.concat([this[BUFFER], chunk])
         this[BUFFER] = null
@@ -356,15 +368,45 @@ module.exports = warner(class Parser extends EE {
         this[BUFFER] = chunk
         return true
       }
+
+      // look for gzip header
       for (let i = 0; this[UNZIP] === null && i < gzipHeader.length; i++) {
         if (chunk[i] !== gzipHeader[i]) {
           this[UNZIP] = false
         }
       }
-      if (this[UNZIP] === null) {
+
+      const maybeBrotli = this.brotli === undefined
+      if (this[UNZIP] === false && maybeBrotli) {
+        // read the first header to see if it's a valid tar file. If so,
+        // we can safely assume that it's not actually brotli, despite the
+        // .tbr or .tar.br file extension.
+        // if we ended before getting a full chunk, yes, def brotli
+        if (chunk.length < 512) {
+          if (this[ENDED]) {
+            this.brotli = true
+          } else {
+            this[BUFFER] = chunk
+            return true
+          }
+        } else {
+          // if it's tar, it's pretty reliably not brotli, chances of
+          // that happening are astronomical.
+          try {
+            new Header(chunk.slice(0, 512))
+            this.brotli = false
+          } catch (_) {
+            this.brotli = true
+          }
+        }
+      }
+
+      if (this[UNZIP] === null || (this[UNZIP] === false && this.brotli)) {
         const ended = this[ENDED]
         this[ENDED] = false
-        this[UNZIP] = new zlib.Unzip()
+        this[UNZIP] = this[UNZIP] === null
+          ? new zlib.Unzip()
+          : new zlib.BrotliDecompress()
         this[UNZIP].on('data', chunk => this[CONSUMECHUNK](chunk))
         this[UNZIP].on('error', er => this.abort(er))
         this[UNZIP].on('end', _ => {
@@ -502,6 +544,7 @@ module.exports = warner(class Parser extends EE {
         this[UNZIP].end(chunk)
       } else {
         this[ENDED] = true
+        if (this.brotli === undefined) chunk = chunk || Buffer.alloc(0)
         this.write(chunk)
       }
     }
diff --git a/deps/npm/node_modules/tar/lib/replace.js b/deps/npm/node_modules/tar/lib/replace.js
index c6e619be6f0326..8db6800bdf4644 100644
--- a/deps/npm/node_modules/tar/lib/replace.js
+++ b/deps/npm/node_modules/tar/lib/replace.js
@@ -23,7 +23,7 @@ module.exports = (opt_, files, cb) => {
     throw new TypeError('file is required')
   }
 
-  if (opt.gzip) {
+  if (opt.gzip || opt.brotli || opt.file.endsWith('.br') || opt.file.endsWith('.tbr')) {
     throw new TypeError('cannot append to compressed archives')
   }
 
diff --git a/deps/npm/node_modules/tar/lib/update.js b/deps/npm/node_modules/tar/lib/update.js
index ded977dc1dec0f..4d328543b315e4 100644
--- a/deps/npm/node_modules/tar/lib/update.js
+++ b/deps/npm/node_modules/tar/lib/update.js
@@ -13,7 +13,7 @@ module.exports = (opt_, files, cb) => {
     throw new TypeError('file is required')
   }
 
-  if (opt.gzip) {
+  if (opt.gzip || opt.brotli || opt.file.endsWith('.br') || opt.file.endsWith('.tbr')) {
     throw new TypeError('cannot append to compressed archives')
   }
 
diff --git a/deps/npm/node_modules/tar/node_modules/minipass/LICENSE b/deps/npm/node_modules/tar/node_modules/minipass/LICENSE
new file mode 100644
index 00000000000000..97f8e32ed82e4c
--- /dev/null
+++ b/deps/npm/node_modules/tar/node_modules/minipass/LICENSE
@@ -0,0 +1,15 @@
+The ISC License
+
+Copyright (c) 2017-2023 npm, Inc., Isaac Z. Schlueter, and Contributors
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/deps/npm/node_modules/minipass/index.js b/deps/npm/node_modules/tar/node_modules/minipass/index.js
similarity index 100%
rename from deps/npm/node_modules/minipass/index.js
rename to deps/npm/node_modules/tar/node_modules/minipass/index.js
diff --git a/deps/npm/node_modules/tar/node_modules/minipass/index.mjs b/deps/npm/node_modules/tar/node_modules/minipass/index.mjs
new file mode 100644
index 00000000000000..89b3fbf1a4d445
--- /dev/null
+++ b/deps/npm/node_modules/tar/node_modules/minipass/index.mjs
@@ -0,0 +1,700 @@
+'use strict'
+const proc =
+  typeof process === 'object' && process
+    ? process
+    : {
+        stdout: null,
+        stderr: null,
+      }
+import EE from 'events'
+import Stream from 'stream'
+import stringdecoder from 'string_decoder'
+const SD = stringdecoder.StringDecoder
+
+const EOF = Symbol('EOF')
+const MAYBE_EMIT_END = Symbol('maybeEmitEnd')
+const EMITTED_END = Symbol('emittedEnd')
+const EMITTING_END = Symbol('emittingEnd')
+const EMITTED_ERROR = Symbol('emittedError')
+const CLOSED = Symbol('closed')
+const READ = Symbol('read')
+const FLUSH = Symbol('flush')
+const FLUSHCHUNK = Symbol('flushChunk')
+const ENCODING = Symbol('encoding')
+const DECODER = Symbol('decoder')
+const FLOWING = Symbol('flowing')
+const PAUSED = Symbol('paused')
+const RESUME = Symbol('resume')
+const BUFFER = Symbol('buffer')
+const PIPES = Symbol('pipes')
+const BUFFERLENGTH = Symbol('bufferLength')
+const BUFFERPUSH = Symbol('bufferPush')
+const BUFFERSHIFT = Symbol('bufferShift')
+const OBJECTMODE = Symbol('objectMode')
+// internal event when stream is destroyed
+const DESTROYED = Symbol('destroyed')
+// internal event when stream has an error
+const ERROR = Symbol('error')
+const EMITDATA = Symbol('emitData')
+const EMITEND = Symbol('emitEnd')
+const EMITEND2 = Symbol('emitEnd2')
+const ASYNC = Symbol('async')
+const ABORT = Symbol('abort')
+const ABORTED = Symbol('aborted')
+const SIGNAL = Symbol('signal')
+
+const defer = fn => Promise.resolve().then(fn)
+
+// TODO remove when Node v8 support drops
+const doIter = global._MP_NO_ITERATOR_SYMBOLS_ !== '1'
+const ASYNCITERATOR =
+  (doIter && Symbol.asyncIterator) || Symbol('asyncIterator not implemented')
+const ITERATOR =
+  (doIter && Symbol.iterator) || Symbol('iterator not implemented')
+
+// events that mean 'the stream is over'
+// these are treated specially, and re-emitted
+// if they are listened for after emitting.
+const isEndish = ev => ev === 'end' || ev === 'finish' || ev === 'prefinish'
+
+const isArrayBuffer = b =>
+  b instanceof ArrayBuffer ||
+  (typeof b === 'object' &&
+    b.constructor &&
+    b.constructor.name === 'ArrayBuffer' &&
+    b.byteLength >= 0)
+
+const isArrayBufferView = b => !Buffer.isBuffer(b) && ArrayBuffer.isView(b)
+
+class Pipe {
+  constructor(src, dest, opts) {
+    this.src = src
+    this.dest = dest
+    this.opts = opts
+    this.ondrain = () => src[RESUME]()
+    dest.on('drain', this.ondrain)
+  }
+  unpipe() {
+    this.dest.removeListener('drain', this.ondrain)
+  }
+  // istanbul ignore next - only here for the prototype
+  proxyErrors() {}
+  end() {
+    this.unpipe()
+    if (this.opts.end) this.dest.end()
+  }
+}
+
+class PipeProxyErrors extends Pipe {
+  unpipe() {
+    this.src.removeListener('error', this.proxyErrors)
+    super.unpipe()
+  }
+  constructor(src, dest, opts) {
+    super(src, dest, opts)
+    this.proxyErrors = er => dest.emit('error', er)
+    src.on('error', this.proxyErrors)
+  }
+}
+
+export class Minipass extends Stream {
+  constructor(options) {
+    super()
+    this[FLOWING] = false
+    // whether we're explicitly paused
+    this[PAUSED] = false
+    this[PIPES] = []
+    this[BUFFER] = []
+    this[OBJECTMODE] = (options && options.objectMode) || false
+    if (this[OBJECTMODE]) this[ENCODING] = null
+    else this[ENCODING] = (options && options.encoding) || null
+    if (this[ENCODING] === 'buffer') this[ENCODING] = null
+    this[ASYNC] = (options && !!options.async) || false
+    this[DECODER] = this[ENCODING] ? new SD(this[ENCODING]) : null
+    this[EOF] = false
+    this[EMITTED_END] = false
+    this[EMITTING_END] = false
+    this[CLOSED] = false
+    this[EMITTED_ERROR] = null
+    this.writable = true
+    this.readable = true
+    this[BUFFERLENGTH] = 0
+    this[DESTROYED] = false
+    if (options && options.debugExposeBuffer === true) {
+      Object.defineProperty(this, 'buffer', { get: () => this[BUFFER] })
+    }
+    if (options && options.debugExposePipes === true) {
+      Object.defineProperty(this, 'pipes', { get: () => this[PIPES] })
+    }
+    this[SIGNAL] = options && options.signal
+    this[ABORTED] = false
+    if (this[SIGNAL]) {
+      this[SIGNAL].addEventListener('abort', () => this[ABORT]())
+      if (this[SIGNAL].aborted) {
+        this[ABORT]()
+      }
+    }
+  }
+
+  get bufferLength() {
+    return this[BUFFERLENGTH]
+  }
+
+  get encoding() {
+    return this[ENCODING]
+  }
+  set encoding(enc) {
+    if (this[OBJECTMODE]) throw new Error('cannot set encoding in objectMode')
+
+    if (
+      this[ENCODING] &&
+      enc !== this[ENCODING] &&
+      ((this[DECODER] && this[DECODER].lastNeed) || this[BUFFERLENGTH])
+    )
+      throw new Error('cannot change encoding')
+
+    if (this[ENCODING] !== enc) {
+      this[DECODER] = enc ? new SD(enc) : null
+      if (this[BUFFER].length)
+        this[BUFFER] = this[BUFFER].map(chunk => this[DECODER].write(chunk))
+    }
+
+    this[ENCODING] = enc
+  }
+
+  setEncoding(enc) {
+    this.encoding = enc
+  }
+
+  get objectMode() {
+    return this[OBJECTMODE]
+  }
+  set objectMode(om) {
+    this[OBJECTMODE] = this[OBJECTMODE] || !!om
+  }
+
+  get ['async']() {
+    return this[ASYNC]
+  }
+  set ['async'](a) {
+    this[ASYNC] = this[ASYNC] || !!a
+  }
+
+  // drop everything and get out of the flow completely
+  [ABORT]() {
+    this[ABORTED] = true
+    this.emit('abort', this[SIGNAL].reason)
+    this.destroy(this[SIGNAL].reason)
+  }
+
+  get aborted() {
+    return this[ABORTED]
+  }
+  set aborted(_) {}
+
+  write(chunk, encoding, cb) {
+    if (this[ABORTED]) return false
+    if (this[EOF]) throw new Error('write after end')
+
+    if (this[DESTROYED]) {
+      this.emit(
+        'error',
+        Object.assign(
+          new Error('Cannot call write after a stream was destroyed'),
+          { code: 'ERR_STREAM_DESTROYED' }
+        )
+      )
+      return true
+    }
+
+    if (typeof encoding === 'function') (cb = encoding), (encoding = 'utf8')
+
+    if (!encoding) encoding = 'utf8'
+
+    const fn = this[ASYNC] ? defer : f => f()
+
+    // convert array buffers and typed array views into buffers
+    // at some point in the future, we may want to do the opposite!
+    // leave strings and buffers as-is
+    // anything else switches us into object mode
+    if (!this[OBJECTMODE] && !Buffer.isBuffer(chunk)) {
+      if (isArrayBufferView(chunk))
+        chunk = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength)
+      else if (isArrayBuffer(chunk)) chunk = Buffer.from(chunk)
+      else if (typeof chunk !== 'string')
+        // use the setter so we throw if we have encoding set
+        this.objectMode = true
+    }
+
+    // handle object mode up front, since it's simpler
+    // this yields better performance, fewer checks later.
+    if (this[OBJECTMODE]) {
+      /* istanbul ignore if - maybe impossible? */
+      if (this.flowing && this[BUFFERLENGTH] !== 0) this[FLUSH](true)
+
+      if (this.flowing) this.emit('data', chunk)
+      else this[BUFFERPUSH](chunk)
+
+      if (this[BUFFERLENGTH] !== 0) this.emit('readable')
+
+      if (cb) fn(cb)
+
+      return this.flowing
+    }
+
+    // at this point the chunk is a buffer or string
+    // don't buffer it up or send it to the decoder
+    if (!chunk.length) {
+      if (this[BUFFERLENGTH] !== 0) this.emit('readable')
+      if (cb) fn(cb)
+      return this.flowing
+    }
+
+    // fast-path writing strings of same encoding to a stream with
+    // an empty buffer, skipping the buffer/decoder dance
+    if (
+      typeof chunk === 'string' &&
+      // unless it is a string already ready for us to use
+      !(encoding === this[ENCODING] && !this[DECODER].lastNeed)
+    ) {
+      chunk = Buffer.from(chunk, encoding)
+    }
+
+    if (Buffer.isBuffer(chunk) && this[ENCODING])
+      chunk = this[DECODER].write(chunk)
+
+    // Note: flushing CAN potentially switch us into not-flowing mode
+    if (this.flowing && this[BUFFERLENGTH] !== 0) this[FLUSH](true)
+
+    if (this.flowing) this.emit('data', chunk)
+    else this[BUFFERPUSH](chunk)
+
+    if (this[BUFFERLENGTH] !== 0) this.emit('readable')
+
+    if (cb) fn(cb)
+
+    return this.flowing
+  }
+
+  read(n) {
+    if (this[DESTROYED]) return null
+
+    if (this[BUFFERLENGTH] === 0 || n === 0 || n > this[BUFFERLENGTH]) {
+      this[MAYBE_EMIT_END]()
+      return null
+    }
+
+    if (this[OBJECTMODE]) n = null
+
+    if (this[BUFFER].length > 1 && !this[OBJECTMODE]) {
+      if (this.encoding) this[BUFFER] = [this[BUFFER].join('')]
+      else this[BUFFER] = [Buffer.concat(this[BUFFER], this[BUFFERLENGTH])]
+    }
+
+    const ret = this[READ](n || null, this[BUFFER][0])
+    this[MAYBE_EMIT_END]()
+    return ret
+  }
+
+  [READ](n, chunk) {
+    if (n === chunk.length || n === null) this[BUFFERSHIFT]()
+    else {
+      this[BUFFER][0] = chunk.slice(n)
+      chunk = chunk.slice(0, n)
+      this[BUFFERLENGTH] -= n
+    }
+
+    this.emit('data', chunk)
+
+    if (!this[BUFFER].length && !this[EOF]) this.emit('drain')
+
+    return chunk
+  }
+
+  end(chunk, encoding, cb) {
+    if (typeof chunk === 'function') (cb = chunk), (chunk = null)
+    if (typeof encoding === 'function') (cb = encoding), (encoding = 'utf8')
+    if (chunk) this.write(chunk, encoding)
+    if (cb) this.once('end', cb)
+    this[EOF] = true
+    this.writable = false
+
+    // if we haven't written anything, then go ahead and emit,
+    // even if we're not reading.
+    // we'll re-emit if a new 'end' listener is added anyway.
+    // This makes MP more suitable to write-only use cases.
+    if (this.flowing || !this[PAUSED]) this[MAYBE_EMIT_END]()
+    return this
+  }
+
+  // don't let the internal resume be overwritten
+  [RESUME]() {
+    if (this[DESTROYED]) return
+
+    this[PAUSED] = false
+    this[FLOWING] = true
+    this.emit('resume')
+    if (this[BUFFER].length) this[FLUSH]()
+    else if (this[EOF]) this[MAYBE_EMIT_END]()
+    else this.emit('drain')
+  }
+
+  resume() {
+    return this[RESUME]()
+  }
+
+  pause() {
+    this[FLOWING] = false
+    this[PAUSED] = true
+  }
+
+  get destroyed() {
+    return this[DESTROYED]
+  }
+
+  get flowing() {
+    return this[FLOWING]
+  }
+
+  get paused() {
+    return this[PAUSED]
+  }
+
+  [BUFFERPUSH](chunk) {
+    if (this[OBJECTMODE]) this[BUFFERLENGTH] += 1
+    else this[BUFFERLENGTH] += chunk.length
+    this[BUFFER].push(chunk)
+  }
+
+  [BUFFERSHIFT]() {
+    if (this[OBJECTMODE]) this[BUFFERLENGTH] -= 1
+    else this[BUFFERLENGTH] -= this[BUFFER][0].length
+    return this[BUFFER].shift()
+  }
+
+  [FLUSH](noDrain) {
+    do {} while (this[FLUSHCHUNK](this[BUFFERSHIFT]()) && this[BUFFER].length)
+
+    if (!noDrain && !this[BUFFER].length && !this[EOF]) this.emit('drain')
+  }
+
+  [FLUSHCHUNK](chunk) {
+    this.emit('data', chunk)
+    return this.flowing
+  }
+
+  pipe(dest, opts) {
+    if (this[DESTROYED]) return
+
+    const ended = this[EMITTED_END]
+    opts = opts || {}
+    if (dest === proc.stdout || dest === proc.stderr) opts.end = false
+    else opts.end = opts.end !== false
+    opts.proxyErrors = !!opts.proxyErrors
+
+    // piping an ended stream ends immediately
+    if (ended) {
+      if (opts.end) dest.end()
+    } else {
+      this[PIPES].push(
+        !opts.proxyErrors
+          ? new Pipe(this, dest, opts)
+          : new PipeProxyErrors(this, dest, opts)
+      )
+      if (this[ASYNC]) defer(() => this[RESUME]())
+      else this[RESUME]()
+    }
+
+    return dest
+  }
+
+  unpipe(dest) {
+    const p = this[PIPES].find(p => p.dest === dest)
+    if (p) {
+      this[PIPES].splice(this[PIPES].indexOf(p), 1)
+      p.unpipe()
+    }
+  }
+
+  addListener(ev, fn) {
+    return this.on(ev, fn)
+  }
+
+  on(ev, fn) {
+    const ret = super.on(ev, fn)
+    if (ev === 'data' && !this[PIPES].length && !this.flowing) this[RESUME]()
+    else if (ev === 'readable' && this[BUFFERLENGTH] !== 0)
+      super.emit('readable')
+    else if (isEndish(ev) && this[EMITTED_END]) {
+      super.emit(ev)
+      this.removeAllListeners(ev)
+    } else if (ev === 'error' && this[EMITTED_ERROR]) {
+      if (this[ASYNC]) defer(() => fn.call(this, this[EMITTED_ERROR]))
+      else fn.call(this, this[EMITTED_ERROR])
+    }
+    return ret
+  }
+
+  get emittedEnd() {
+    return this[EMITTED_END]
+  }
+
+  [MAYBE_EMIT_END]() {
+    if (
+      !this[EMITTING_END] &&
+      !this[EMITTED_END] &&
+      !this[DESTROYED] &&
+      this[BUFFER].length === 0 &&
+      this[EOF]
+    ) {
+      this[EMITTING_END] = true
+      this.emit('end')
+      this.emit('prefinish')
+      this.emit('finish')
+      if (this[CLOSED]) this.emit('close')
+      this[EMITTING_END] = false
+    }
+  }
+
+  emit(ev, data, ...extra) {
+    // error and close are only events allowed after calling destroy()
+    if (ev !== 'error' && ev !== 'close' && ev !== DESTROYED && this[DESTROYED])
+      return
+    else if (ev === 'data') {
+      return !this[OBJECTMODE] && !data
+        ? false
+        : this[ASYNC]
+        ? defer(() => this[EMITDATA](data))
+        : this[EMITDATA](data)
+    } else if (ev === 'end') {
+      return this[EMITEND]()
+    } else if (ev === 'close') {
+      this[CLOSED] = true
+      // don't emit close before 'end' and 'finish'
+      if (!this[EMITTED_END] && !this[DESTROYED]) return
+      const ret = super.emit('close')
+      this.removeAllListeners('close')
+      return ret
+    } else if (ev === 'error') {
+      this[EMITTED_ERROR] = data
+      super.emit(ERROR, data)
+      const ret =
+        !this[SIGNAL] || this.listeners('error').length
+          ? super.emit('error', data)
+          : false
+      this[MAYBE_EMIT_END]()
+      return ret
+    } else if (ev === 'resume') {
+      const ret = super.emit('resume')
+      this[MAYBE_EMIT_END]()
+      return ret
+    } else if (ev === 'finish' || ev === 'prefinish') {
+      const ret = super.emit(ev)
+      this.removeAllListeners(ev)
+      return ret
+    }
+
+    // Some other unknown event
+    const ret = super.emit(ev, data, ...extra)
+    this[MAYBE_EMIT_END]()
+    return ret
+  }
+
+  [EMITDATA](data) {
+    for (const p of this[PIPES]) {
+      if (p.dest.write(data) === false) this.pause()
+    }
+    const ret = super.emit('data', data)
+    this[MAYBE_EMIT_END]()
+    return ret
+  }
+
+  [EMITEND]() {
+    if (this[EMITTED_END]) return
+
+    this[EMITTED_END] = true
+    this.readable = false
+    if (this[ASYNC]) defer(() => this[EMITEND2]())
+    else this[EMITEND2]()
+  }
+
+  [EMITEND2]() {
+    if (this[DECODER]) {
+      const data = this[DECODER].end()
+      if (data) {
+        for (const p of this[PIPES]) {
+          p.dest.write(data)
+        }
+        super.emit('data', data)
+      }
+    }
+
+    for (const p of this[PIPES]) {
+      p.end()
+    }
+    const ret = super.emit('end')
+    this.removeAllListeners('end')
+    return ret
+  }
+
+  // const all = await stream.collect()
+  collect() {
+    const buf = []
+    if (!this[OBJECTMODE]) buf.dataLength = 0
+    // set the promise first, in case an error is raised
+    // by triggering the flow here.
+    const p = this.promise()
+    this.on('data', c => {
+      buf.push(c)
+      if (!this[OBJECTMODE]) buf.dataLength += c.length
+    })
+    return p.then(() => buf)
+  }
+
+  // const data = await stream.concat()
+  concat() {
+    return this[OBJECTMODE]
+      ? Promise.reject(new Error('cannot concat in objectMode'))
+      : this.collect().then(buf =>
+          this[OBJECTMODE]
+            ? Promise.reject(new Error('cannot concat in objectMode'))
+            : this[ENCODING]
+            ? buf.join('')
+            : Buffer.concat(buf, buf.dataLength)
+        )
+  }
+
+  // stream.promise().then(() => done, er => emitted error)
+  promise() {
+    return new Promise((resolve, reject) => {
+      this.on(DESTROYED, () => reject(new Error('stream destroyed')))
+      this.on('error', er => reject(er))
+      this.on('end', () => resolve())
+    })
+  }
+
+  // for await (let chunk of stream)
+  [ASYNCITERATOR]() {
+    let stopped = false
+    const stop = () => {
+      this.pause()
+      stopped = true
+      return Promise.resolve({ done: true })
+    }
+    const next = () => {
+      if (stopped) return stop()
+      const res = this.read()
+      if (res !== null) return Promise.resolve({ done: false, value: res })
+
+      if (this[EOF]) return stop()
+
+      let resolve = null
+      let reject = null
+      const onerr = er => {
+        this.removeListener('data', ondata)
+        this.removeListener('end', onend)
+        this.removeListener(DESTROYED, ondestroy)
+        stop()
+        reject(er)
+      }
+      const ondata = value => {
+        this.removeListener('error', onerr)
+        this.removeListener('end', onend)
+        this.removeListener(DESTROYED, ondestroy)
+        this.pause()
+        resolve({ value: value, done: !!this[EOF] })
+      }
+      const onend = () => {
+        this.removeListener('error', onerr)
+        this.removeListener('data', ondata)
+        this.removeListener(DESTROYED, ondestroy)
+        stop()
+        resolve({ done: true })
+      }
+      const ondestroy = () => onerr(new Error('stream destroyed'))
+      return new Promise((res, rej) => {
+        reject = rej
+        resolve = res
+        this.once(DESTROYED, ondestroy)
+        this.once('error', onerr)
+        this.once('end', onend)
+        this.once('data', ondata)
+      })
+    }
+
+    return {
+      next,
+      throw: stop,
+      return: stop,
+      [ASYNCITERATOR]() {
+        return this
+      },
+    }
+  }
+
+  // for (let chunk of stream)
+  [ITERATOR]() {
+    let stopped = false
+    const stop = () => {
+      this.pause()
+      this.removeListener(ERROR, stop)
+      this.removeListener(DESTROYED, stop)
+      this.removeListener('end', stop)
+      stopped = true
+      return { done: true }
+    }
+
+    const next = () => {
+      if (stopped) return stop()
+      const value = this.read()
+      return value === null ? stop() : { value }
+    }
+    this.once('end', stop)
+    this.once(ERROR, stop)
+    this.once(DESTROYED, stop)
+
+    return {
+      next,
+      throw: stop,
+      return: stop,
+      [ITERATOR]() {
+        return this
+      },
+    }
+  }
+
+  destroy(er) {
+    if (this[DESTROYED]) {
+      if (er) this.emit('error', er)
+      else this.emit(DESTROYED)
+      return this
+    }
+
+    this[DESTROYED] = true
+
+    // throw away all buffered data, it's never coming out
+    this[BUFFER].length = 0
+    this[BUFFERLENGTH] = 0
+
+    if (typeof this.close === 'function' && !this[CLOSED]) this.close()
+
+    if (er) this.emit('error', er)
+    // if no error to emit, still reject pending promises
+    else this.emit(DESTROYED)
+
+    return this
+  }
+
+  static isStream(s) {
+    return (
+      !!s &&
+      (s instanceof Minipass ||
+        s instanceof Stream ||
+        (s instanceof EE &&
+          // readable
+          (typeof s.pipe === 'function' ||
+            // writable
+            (typeof s.write === 'function' && typeof s.end === 'function'))))
+    )
+  }
+}
diff --git a/deps/npm/node_modules/tar/node_modules/minipass/package.json b/deps/npm/node_modules/tar/node_modules/minipass/package.json
new file mode 100644
index 00000000000000..0e20e988047f23
--- /dev/null
+++ b/deps/npm/node_modules/tar/node_modules/minipass/package.json
@@ -0,0 +1,76 @@
+{
+  "name": "minipass",
+  "version": "5.0.0",
+  "description": "minimal implementation of a PassThrough stream",
+  "main": "./index.js",
+  "module": "./index.mjs",
+  "types": "./index.d.ts",
+  "exports": {
+    ".": {
+      "import": {
+        "types": "./index.d.ts",
+        "default": "./index.mjs"
+      },
+      "require": {
+        "types": "./index.d.ts",
+        "default": "./index.js"
+      }
+    },
+    "./package.json": "./package.json"
+  },
+  "devDependencies": {
+    "@types/node": "^17.0.41",
+    "end-of-stream": "^1.4.0",
+    "node-abort-controller": "^3.1.1",
+    "prettier": "^2.6.2",
+    "tap": "^16.2.0",
+    "through2": "^2.0.3",
+    "ts-node": "^10.8.1",
+    "typedoc": "^0.23.24",
+    "typescript": "^4.7.3"
+  },
+  "scripts": {
+    "pretest": "npm run prepare",
+    "presnap": "npm run prepare",
+    "prepare": "node ./scripts/transpile-to-esm.js",
+    "snap": "tap",
+    "test": "tap",
+    "preversion": "npm test",
+    "postversion": "npm publish",
+    "postpublish": "git push origin --follow-tags",
+    "typedoc": "typedoc ./index.d.ts",
+    "format": "prettier --write . --loglevel warn"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/isaacs/minipass.git"
+  },
+  "keywords": [
+    "passthrough",
+    "stream"
+  ],
+  "author": "Isaac Z. Schlueter  (http://blog.izs.me/)",
+  "license": "ISC",
+  "files": [
+    "index.d.ts",
+    "index.js",
+    "index.mjs"
+  ],
+  "tap": {
+    "check-coverage": true
+  },
+  "engines": {
+    "node": ">=8"
+  },
+  "prettier": {
+    "semi": false,
+    "printWidth": 80,
+    "tabWidth": 2,
+    "useTabs": false,
+    "singleQuote": true,
+    "jsxSingleQuote": false,
+    "bracketSameLine": true,
+    "arrowParens": "avoid",
+    "endOfLine": "lf"
+  }
+}
diff --git a/deps/npm/node_modules/tar/package.json b/deps/npm/node_modules/tar/package.json
index f59f54ae837bd2..46d91ee1b299cf 100644
--- a/deps/npm/node_modules/tar/package.json
+++ b/deps/npm/node_modules/tar/package.json
@@ -2,20 +2,15 @@
   "author": "GitHub Inc.",
   "name": "tar",
   "description": "tar for node",
-  "version": "6.1.15",
+  "version": "6.2.0",
   "repository": {
     "type": "git",
     "url": "https://github.com/isaacs/node-tar.git"
   },
   "scripts": {
     "genparse": "node scripts/generate-parse-fixtures.js",
-    "template-oss-apply": "template-oss-apply --force",
-    "lint": "eslint \"**/*.js\"",
-    "postlint": "template-oss-check",
-    "lintfix": "npm run lint -- --fix",
     "snap": "tap",
-    "test": "tap",
-    "posttest": "npm run lint"
+    "test": "tap"
   },
   "dependencies": {
     "chownr": "^2.0.0",
diff --git a/deps/npm/node_modules/tuf-js/dist/config.js b/deps/npm/node_modules/tuf-js/dist/config.js
index c2d970e2562449..bafb33a8a1bf7c 100644
--- a/deps/npm/node_modules/tuf-js/dist/config.js
+++ b/deps/npm/node_modules/tuf-js/dist/config.js
@@ -10,5 +10,6 @@ exports.defaultConfig = {
     targetsMaxLength: 5000000,
     prefixTargetsWithHash: true,
     fetchTimeout: 100000,
-    fetchRetries: 2,
+    fetchRetries: undefined,
+    fetchRetry: 2,
 };
diff --git a/deps/npm/node_modules/tuf-js/dist/fetcher.js b/deps/npm/node_modules/tuf-js/dist/fetcher.js
index d3dcf53eeb8697..f966ce1bb0cdc6 100644
--- a/deps/npm/node_modules/tuf-js/dist/fetcher.js
+++ b/deps/npm/node_modules/tuf-js/dist/fetcher.js
@@ -57,13 +57,13 @@ class DefaultFetcher extends BaseFetcher {
     constructor(options = {}) {
         super();
         this.timeout = options.timeout;
-        this.retries = options.retries;
+        this.retry = options.retry;
     }
     async fetch(url) {
         log('GET %s', url);
         const response = await (0, make_fetch_happen_1.default)(url, {
             timeout: this.timeout,
-            retry: this.retries,
+            retry: this.retry,
         });
         if (!response.ok || !response?.body) {
             throw new error_1.DownloadHTTPError('Failed to download', response.status);
diff --git a/deps/npm/node_modules/tuf-js/dist/updater.js b/deps/npm/node_modules/tuf-js/dist/updater.js
index 2aba48d24affd5..2d0c769c7af647 100644
--- a/deps/npm/node_modules/tuf-js/dist/updater.js
+++ b/deps/npm/node_modules/tuf-js/dist/updater.js
@@ -51,7 +51,7 @@ class Updater {
             fetcher ||
                 new fetcher_1.DefaultFetcher({
                     timeout: this.config.fetchTimeout,
-                    retries: this.config.fetchRetries,
+                    retry: this.config.fetchRetries ?? this.config.fetchRetry,
                 });
     }
     // refresh and load the metadata before downloading the target
@@ -306,7 +306,7 @@ class Updater {
         const filePath = encodeURIComponent(targetInfo.path);
         return path.join(this.targetDir, filePath);
     }
-    async persistMetadata(metaDataName, bytesData) {
+    persistMetadata(metaDataName, bytesData) {
         try {
             const filePath = path.join(this.dir, `${metaDataName}.json`);
             log('WRITE %s', filePath);
diff --git a/deps/npm/node_modules/tuf-js/package.json b/deps/npm/node_modules/tuf-js/package.json
index 9187d88083272c..c757d6a00d7008 100644
--- a/deps/npm/node_modules/tuf-js/package.json
+++ b/deps/npm/node_modules/tuf-js/package.json
@@ -1,6 +1,6 @@
 {
   "name": "tuf-js",
-  "version": "1.1.7",
+  "version": "2.1.0",
   "description": "JavaScript implementation of The Update Framework (TUF)",
   "main": "dist/index.js",
   "types": "dist/index.d.ts",
@@ -28,19 +28,16 @@
   },
   "homepage": "https://github.com/theupdateframework/tuf-js/tree/main/packages/client#readme",
   "devDependencies": {
-    "@tufjs/repo-mock": "1.3.1",
+    "@tufjs/repo-mock": "2.0.0",
     "@types/debug": "^4.1.8",
-    "@types/make-fetch-happen": "^10.0.1",
-    "@types/node": "^20.2.5",
-    "nock": "^13.3.1",
-    "typescript": "^5.1.3"
+    "@types/make-fetch-happen": "^10.0.1"
   },
   "dependencies": {
-    "@tufjs/models": "1.0.4",
+    "@tufjs/models": "2.0.0",
     "debug": "^4.3.4",
-    "make-fetch-happen": "^11.1.1"
+    "make-fetch-happen": "^13.0.0"
   },
   "engines": {
-    "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+    "node": "^16.14.0 || >=18.0.0"
   }
 }
diff --git a/deps/npm/node_modules/which/lib/index.js b/deps/npm/node_modules/which/lib/index.js
index 52e9ea62377e74..2fd358baf888fd 100644
--- a/deps/npm/node_modules/which/lib/index.js
+++ b/deps/npm/node_modules/which/lib/index.js
@@ -1,4 +1,4 @@
-const isexe = require('isexe')
+const { isexe, sync: isexeSync } = require('isexe')
 const { join, delimiter, sep, posix } = require('path')
 
 const isWindows = process.platform === 'win32'
@@ -31,11 +31,7 @@ const getPathInfo = (cmd, {
   if (isWindows) {
     const pathExtExe = optPathExt ||
       ['.EXE', '.CMD', '.BAT', '.COM'].join(optDelimiter)
-    const pathExt = pathExtExe.split(optDelimiter).reduce((acc, item) => {
-      acc.push(item)
-      acc.push(item.toLowerCase())
-      return acc
-    }, [])
+    const pathExt = pathExtExe.split(optDelimiter).flatMap((item) => [item, item.toLowerCase()])
     if (cmd.includes('.') && pathExt[0] !== '') {
       pathExt.unshift('')
     }
@@ -90,7 +86,7 @@ const whichSync = (cmd, opt = {}) => {
 
     for (const ext of pathExt) {
       const withExt = p + ext
-      const is = isexe.sync(withExt, { pathExt: pathExtExe, ignoreErrors: true })
+      const is = isexeSync(withExt, { pathExt: pathExtExe, ignoreErrors: true })
       if (is) {
         if (!opt.all) {
           return withExt
diff --git a/deps/npm/node_modules/which/node_modules/isexe/LICENSE b/deps/npm/node_modules/which/node_modules/isexe/LICENSE
new file mode 100644
index 00000000000000..c925dbe826b670
--- /dev/null
+++ b/deps/npm/node_modules/which/node_modules/isexe/LICENSE
@@ -0,0 +1,15 @@
+The ISC License
+
+Copyright (c) 2016-2022 Isaac Z. Schlueter and Contributors
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/deps/npm/node_modules/which/node_modules/isexe/dist/cjs/index.js b/deps/npm/node_modules/which/node_modules/isexe/dist/cjs/index.js
new file mode 100644
index 00000000000000..cefcb66b5c5434
--- /dev/null
+++ b/deps/npm/node_modules/which/node_modules/isexe/dist/cjs/index.js
@@ -0,0 +1,46 @@
+"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 (mod) {
+    if (mod && mod.__esModule) return mod;
+    var result = {};
+    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
+    __setModuleDefault(result, mod);
+    return result;
+};
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.sync = exports.isexe = exports.posix = exports.win32 = void 0;
+const posix = __importStar(require("./posix.js"));
+exports.posix = posix;
+const win32 = __importStar(require("./win32.js"));
+exports.win32 = win32;
+__exportStar(require("./options.js"), exports);
+const platform = process.env._ISEXE_TEST_PLATFORM_ || process.platform;
+const impl = platform === 'win32' ? win32 : posix;
+/**
+ * Determine whether a path is executable on the current platform.
+ */
+exports.isexe = impl.isexe;
+/**
+ * Synchronously determine whether a path is executable on the
+ * current platform.
+ */
+exports.sync = impl.sync;
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/deps/npm/node_modules/which/node_modules/isexe/dist/cjs/options.js b/deps/npm/node_modules/which/node_modules/isexe/dist/cjs/options.js
new file mode 100644
index 00000000000000..0dfad0762cc32c
--- /dev/null
+++ b/deps/npm/node_modules/which/node_modules/isexe/dist/cjs/options.js
@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=options.js.map
\ No newline at end of file
diff --git a/deps/npm/node_modules/path-scurry/node_modules/lru-cache/dist/cjs/package.json b/deps/npm/node_modules/which/node_modules/isexe/dist/cjs/package.json
similarity index 100%
rename from deps/npm/node_modules/path-scurry/node_modules/lru-cache/dist/cjs/package.json
rename to deps/npm/node_modules/which/node_modules/isexe/dist/cjs/package.json
diff --git a/deps/npm/node_modules/which/node_modules/isexe/dist/cjs/posix.js b/deps/npm/node_modules/which/node_modules/isexe/dist/cjs/posix.js
new file mode 100644
index 00000000000000..3bc5e79d7007e9
--- /dev/null
+++ b/deps/npm/node_modules/which/node_modules/isexe/dist/cjs/posix.js
@@ -0,0 +1,67 @@
+"use strict";
+/**
+ * This is the Posix implementation of isexe, which uses the file
+ * mode and uid/gid values.
+ *
+ * @module
+ */
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.sync = exports.isexe = void 0;
+const fs_1 = require("fs");
+const promises_1 = require("fs/promises");
+/**
+ * Determine whether a path is executable according to the mode and
+ * current (or specified) user and group IDs.
+ */
+const isexe = async (path, options = {}) => {
+    const { ignoreErrors = false } = options;
+    try {
+        return checkStat(await (0, promises_1.stat)(path), options);
+    }
+    catch (e) {
+        const er = e;
+        if (ignoreErrors || er.code === 'EACCES')
+            return false;
+        throw er;
+    }
+};
+exports.isexe = isexe;
+/**
+ * Synchronously determine whether a path is executable according to
+ * the mode and current (or specified) user and group IDs.
+ */
+const sync = (path, options = {}) => {
+    const { ignoreErrors = false } = options;
+    try {
+        return checkStat((0, fs_1.statSync)(path), options);
+    }
+    catch (e) {
+        const er = e;
+        if (ignoreErrors || er.code === 'EACCES')
+            return false;
+        throw er;
+    }
+};
+exports.sync = sync;
+const checkStat = (stat, options) => stat.isFile() && checkMode(stat, options);
+const checkMode = (stat, options) => {
+    const myUid = options.uid ?? process.getuid?.();
+    const myGroups = options.groups ?? process.getgroups?.() ?? [];
+    const myGid = options.gid ?? process.getgid?.() ?? myGroups[0];
+    if (myUid === undefined || myGid === undefined) {
+        throw new Error('cannot get uid or gid');
+    }
+    const groups = new Set([myGid, ...myGroups]);
+    const mod = stat.mode;
+    const uid = stat.uid;
+    const gid = stat.gid;
+    const u = parseInt('100', 8);
+    const g = parseInt('010', 8);
+    const o = parseInt('001', 8);
+    const ug = u | g;
+    return !!(mod & o ||
+        (mod & g && groups.has(gid)) ||
+        (mod & u && uid === myUid) ||
+        (mod & ug && myUid === 0));
+};
+//# sourceMappingURL=posix.js.map
\ No newline at end of file
diff --git a/deps/npm/node_modules/which/node_modules/isexe/dist/cjs/win32.js b/deps/npm/node_modules/which/node_modules/isexe/dist/cjs/win32.js
new file mode 100644
index 00000000000000..fa7a4d2f7d240d
--- /dev/null
+++ b/deps/npm/node_modules/which/node_modules/isexe/dist/cjs/win32.js
@@ -0,0 +1,62 @@
+"use strict";
+/**
+ * This is the Windows implementation of isexe, which uses the file
+ * extension and PATHEXT setting.
+ *
+ * @module
+ */
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.sync = exports.isexe = void 0;
+const fs_1 = require("fs");
+const promises_1 = require("fs/promises");
+/**
+ * Determine whether a path is executable based on the file extension
+ * and PATHEXT environment variable (or specified pathExt option)
+ */
+const isexe = async (path, options = {}) => {
+    const { ignoreErrors = false } = options;
+    try {
+        return checkStat(await (0, promises_1.stat)(path), path, options);
+    }
+    catch (e) {
+        const er = e;
+        if (ignoreErrors || er.code === 'EACCES')
+            return false;
+        throw er;
+    }
+};
+exports.isexe = isexe;
+/**
+ * Synchronously determine whether a path is executable based on the file
+ * extension and PATHEXT environment variable (or specified pathExt option)
+ */
+const sync = (path, options = {}) => {
+    const { ignoreErrors = false } = options;
+    try {
+        return checkStat((0, fs_1.statSync)(path), path, options);
+    }
+    catch (e) {
+        const er = e;
+        if (ignoreErrors || er.code === 'EACCES')
+            return false;
+        throw er;
+    }
+};
+exports.sync = sync;
+const checkPathExt = (path, options) => {
+    const { pathExt = process.env.PATHEXT || '' } = options;
+    const peSplit = pathExt.split(';');
+    if (peSplit.indexOf('') !== -1) {
+        return true;
+    }
+    for (let i = 0; i < peSplit.length; i++) {
+        const p = peSplit[i].toLowerCase();
+        const ext = path.substring(path.length - p.length).toLowerCase();
+        if (p && ext === p) {
+            return true;
+        }
+    }
+    return false;
+};
+const checkStat = (stat, path, options) => stat.isFile() && checkPathExt(path, options);
+//# sourceMappingURL=win32.js.map
\ No newline at end of file
diff --git a/deps/npm/node_modules/which/node_modules/isexe/dist/mjs/index.js b/deps/npm/node_modules/which/node_modules/isexe/dist/mjs/index.js
new file mode 100644
index 00000000000000..1e309acd7355ec
--- /dev/null
+++ b/deps/npm/node_modules/which/node_modules/isexe/dist/mjs/index.js
@@ -0,0 +1,16 @@
+import * as posix from './posix.js';
+import * as win32 from './win32.js';
+export * from './options.js';
+export { win32, posix };
+const platform = process.env._ISEXE_TEST_PLATFORM_ || process.platform;
+const impl = platform === 'win32' ? win32 : posix;
+/**
+ * Determine whether a path is executable on the current platform.
+ */
+export const isexe = impl.isexe;
+/**
+ * Synchronously determine whether a path is executable on the
+ * current platform.
+ */
+export const sync = impl.sync;
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/deps/npm/node_modules/which/node_modules/isexe/dist/mjs/options.js b/deps/npm/node_modules/which/node_modules/isexe/dist/mjs/options.js
new file mode 100644
index 00000000000000..e9ded40bd5b2cd
--- /dev/null
+++ b/deps/npm/node_modules/which/node_modules/isexe/dist/mjs/options.js
@@ -0,0 +1,2 @@
+export {};
+//# sourceMappingURL=options.js.map
\ No newline at end of file
diff --git a/deps/npm/node_modules/path-scurry/node_modules/lru-cache/dist/mjs/package.json b/deps/npm/node_modules/which/node_modules/isexe/dist/mjs/package.json
similarity index 100%
rename from deps/npm/node_modules/path-scurry/node_modules/lru-cache/dist/mjs/package.json
rename to deps/npm/node_modules/which/node_modules/isexe/dist/mjs/package.json
diff --git a/deps/npm/node_modules/which/node_modules/isexe/dist/mjs/posix.js b/deps/npm/node_modules/which/node_modules/isexe/dist/mjs/posix.js
new file mode 100644
index 00000000000000..c453776c0452f7
--- /dev/null
+++ b/deps/npm/node_modules/which/node_modules/isexe/dist/mjs/posix.js
@@ -0,0 +1,62 @@
+/**
+ * This is the Posix implementation of isexe, which uses the file
+ * mode and uid/gid values.
+ *
+ * @module
+ */
+import { statSync } from 'fs';
+import { stat } from 'fs/promises';
+/**
+ * Determine whether a path is executable according to the mode and
+ * current (or specified) user and group IDs.
+ */
+export const isexe = async (path, options = {}) => {
+    const { ignoreErrors = false } = options;
+    try {
+        return checkStat(await stat(path), options);
+    }
+    catch (e) {
+        const er = e;
+        if (ignoreErrors || er.code === 'EACCES')
+            return false;
+        throw er;
+    }
+};
+/**
+ * Synchronously determine whether a path is executable according to
+ * the mode and current (or specified) user and group IDs.
+ */
+export const sync = (path, options = {}) => {
+    const { ignoreErrors = false } = options;
+    try {
+        return checkStat(statSync(path), options);
+    }
+    catch (e) {
+        const er = e;
+        if (ignoreErrors || er.code === 'EACCES')
+            return false;
+        throw er;
+    }
+};
+const checkStat = (stat, options) => stat.isFile() && checkMode(stat, options);
+const checkMode = (stat, options) => {
+    const myUid = options.uid ?? process.getuid?.();
+    const myGroups = options.groups ?? process.getgroups?.() ?? [];
+    const myGid = options.gid ?? process.getgid?.() ?? myGroups[0];
+    if (myUid === undefined || myGid === undefined) {
+        throw new Error('cannot get uid or gid');
+    }
+    const groups = new Set([myGid, ...myGroups]);
+    const mod = stat.mode;
+    const uid = stat.uid;
+    const gid = stat.gid;
+    const u = parseInt('100', 8);
+    const g = parseInt('010', 8);
+    const o = parseInt('001', 8);
+    const ug = u | g;
+    return !!(mod & o ||
+        (mod & g && groups.has(gid)) ||
+        (mod & u && uid === myUid) ||
+        (mod & ug && myUid === 0));
+};
+//# sourceMappingURL=posix.js.map
\ No newline at end of file
diff --git a/deps/npm/node_modules/which/node_modules/isexe/dist/mjs/win32.js b/deps/npm/node_modules/which/node_modules/isexe/dist/mjs/win32.js
new file mode 100644
index 00000000000000..a354ee2a5115c7
--- /dev/null
+++ b/deps/npm/node_modules/which/node_modules/isexe/dist/mjs/win32.js
@@ -0,0 +1,57 @@
+/**
+ * This is the Windows implementation of isexe, which uses the file
+ * extension and PATHEXT setting.
+ *
+ * @module
+ */
+import { statSync } from 'fs';
+import { stat } from 'fs/promises';
+/**
+ * Determine whether a path is executable based on the file extension
+ * and PATHEXT environment variable (or specified pathExt option)
+ */
+export const isexe = async (path, options = {}) => {
+    const { ignoreErrors = false } = options;
+    try {
+        return checkStat(await stat(path), path, options);
+    }
+    catch (e) {
+        const er = e;
+        if (ignoreErrors || er.code === 'EACCES')
+            return false;
+        throw er;
+    }
+};
+/**
+ * Synchronously determine whether a path is executable based on the file
+ * extension and PATHEXT environment variable (or specified pathExt option)
+ */
+export const sync = (path, options = {}) => {
+    const { ignoreErrors = false } = options;
+    try {
+        return checkStat(statSync(path), path, options);
+    }
+    catch (e) {
+        const er = e;
+        if (ignoreErrors || er.code === 'EACCES')
+            return false;
+        throw er;
+    }
+};
+const checkPathExt = (path, options) => {
+    const { pathExt = process.env.PATHEXT || '' } = options;
+    const peSplit = pathExt.split(';');
+    if (peSplit.indexOf('') !== -1) {
+        return true;
+    }
+    for (let i = 0; i < peSplit.length; i++) {
+        const p = peSplit[i].toLowerCase();
+        const ext = path.substring(path.length - p.length).toLowerCase();
+        if (p && ext === p) {
+            return true;
+        }
+    }
+    return false;
+};
+const checkStat = (stat, path, options) => stat.isFile() && checkPathExt(path, options);
+//# sourceMappingURL=win32.js.map
\ No newline at end of file
diff --git a/deps/npm/node_modules/which/node_modules/isexe/package.json b/deps/npm/node_modules/which/node_modules/isexe/package.json
new file mode 100644
index 00000000000000..a0e2cd04bfdbfe
--- /dev/null
+++ b/deps/npm/node_modules/which/node_modules/isexe/package.json
@@ -0,0 +1,96 @@
+{
+  "name": "isexe",
+  "version": "3.1.1",
+  "description": "Minimal module to check if a file is executable.",
+  "main": "./dist/cjs/index.js",
+  "module": "./dist/mjs/index.js",
+  "types": "./dist/cjs/index.js",
+  "files": [
+    "dist"
+  ],
+  "exports": {
+    ".": {
+      "import": {
+        "types": "./dist/mjs/index.d.ts",
+        "default": "./dist/mjs/index.js"
+      },
+      "require": {
+        "types": "./dist/cjs/index.d.ts",
+        "default": "./dist/cjs/index.js"
+      }
+    },
+    "./posix": {
+      "import": {
+        "types": "./dist/mjs/posix.d.ts",
+        "default": "./dist/mjs/posix.js"
+      },
+      "require": {
+        "types": "./dist/cjs/posix.d.ts",
+        "default": "./dist/cjs/posix.js"
+      }
+    },
+    "./win32": {
+      "import": {
+        "types": "./dist/mjs/win32.d.ts",
+        "default": "./dist/mjs/win32.js"
+      },
+      "require": {
+        "types": "./dist/cjs/win32.d.ts",
+        "default": "./dist/cjs/win32.js"
+      }
+    },
+    "./package.json": "./package.json"
+  },
+  "devDependencies": {
+    "@types/node": "^20.4.5",
+    "@types/tap": "^15.0.8",
+    "c8": "^8.0.1",
+    "mkdirp": "^0.5.1",
+    "prettier": "^2.8.8",
+    "rimraf": "^2.5.0",
+    "sync-content": "^1.0.2",
+    "tap": "^16.3.8",
+    "ts-node": "^10.9.1",
+    "typedoc": "^0.24.8",
+    "typescript": "^5.1.6"
+  },
+  "scripts": {
+    "preversion": "npm test",
+    "postversion": "npm publish",
+    "prepublishOnly": "git push origin --follow-tags",
+    "prepare": "tsc -p tsconfig/cjs.json && tsc -p tsconfig/esm.json && bash ./scripts/fixup.sh",
+    "pretest": "npm run prepare",
+    "presnap": "npm run prepare",
+    "test": "c8 tap",
+    "snap": "c8 tap",
+    "format": "prettier --write . --loglevel warn --ignore-path ../../.prettierignore --cache",
+    "typedoc": "typedoc --tsconfig tsconfig/esm.json ./src/*.ts"
+  },
+  "author": "Isaac Z. Schlueter  (http://blog.izs.me/)",
+  "license": "ISC",
+  "tap": {
+    "coverage": false,
+    "node-arg": [
+      "--enable-source-maps",
+      "--no-warnings",
+      "--loader",
+      "ts-node/esm"
+    ],
+    "ts": false
+  },
+  "prettier": {
+    "semi": false,
+    "printWidth": 75,
+    "tabWidth": 2,
+    "useTabs": false,
+    "singleQuote": true,
+    "jsxSingleQuote": false,
+    "bracketSameLine": true,
+    "arrowParens": "avoid",
+    "endOfLine": "lf"
+  },
+  "repository": "https://github.com/isaacs/isexe",
+  "engines": {
+    "node": ">=16"
+  }
+}
diff --git a/deps/npm/node_modules/which/package.json b/deps/npm/node_modules/which/package.json
index 989e01c9a36830..515bfb22ca0e1e 100644
--- a/deps/npm/node_modules/which/package.json
+++ b/deps/npm/node_modules/which/package.json
@@ -2,7 +2,7 @@
   "author": "GitHub Inc.",
   "name": "which",
   "description": "Like which(1) unix command. Find the first instance of an executable in the PATH.",
-  "version": "3.0.1",
+  "version": "4.0.0",
   "repository": {
     "type": "git",
     "url": "https://github.com/npm/node-which.git"
@@ -13,11 +13,11 @@
   },
   "license": "ISC",
   "dependencies": {
-    "isexe": "^2.0.0"
+    "isexe": "^3.1.1"
   },
   "devDependencies": {
     "@npmcli/eslint-config": "^4.0.0",
-    "@npmcli/template-oss": "4.14.1",
+    "@npmcli/template-oss": "4.18.0",
     "tap": "^16.3.0"
   },
   "scripts": {
@@ -41,11 +41,17 @@
     ]
   },
   "engines": {
-    "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+    "node": "^16.13.0 || >=18.0.0"
   },
   "templateOSS": {
     "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
-    "version": "4.14.1",
+    "ciVersions": [
+      "16.13.0",
+      "16.x",
+      "18.0.0",
+      "18.x"
+    ],
+    "version": "4.18.0",
     "publish": "true"
   }
 }
diff --git a/deps/npm/node_modules/wrappy/LICENSE b/deps/npm/node_modules/wrappy/LICENSE
deleted file mode 100644
index 19129e315fe593..00000000000000
--- a/deps/npm/node_modules/wrappy/LICENSE
+++ /dev/null
@@ -1,15 +0,0 @@
-The ISC License
-
-Copyright (c) Isaac Z. Schlueter and Contributors
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/deps/npm/node_modules/wrappy/package.json b/deps/npm/node_modules/wrappy/package.json
deleted file mode 100644
index 130752046714d6..00000000000000
--- a/deps/npm/node_modules/wrappy/package.json
+++ /dev/null
@@ -1,29 +0,0 @@
-{
-  "name": "wrappy",
-  "version": "1.0.2",
-  "description": "Callback wrapping utility",
-  "main": "wrappy.js",
-  "files": [
-    "wrappy.js"
-  ],
-  "directories": {
-    "test": "test"
-  },
-  "dependencies": {},
-  "devDependencies": {
-    "tap": "^2.3.1"
-  },
-  "scripts": {
-    "test": "tap --coverage test/*.js"
-  },
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/npm/wrappy"
-  },
-  "author": "Isaac Z. Schlueter  (http://blog.izs.me/)",
-  "license": "ISC",
-  "bugs": {
-    "url": "https://github.com/npm/wrappy/issues"
-  },
-  "homepage": "https://github.com/npm/wrappy"
-}
diff --git a/deps/npm/node_modules/wrappy/wrappy.js b/deps/npm/node_modules/wrappy/wrappy.js
deleted file mode 100644
index bb7e7d6fcf70fd..00000000000000
--- a/deps/npm/node_modules/wrappy/wrappy.js
+++ /dev/null
@@ -1,33 +0,0 @@
-// Returns a wrapper function that returns a wrapped callback
-// The wrapper function should do some stuff, and return a
-// presumably different callback function.
-// This makes sure that own properties are retained, so that
-// decorations and such are not lost along the way.
-module.exports = wrappy
-function wrappy (fn, cb) {
-  if (fn && cb) return wrappy(fn)(cb)
-
-  if (typeof fn !== 'function')
-    throw new TypeError('need wrapper function')
-
-  Object.keys(fn).forEach(function (k) {
-    wrapper[k] = fn[k]
-  })
-
-  return wrapper
-
-  function wrapper() {
-    var args = new Array(arguments.length)
-    for (var i = 0; i < args.length; i++) {
-      args[i] = arguments[i]
-    }
-    var ret = fn.apply(this, args)
-    var cb = args[args.length-1]
-    if (typeof ret === 'function' && ret !== cb) {
-      Object.keys(cb).forEach(function (k) {
-        ret[k] = cb[k]
-      })
-    }
-    return ret
-  }
-}
diff --git a/deps/npm/package.json b/deps/npm/package.json
index 6e719a073893b0..185b5090cb9a2f 100644
--- a/deps/npm/package.json
+++ b/deps/npm/package.json
@@ -1,5 +1,5 @@
 {
-  "version": "9.8.1",
+  "version": "10.2.3",
   "name": "npm",
   "description": "a package manager for JavaScript",
   "workspaces": [
@@ -52,72 +52,75 @@
   },
   "dependencies": {
     "@isaacs/string-locale-compare": "^1.1.0",
-    "@npmcli/arborist": "^6.3.0",
-    "@npmcli/config": "^6.2.1",
+    "@npmcli/arborist": "^7.2.1",
+    "@npmcli/config": "^8.0.1",
     "@npmcli/fs": "^3.1.0",
     "@npmcli/map-workspaces": "^3.0.4",
-    "@npmcli/package-json": "^4.0.1",
-    "@npmcli/promise-spawn": "^6.0.2",
-    "@npmcli/run-script": "^6.0.2",
+    "@npmcli/package-json": "^5.0.0",
+    "@npmcli/promise-spawn": "^7.0.0",
+    "@npmcli/run-script": "^7.0.2",
+    "@sigstore/tuf": "^2.1.0",
     "abbrev": "^2.0.0",
     "archy": "~1.0.0",
-    "cacache": "^17.1.3",
+    "cacache": "^18.0.0",
     "chalk": "^5.3.0",
-    "ci-info": "^3.8.0",
+    "ci-info": "^3.9.0",
     "cli-columns": "^4.0.0",
     "cli-table3": "^0.6.3",
     "columnify": "^1.6.0",
     "fastest-levenshtein": "^1.0.16",
-    "fs-minipass": "^3.0.2",
-    "glob": "^10.2.7",
+    "fs-minipass": "^3.0.3",
+    "glob": "^10.3.10",
     "graceful-fs": "^4.2.11",
-    "hosted-git-info": "^6.1.1",
+    "hosted-git-info": "^7.0.1",
     "ini": "^4.1.1",
-    "init-package-json": "^5.0.0",
+    "init-package-json": "^6.0.0",
     "is-cidr": "^4.0.2",
     "json-parse-even-better-errors": "^3.0.0",
-    "libnpmaccess": "^7.0.2",
-    "libnpmdiff": "^5.0.19",
-    "libnpmexec": "^6.0.3",
-    "libnpmfund": "^4.0.19",
-    "libnpmhook": "^9.0.3",
-    "libnpmorg": "^5.0.4",
-    "libnpmpack": "^5.0.19",
-    "libnpmpublish": "^7.5.0",
-    "libnpmsearch": "^6.0.2",
-    "libnpmteam": "^5.0.3",
-    "libnpmversion": "^4.0.2",
-    "make-fetch-happen": "^11.1.1",
+    "libnpmaccess": "^8.0.1",
+    "libnpmdiff": "^6.0.3",
+    "libnpmexec": "^7.0.3",
+    "libnpmfund": "^5.0.1",
+    "libnpmhook": "^10.0.0",
+    "libnpmorg": "^6.0.1",
+    "libnpmpack": "^6.0.3",
+    "libnpmpublish": "^9.0.1",
+    "libnpmsearch": "^7.0.0",
+    "libnpmteam": "^6.0.0",
+    "libnpmversion": "^5.0.1",
+    "make-fetch-happen": "^13.0.0",
     "minimatch": "^9.0.3",
-    "minipass": "^5.0.0",
+    "minipass": "^7.0.4",
     "minipass-pipeline": "^1.2.4",
     "ms": "^2.1.2",
-    "node-gyp": "^9.4.0",
+    "node-gyp": "^10.0.1",
     "nopt": "^7.2.0",
+    "normalize-package-data": "^6.0.0",
     "npm-audit-report": "^5.0.0",
-    "npm-install-checks": "^6.1.1",
-    "npm-package-arg": "^10.1.0",
-    "npm-pick-manifest": "^8.0.1",
-    "npm-profile": "^7.0.1",
-    "npm-registry-fetch": "^14.0.5",
+    "npm-install-checks": "^6.3.0",
+    "npm-package-arg": "^11.0.1",
+    "npm-pick-manifest": "^9.0.0",
+    "npm-profile": "^9.0.0",
+    "npm-registry-fetch": "^16.1.0",
     "npm-user-validate": "^2.0.0",
     "npmlog": "^7.0.1",
     "p-map": "^4.0.0",
-    "pacote": "^15.2.0",
+    "pacote": "^17.0.4",
     "parse-conflict-json": "^3.0.1",
     "proc-log": "^3.0.0",
     "qrcode-terminal": "^0.12.0",
     "read": "^2.1.0",
     "semver": "^7.5.4",
-    "sigstore": "^1.7.0",
-    "ssri": "^10.0.4",
+    "spdx-expression-parse": "^3.0.1",
+    "ssri": "^10.0.5",
+    "strip-ansi": "^6.0.1",
     "supports-color": "^9.4.0",
-    "tar": "^6.1.15",
+    "tar": "^6.2.0",
     "text-table": "~0.2.0",
     "tiny-relative-date": "^1.3.0",
     "treeverse": "^3.0.0",
     "validate-npm-package-name": "^5.0.0",
-    "which": "^3.0.1",
+    "which": "^4.0.0",
     "write-file-atomic": "^5.0.1"
   },
   "bundleDependencies": [
@@ -129,6 +132,7 @@
     "@npmcli/package-json",
     "@npmcli/promise-spawn",
     "@npmcli/run-script",
+    "@sigstore/tuf",
     "abbrev",
     "archy",
     "cacache",
@@ -164,6 +168,7 @@
     "ms",
     "node-gyp",
     "nopt",
+    "normalize-package-data",
     "npm-audit-report",
     "npm-install-checks",
     "npm-package-arg",
@@ -179,8 +184,9 @@
     "qrcode-terminal",
     "read",
     "semver",
-    "sigstore",
+    "spdx-expression-parse",
     "ssri",
+    "strip-ansi",
     "supports-color",
     "tar",
     "text-table",
@@ -193,20 +199,23 @@
   "devDependencies": {
     "@npmcli/docs": "^1.0.0",
     "@npmcli/eslint-config": "^4.0.2",
-    "@npmcli/git": "^4.1.0",
+    "@npmcli/git": "^5.0.3",
     "@npmcli/mock-globals": "^1.0.0",
     "@npmcli/mock-registry": "^1.0.0",
-    "@npmcli/template-oss": "4.18.0",
-    "@tufjs/repo-mock": "^1.3.1",
+    "@npmcli/template-oss": "4.19.0",
+    "@tufjs/repo-mock": "^2.0.0",
+    "ajv": "^8.12.0",
+    "ajv-formats": "^2.1.1",
+    "ajv-formats-draft2019": "^1.6.1",
     "diff": "^5.1.0",
     "licensee": "^10.0.0",
-    "nock": "^13.3.0",
-    "npm-packlist": "^7.0.4",
+    "nock": "^13.3.3",
+    "npm-packlist": "^8.0.0",
     "remark": "^14.0.2",
     "remark-gfm": "^3.0.1",
     "remark-github": "^11.2.4",
     "spawk": "^1.7.1",
-    "tap": "^16.3.4"
+    "tap": "^16.3.8"
   },
   "scripts": {
     "dependencies": "node scripts/bundle-and-gitignore-deps.js && node scripts/dependency-graph.js",
@@ -249,11 +258,11 @@
   },
   "templateOSS": {
     "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
-    "version": "4.18.0",
+    "version": "4.19.0",
     "content": "./scripts/template-oss/root.js"
   },
   "license": "Artistic-2.0",
   "engines": {
-    "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+    "node": "^18.17.0 || >=20.5.0"
   }
 }
diff --git a/deps/npm/tap-snapshots/test/lib/commands/completion.js.test.cjs b/deps/npm/tap-snapshots/test/lib/commands/completion.js.test.cjs
index b21e378b1cfbe8..089d92440f653f 100644
--- a/deps/npm/tap-snapshots/test/lib/commands/completion.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/commands/completion.js.test.cjs
@@ -93,6 +93,7 @@ Array [
       restart
       root
       run-script
+      sbom
       search
       set
       shrinkwrap
diff --git a/deps/npm/tap-snapshots/test/lib/commands/config.js.test.cjs b/deps/npm/tap-snapshots/test/lib/commands/config.js.test.cjs
index af600062c980e7..b210601e9118b9 100644
--- a/deps/npm/tap-snapshots/test/lib/commands/config.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/commands/config.js.test.cjs
@@ -30,10 +30,11 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna
   "cafile": null,
   "call": "",
   "cert": null,
-  "ci-name": null,
   "cidr": null,
   "color": true,
   "commit-hooks": true,
+  "cpu": null,
+  "os": null,
   "depth": null,
   "description": true,
   "dev": false,
@@ -88,6 +89,8 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna
   "legacy-peer-deps": false,
   "link": false,
   "local-address": null,
+  "sbom-format": null,
+  "sbom-type": "library",
   "location": "user",
   "lockfile-version": null,
   "loglevel": "notice",
@@ -147,7 +150,6 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna
   "tag": "latest",
   "tag-version-prefix": "v",
   "timing": false,
-  "tmp": "{TMP}",
   "umask": 0,
   "unicode": false,
   "update-notifier": true,
@@ -161,8 +163,7 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna
   "workspaces": null,
   "workspaces-update": true,
   "yes": null,
-  "npm-version": "{NPM-VERSION}",
-  "metrics-registry": "https://registry.npmjs.org/"
+  "npm-version": "{NPM-VERSION}"
 }
 `
 
@@ -187,10 +188,10 @@ cache-min = 0
 cafile = null
 call = ""
 cert = null
-ci-name = null
 cidr = null
 color = true
 commit-hooks = true
+cpu = null
 depth = null
 description = true
 dev = false
@@ -254,7 +255,6 @@ logs-max = 10
 ; long = false ; overridden by cli
 maxsockets = 15
 message = "%s"
-metrics-registry = "https://registry.npmjs.org/"
 node-options = null
 noproxy = [""]
 npm-version = "{NPM-VERSION}"
@@ -263,6 +263,7 @@ omit = []
 omit-lockfile-registry-resolved = false
 only = null
 optional = null
+os = null
 otp = null
 pack-destination = "."
 package = []
@@ -291,6 +292,8 @@ save-optional = false
 save-peer = false
 save-prefix = "^"
 save-prod = false
+sbom-format = null
+sbom-type = "library"
 scope = ""
 script-shell = null
 searchexclude = ""
@@ -306,7 +309,6 @@ strict-ssl = true
 tag = "latest"
 tag-version-prefix = "v"
 timing = false
-tmp = "{TMP}"
 umask = 0
 unicode = false
 update-notifier = true
diff --git a/deps/npm/tap-snapshots/test/lib/commands/doctor.js.test.cjs b/deps/npm/tap-snapshots/test/lib/commands/doctor.js.test.cjs
index b7ea39ac4de0ef..98d10c2bb5d4bb 100644
--- a/deps/npm/tap-snapshots/test/lib/commands/doctor.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/commands/doctor.js.test.cjs
@@ -180,9 +180,9 @@ Object {
 
 exports[`test/lib/commands/doctor.js TAP bad proxy > output 1`] = `
 Check                               Value   Recommendation/Notes
-npm ping                            not ok  unsupported proxy protocol: 'ssh:'
-npm -v                              not ok  Error: unsupported proxy protocol: 'ssh:'
-node -v                             not ok  Error: unsupported proxy protocol: 'ssh:'
+npm ping                            not ok  Invalid protocol \`ssh:\` connecting to proxy \`npmjs.org\`
+npm -v                              not ok  Error: Invalid protocol \`ssh:\` connecting to proxy \`npmjs.org\`
+node -v                             not ok  Error: Invalid protocol \`ssh:\` connecting to proxy \`npmjs.org\`
 npm config get registry             ok      using default registry (https://registry.npmjs.org/)
 git executable in PATH              ok      /path/to/git
 global bin folder in PATH           ok      {CWD}/global/bin
diff --git a/deps/npm/tap-snapshots/test/lib/commands/publish.js.test.cjs b/deps/npm/tap-snapshots/test/lib/commands/publish.js.test.cjs
index 7a5c2ddcc3882b..0055c59c3641cf 100644
--- a/deps/npm/tap-snapshots/test/lib/commands/publish.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/commands/publish.js.test.cjs
@@ -191,6 +191,7 @@ Object {
     "man/man1/npm-restart.1",
     "man/man1/npm-root.1",
     "man/man1/npm-run-script.1",
+    "man/man1/npm-sbom.1",
     "man/man1/npm-search.1",
     "man/man1/npm-shrinkwrap.1",
     "man/man1/npm-star.1",
diff --git a/deps/npm/tap-snapshots/test/lib/commands/query.js.test.cjs b/deps/npm/tap-snapshots/test/lib/commands/query.js.test.cjs
index a6dbfcf7c693c8..e7321354689653 100644
--- a/deps/npm/tap-snapshots/test/lib/commands/query.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/commands/query.js.test.cjs
@@ -99,6 +99,54 @@ exports[`test/lib/commands/query.js TAP linked node > should return linked node
 ]
 `
 
+exports[`test/lib/commands/query.js TAP package-lock-only with package lock > should return valid response with only lock info 1`] = `
+[
+  {
+    "name": "project",
+    "dependencies": {
+      "a": "^1.0.0"
+    },
+    "pkgid": "project@",
+    "location": "",
+    "path": "{CWD}/prefix",
+    "realpath": "{CWD}/prefix",
+    "resolved": null,
+    "from": [],
+    "to": [
+      "node_modules/a"
+    ],
+    "dev": false,
+    "inBundle": false,
+    "deduped": false,
+    "overridden": false,
+    "queryContext": {}
+  },
+  {
+    "version": "1.2.3",
+    "resolved": "https://dummy.npmjs.org/a/-/a-1.2.3.tgz",
+    "integrity": "sha512-dummy",
+    "engines": {
+      "node": ">=14.17"
+    },
+    "name": "a",
+    "_id": "a@1.2.3",
+    "pkgid": "a@1.2.3",
+    "location": "node_modules/a",
+    "path": "{CWD}/prefix/node_modules/a",
+    "realpath": "{CWD}/prefix/node_modules/a",
+    "from": [
+      ""
+    ],
+    "to": [],
+    "dev": false,
+    "inBundle": false,
+    "deduped": false,
+    "overridden": false,
+    "queryContext": {}
+  }
+]
+`
+
 exports[`test/lib/commands/query.js TAP recursive tree > should return everything in the tree, accounting for recursion 1`] = `
 [
   {
diff --git a/deps/npm/tap-snapshots/test/lib/commands/sbom.js.test.cjs b/deps/npm/tap-snapshots/test/lib/commands/sbom.js.test.cjs
new file mode 100644
index 00000000000000..0079832f7427fb
--- /dev/null
+++ b/deps/npm/tap-snapshots/test/lib/commands/sbom.js.test.cjs
@@ -0,0 +1,1410 @@
+/* IMPORTANT
+ * This snapshot file is auto-generated, but designed for humans.
+ * It should be checked into source control and tracked carefully.
+ * Re-generate by setting TAP_SNAPSHOT=1 and running tests.
+ * Make sure to inspect the output below.  Do not ignore changes!
+ */
+'use strict'
+exports[`test/lib/commands/sbom.js TAP sbom --omit dev > must match snapshot 1`] = `
+{
+  "spdxVersion": "SPDX-2.3",
+  "dataLicense": "CC0-1.0",
+  "SPDXID": "SPDXRef-DOCUMENT",
+  "name": "test-npm-sbom@1.0.0",
+  "documentNamespace": "http://spdx.org/spdxdocs/test-npm-sbom-1.0.0-00000000-0000-0000-0000-000000000000",
+  "creationInfo": {
+    "created": "2020-01-01T00:00:00.000Z",
+    "creators": [
+      "Tool: npm/cli-10.0.0"
+    ]
+  },
+  "documentDescribes": [
+    "SPDXRef-Package-test-npm-sbom-1.0.0"
+  ],
+  "packages": [
+    {
+      "name": "test-npm-sbom",
+      "SPDXID": "SPDXRef-Package-test-npm-sbom-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "",
+      "primaryPackagePurpose": "LIBRARY",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/test-npm-sbom@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "foo",
+      "SPDXID": "SPDXRef-Package-foo-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/foo",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/foo@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "dog",
+      "SPDXID": "SPDXRef-Package-dog-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/foo/node_modules/dog",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/dog@1.0.0"
+        }
+      ]
+    }
+  ],
+  "relationships": [
+    {
+      "spdxElementId": "SPDXRef-DOCUMENT",
+      "relatedSpdxElement": "SPDXRef-Package-test-npm-sbom-1.0.0",
+      "relationshipType": "DESCRIBES"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-test-npm-sbom-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-foo-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-foo-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-dog-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    }
+  ]
+}
+`
+
+exports[`test/lib/commands/sbom.js TAP sbom --omit optional > must match snapshot 1`] = `
+{
+  "spdxVersion": "SPDX-2.3",
+  "dataLicense": "CC0-1.0",
+  "SPDXID": "SPDXRef-DOCUMENT",
+  "name": "test-npm-sbom@1.0.0",
+  "documentNamespace": "http://spdx.org/spdxdocs/test-npm-sbom-1.0.0-00000000-0000-0000-0000-000000000000",
+  "creationInfo": {
+    "created": "2020-01-01T00:00:00.000Z",
+    "creators": [
+      "Tool: npm/cli-10.0.0"
+    ]
+  },
+  "documentDescribes": [
+    "SPDXRef-Package-test-npm-sbom-1.0.0"
+  ],
+  "packages": [
+    {
+      "name": "test-npm-sbom",
+      "SPDXID": "SPDXRef-Package-test-npm-sbom-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "",
+      "primaryPackagePurpose": "LIBRARY",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/test-npm-sbom@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "chai",
+      "SPDXID": "SPDXRef-Package-chai-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/chai",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/chai@1.0.0"
+        }
+      ]
+    }
+  ],
+  "relationships": [
+    {
+      "spdxElementId": "SPDXRef-DOCUMENT",
+      "relatedSpdxElement": "SPDXRef-Package-test-npm-sbom-1.0.0",
+      "relationshipType": "DESCRIBES"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-test-npm-sbom-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-chai-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    }
+  ]
+}
+`
+
+exports[`test/lib/commands/sbom.js TAP sbom --omit peer > must match snapshot 1`] = `
+{
+  "spdxVersion": "SPDX-2.3",
+  "dataLicense": "CC0-1.0",
+  "SPDXID": "SPDXRef-DOCUMENT",
+  "name": "test-npm-sbom@1.0.0",
+  "documentNamespace": "http://spdx.org/spdxdocs/test-npm-sbom-1.0.0-00000000-0000-0000-0000-000000000000",
+  "creationInfo": {
+    "created": "2020-01-01T00:00:00.000Z",
+    "creators": [
+      "Tool: npm/cli-10.0.0"
+    ]
+  },
+  "documentDescribes": [
+    "SPDXRef-Package-test-npm-sbom-1.0.0"
+  ],
+  "packages": [
+    {
+      "name": "test-npm-sbom",
+      "SPDXID": "SPDXRef-Package-test-npm-sbom-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "",
+      "primaryPackagePurpose": "LIBRARY",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/test-npm-sbom@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "chai",
+      "SPDXID": "SPDXRef-Package-chai-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/chai",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/chai@1.0.0"
+        }
+      ]
+    }
+  ],
+  "relationships": [
+    {
+      "spdxElementId": "SPDXRef-DOCUMENT",
+      "relatedSpdxElement": "SPDXRef-Package-test-npm-sbom-1.0.0",
+      "relationshipType": "DESCRIBES"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-test-npm-sbom-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-chai-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    }
+  ]
+}
+`
+
+exports[`test/lib/commands/sbom.js TAP sbom basic sbom - cyclonedx > must match snapshot 1`] = `
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.5",
+  "serialNumber": "urn:uuid:00000000-0000-0000-0000-000000000000",
+  "version": 1,
+  "metadata": {
+    "timestamp": "2020-01-01T00:00:00.000Z",
+    "lifecycles": [
+      {
+        "phase": "build"
+      }
+    ],
+    "tools": [
+      {
+        "vendor": "npm",
+        "name": "cli",
+        "version": "10.0.0"
+      }
+    ],
+    "component": {
+      "bom-ref": "test-npm-sbom@1.0.0",
+      "type": "application",
+      "name": "prefix",
+      "version": "1.0.0",
+      "scope": "required",
+      "purl": "pkg:npm/test-npm-sbom@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": ""
+        }
+      ],
+      "externalReferences": []
+    }
+  },
+  "components": [
+    {
+      "bom-ref": "chai@1.0.0",
+      "type": "library",
+      "name": "chai",
+      "version": "1.0.0",
+      "scope": "required",
+      "purl": "pkg:npm/chai@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": "node_modules/chai"
+        }
+      ],
+      "externalReferences": []
+    },
+    {
+      "bom-ref": "foo@1.0.0",
+      "type": "library",
+      "name": "foo",
+      "version": "1.0.0",
+      "scope": "required",
+      "purl": "pkg:npm/foo@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": "node_modules/foo"
+        }
+      ],
+      "externalReferences": []
+    },
+    {
+      "bom-ref": "dog@1.0.0",
+      "type": "library",
+      "name": "dog",
+      "version": "1.0.0",
+      "scope": "required",
+      "purl": "pkg:npm/dog@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": "node_modules/foo/node_modules/dog"
+        }
+      ],
+      "externalReferences": []
+    }
+  ],
+  "dependencies": [
+    {
+      "ref": "test-npm-sbom@1.0.0",
+      "dependsOn": [
+        "foo@1.0.0",
+        "chai@1.0.0"
+      ]
+    },
+    {
+      "ref": "chai@1.0.0",
+      "dependsOn": []
+    },
+    {
+      "ref": "foo@1.0.0",
+      "dependsOn": [
+        "dog@1.0.0"
+      ]
+    },
+    {
+      "ref": "dog@1.0.0",
+      "dependsOn": []
+    }
+  ]
+}
+`
+
+exports[`test/lib/commands/sbom.js TAP sbom basic sbom - spdx > must match snapshot 1`] = `
+{
+  "spdxVersion": "SPDX-2.3",
+  "dataLicense": "CC0-1.0",
+  "SPDXID": "SPDXRef-DOCUMENT",
+  "name": "test-npm-sbom@1.0.0",
+  "documentNamespace": "http://spdx.org/spdxdocs/test-npm-sbom-1.0.0-00000000-0000-0000-0000-000000000000",
+  "creationInfo": {
+    "created": "2020-01-01T00:00:00.000Z",
+    "creators": [
+      "Tool: npm/cli-10.0.0"
+    ]
+  },
+  "documentDescribes": [
+    "SPDXRef-Package-test-npm-sbom-1.0.0"
+  ],
+  "packages": [
+    {
+      "name": "test-npm-sbom",
+      "SPDXID": "SPDXRef-Package-test-npm-sbom-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "",
+      "primaryPackagePurpose": "LIBRARY",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/test-npm-sbom@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "chai",
+      "SPDXID": "SPDXRef-Package-chai-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/chai",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/chai@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "foo",
+      "SPDXID": "SPDXRef-Package-foo-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/foo",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/foo@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "dog",
+      "SPDXID": "SPDXRef-Package-dog-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/foo/node_modules/dog",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/dog@1.0.0"
+        }
+      ]
+    }
+  ],
+  "relationships": [
+    {
+      "spdxElementId": "SPDXRef-DOCUMENT",
+      "relatedSpdxElement": "SPDXRef-Package-test-npm-sbom-1.0.0",
+      "relationshipType": "DESCRIBES"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-test-npm-sbom-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-foo-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-test-npm-sbom-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-chai-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-foo-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-dog-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    }
+  ]
+}
+`
+
+exports[`test/lib/commands/sbom.js TAP sbom extraneous dep > must match snapshot 1`] = `
+{
+  "spdxVersion": "SPDX-2.3",
+  "dataLicense": "CC0-1.0",
+  "SPDXID": "SPDXRef-DOCUMENT",
+  "name": "test-npm-ls@1.0.0",
+  "documentNamespace": "http://spdx.org/spdxdocs/test-npm-sbom-1.0.0-00000000-0000-0000-0000-000000000000",
+  "creationInfo": {
+    "created": "2020-01-01T00:00:00.000Z",
+    "creators": [
+      "Tool: npm/cli-10.0.0"
+    ]
+  },
+  "documentDescribes": [
+    "SPDXRef-Package-test-npm-ls-1.0.0"
+  ],
+  "packages": [
+    {
+      "name": "test-npm-ls",
+      "SPDXID": "SPDXRef-Package-test-npm-ls-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "",
+      "primaryPackagePurpose": "LIBRARY",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/test-npm-ls@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "chai",
+      "SPDXID": "SPDXRef-Package-chai-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/chai",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/chai@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "foo",
+      "SPDXID": "SPDXRef-Package-foo-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/foo",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/foo@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "dog",
+      "SPDXID": "SPDXRef-Package-dog-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/foo/node_modules/dog",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/dog@1.0.0"
+        }
+      ]
+    }
+  ],
+  "relationships": [
+    {
+      "spdxElementId": "SPDXRef-DOCUMENT",
+      "relatedSpdxElement": "SPDXRef-Package-test-npm-ls-1.0.0",
+      "relationshipType": "DESCRIBES"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-test-npm-ls-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-foo-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-foo-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-dog-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-test-npm-ls-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-chai-1.0.0",
+      "relationshipType": "OPTIONAL_DEPENDENCY_OF"
+    }
+  ]
+}
+`
+
+exports[`test/lib/commands/sbom.js TAP sbom loading a tree containing workspaces should filter worksapces with --workspace > must match snapshot 1`] = `
+{
+  "spdxVersion": "SPDX-2.3",
+  "dataLicense": "CC0-1.0",
+  "SPDXID": "SPDXRef-DOCUMENT",
+  "name": "workspaces-tree@1.0.0",
+  "documentNamespace": "http://spdx.org/spdxdocs/test-npm-sbom-1.0.0-00000000-0000-0000-0000-000000000000",
+  "creationInfo": {
+    "created": "2020-01-01T00:00:00.000Z",
+    "creators": [
+      "Tool: npm/cli-10.0.0"
+    ]
+  },
+  "documentDescribes": [
+    "SPDXRef-Package-workspaces-tree-1.0.0"
+  ],
+  "packages": [
+    {
+      "name": "workspaces-tree",
+      "SPDXID": "SPDXRef-Package-workspaces-tree-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "",
+      "primaryPackagePurpose": "LIBRARY",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/workspaces-tree@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "a",
+      "SPDXID": "SPDXRef-Package-a-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/a",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/a@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "d",
+      "SPDXID": "SPDXRef-Package-d-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/d",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/d@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "bar",
+      "SPDXID": "SPDXRef-Package-bar-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/bar",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/bar@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "baz",
+      "SPDXID": "SPDXRef-Package-baz-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/baz",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/baz@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "c",
+      "SPDXID": "SPDXRef-Package-c-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/c",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/c@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "foo",
+      "SPDXID": "SPDXRef-Package-foo-1.1.1",
+      "versionInfo": "1.1.1",
+      "packageFileName": "node_modules/foo",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/foo@1.1.1"
+        }
+      ]
+    }
+  ],
+  "relationships": [
+    {
+      "spdxElementId": "SPDXRef-DOCUMENT",
+      "relatedSpdxElement": "SPDXRef-Package-workspaces-tree-1.0.0",
+      "relationshipType": "DESCRIBES"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-workspaces-tree-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-a-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-workspaces-tree-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-d-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-a-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-c-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-a-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-d-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-a-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-baz-1.0.0",
+      "relationshipType": "DEV_DEPENDENCY_OF"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-d-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-foo-1.1.1",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-foo-1.1.1",
+      "relatedSpdxElement": "SPDXRef-Package-bar-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    }
+  ]
+}
+`
+
+exports[`test/lib/commands/sbom.js TAP sbom loading a tree containing workspaces should filter workspaces with multiple --workspace flags > must match snapshot 1`] = `
+{
+  "spdxVersion": "SPDX-2.3",
+  "dataLicense": "CC0-1.0",
+  "SPDXID": "SPDXRef-DOCUMENT",
+  "name": "workspaces-tree@1.0.0",
+  "documentNamespace": "http://spdx.org/spdxdocs/test-npm-sbom-1.0.0-00000000-0000-0000-0000-000000000000",
+  "creationInfo": {
+    "created": "2020-01-01T00:00:00.000Z",
+    "creators": [
+      "Tool: npm/cli-10.0.0"
+    ]
+  },
+  "documentDescribes": [
+    "SPDXRef-Package-workspaces-tree-1.0.0"
+  ],
+  "packages": [
+    {
+      "name": "workspaces-tree",
+      "SPDXID": "SPDXRef-Package-workspaces-tree-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "",
+      "primaryPackagePurpose": "LIBRARY",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/workspaces-tree@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "e",
+      "SPDXID": "SPDXRef-Package-e-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/e",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/e@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "f",
+      "SPDXID": "SPDXRef-Package-f-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/f",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/f@1.0.0"
+        }
+      ]
+    }
+  ],
+  "relationships": [
+    {
+      "spdxElementId": "SPDXRef-DOCUMENT",
+      "relatedSpdxElement": "SPDXRef-Package-workspaces-tree-1.0.0",
+      "relationshipType": "DESCRIBES"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-workspaces-tree-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-e-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-workspaces-tree-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-f-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    }
+  ]
+}
+`
+
+exports[`test/lib/commands/sbom.js TAP sbom loading a tree containing workspaces should list workspaces properly with default configs > must match snapshot 1`] = `
+{
+  "spdxVersion": "SPDX-2.3",
+  "dataLicense": "CC0-1.0",
+  "SPDXID": "SPDXRef-DOCUMENT",
+  "name": "workspaces-tree@1.0.0",
+  "documentNamespace": "http://spdx.org/spdxdocs/test-npm-sbom-1.0.0-00000000-0000-0000-0000-000000000000",
+  "creationInfo": {
+    "created": "2020-01-01T00:00:00.000Z",
+    "creators": [
+      "Tool: npm/cli-10.0.0"
+    ]
+  },
+  "documentDescribes": [
+    "SPDXRef-Package-workspaces-tree-1.0.0"
+  ],
+  "packages": [
+    {
+      "name": "workspaces-tree",
+      "SPDXID": "SPDXRef-Package-workspaces-tree-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "",
+      "primaryPackagePurpose": "LIBRARY",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/workspaces-tree@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "a",
+      "SPDXID": "SPDXRef-Package-a-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/a",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/a@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "b",
+      "SPDXID": "SPDXRef-Package-b-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/b",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/b@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "d",
+      "SPDXID": "SPDXRef-Package-d-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/d",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/d@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "e",
+      "SPDXID": "SPDXRef-Package-e-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/e",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/e@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "f",
+      "SPDXID": "SPDXRef-Package-f-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/f",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/f@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "bar",
+      "SPDXID": "SPDXRef-Package-bar-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/bar",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/bar@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "baz",
+      "SPDXID": "SPDXRef-Package-baz-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/baz",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/baz@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "c",
+      "SPDXID": "SPDXRef-Package-c-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/c",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/c@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "foo",
+      "SPDXID": "SPDXRef-Package-foo-1.1.1",
+      "versionInfo": "1.1.1",
+      "packageFileName": "node_modules/foo",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/foo@1.1.1"
+        }
+      ]
+    },
+    {
+      "name": "pacote",
+      "SPDXID": "SPDXRef-Package-pacote-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/pacote",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/pacote@1.0.0"
+        }
+      ]
+    }
+  ],
+  "relationships": [
+    {
+      "spdxElementId": "SPDXRef-DOCUMENT",
+      "relatedSpdxElement": "SPDXRef-Package-workspaces-tree-1.0.0",
+      "relationshipType": "DESCRIBES"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-workspaces-tree-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-a-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-workspaces-tree-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-b-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-workspaces-tree-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-d-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-workspaces-tree-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-e-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-workspaces-tree-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-f-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-workspaces-tree-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-pacote-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-a-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-c-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-a-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-d-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-a-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-baz-1.0.0",
+      "relationshipType": "DEV_DEPENDENCY_OF"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-d-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-foo-1.1.1",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-foo-1.1.1",
+      "relatedSpdxElement": "SPDXRef-Package-bar-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    }
+  ]
+}
+`
+
+exports[`test/lib/commands/sbom.js TAP sbom loading a tree containing workspaces should not list workspaces with --no-workspaces > must match snapshot 1`] = `
+{
+  "spdxVersion": "SPDX-2.3",
+  "dataLicense": "CC0-1.0",
+  "SPDXID": "SPDXRef-DOCUMENT",
+  "name": "workspaces-tree@1.0.0",
+  "documentNamespace": "http://spdx.org/spdxdocs/test-npm-sbom-1.0.0-00000000-0000-0000-0000-000000000000",
+  "creationInfo": {
+    "created": "2020-01-01T00:00:00.000Z",
+    "creators": [
+      "Tool: npm/cli-10.0.0"
+    ]
+  },
+  "documentDescribes": [
+    "SPDXRef-Package-workspaces-tree-1.0.0"
+  ],
+  "packages": [
+    {
+      "name": "workspaces-tree",
+      "SPDXID": "SPDXRef-Package-workspaces-tree-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "",
+      "primaryPackagePurpose": "LIBRARY",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/workspaces-tree@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "pacote",
+      "SPDXID": "SPDXRef-Package-pacote-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/pacote",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/pacote@1.0.0"
+        }
+      ]
+    }
+  ],
+  "relationships": [
+    {
+      "spdxElementId": "SPDXRef-DOCUMENT",
+      "relatedSpdxElement": "SPDXRef-Package-workspaces-tree-1.0.0",
+      "relationshipType": "DESCRIBES"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-workspaces-tree-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-pacote-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    }
+  ]
+}
+`
+
+exports[`test/lib/commands/sbom.js TAP sbom lock file only - missing lock file > must match snapshot 1`] = `
+
+`
+
+exports[`test/lib/commands/sbom.js TAP sbom lock file only > must match snapshot 1`] = `
+{
+  "spdxVersion": "SPDX-2.3",
+  "dataLicense": "CC0-1.0",
+  "SPDXID": "SPDXRef-DOCUMENT",
+  "name": "test-npm-ls@1.0.0",
+  "documentNamespace": "http://spdx.org/spdxdocs/test-npm-sbom-1.0.0-00000000-0000-0000-0000-000000000000",
+  "creationInfo": {
+    "created": "2020-01-01T00:00:00.000Z",
+    "creators": [
+      "Tool: npm/cli-10.0.0"
+    ]
+  },
+  "documentDescribes": [
+    "SPDXRef-Package-test-npm-ls-1.0.0"
+  ],
+  "packages": [
+    {
+      "name": "test-npm-ls",
+      "SPDXID": "SPDXRef-Package-test-npm-ls-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "",
+      "primaryPackagePurpose": "LIBRARY",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/test-npm-ls@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "chai",
+      "SPDXID": "SPDXRef-Package-chai-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/chai",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/chai@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "dog",
+      "SPDXID": "SPDXRef-Package-dog-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/dog",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/dog@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "foo",
+      "SPDXID": "SPDXRef-Package-foo-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/foo",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/foo@1.0.0"
+        }
+      ]
+    }
+  ],
+  "relationships": [
+    {
+      "spdxElementId": "SPDXRef-DOCUMENT",
+      "relatedSpdxElement": "SPDXRef-Package-test-npm-ls-1.0.0",
+      "relationshipType": "DESCRIBES"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-test-npm-ls-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-foo-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-test-npm-ls-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-chai-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-foo-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-dog-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    }
+  ]
+}
+`
+
+exports[`test/lib/commands/sbom.js TAP sbom missing (optional) dep > must match snapshot 1`] = `
+{
+  "spdxVersion": "SPDX-2.3",
+  "dataLicense": "CC0-1.0",
+  "SPDXID": "SPDXRef-DOCUMENT",
+  "name": "test-npm-ls@1.0.0",
+  "documentNamespace": "http://spdx.org/spdxdocs/test-npm-sbom-1.0.0-00000000-0000-0000-0000-000000000000",
+  "creationInfo": {
+    "created": "2020-01-01T00:00:00.000Z",
+    "creators": [
+      "Tool: npm/cli-10.0.0"
+    ]
+  },
+  "documentDescribes": [
+    "SPDXRef-Package-test-npm-ls-1.0.0"
+  ],
+  "packages": [
+    {
+      "name": "test-npm-ls",
+      "SPDXID": "SPDXRef-Package-test-npm-ls-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "",
+      "primaryPackagePurpose": "LIBRARY",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/test-npm-ls@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "chai",
+      "SPDXID": "SPDXRef-Package-chai-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/chai",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/chai@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "foo",
+      "SPDXID": "SPDXRef-Package-foo-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/foo",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/foo@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "dog",
+      "SPDXID": "SPDXRef-Package-dog-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "node_modules/foo/node_modules/dog",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/dog@1.0.0"
+        }
+      ]
+    }
+  ],
+  "relationships": [
+    {
+      "spdxElementId": "SPDXRef-DOCUMENT",
+      "relatedSpdxElement": "SPDXRef-Package-test-npm-ls-1.0.0",
+      "relationshipType": "DESCRIBES"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-test-npm-ls-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-foo-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-test-npm-ls-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-chai-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-foo-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-dog-1.0.0",
+      "relationshipType": "DEPENDS_ON"
+    }
+  ]
+}
+`
+
+exports[`test/lib/commands/sbom.js TAP sbom missing format > must match snapshot 1`] = `
+
+`
diff --git a/deps/npm/tap-snapshots/test/lib/commands/search.js.test.cjs b/deps/npm/tap-snapshots/test/lib/commands/search.js.test.cjs
index bfa4b42182e1ea..50032deb745739 100644
--- a/deps/npm/tap-snapshots/test/lib/commands/search.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/commands/search.js.test.cjs
@@ -21,9 +21,10 @@ NAME                      | DESCRIPTION          | AUTHOR          | DATE
 libnpmhook                | programmatic API…    | =nlf…           | 2020-11-03 | 6.0.1    | npm hooks registry npm api
 libnpmpublish             | Programmatic API…    | =nlf…           | 2020-11-03 | 4.0.0    |
 libnpmfund                | Programmatic API…    | =nlf…           | 2020-12-08 | 1.0.2    | npm npmcli libnpm cli git fund gitfund
-@npmcli/map-workspaces    | Retrieves a…         | =nlf…           | 2020-09-30 | 1.0.1    | npm npmcli libnpm cli workspaces map-workspaces
+@npmcli/map-workspaces    | Retrieves a…         | =nlf…           | 2020-09-30 | 1.0.1    | npm  bad map npmcli libnpm cli workspaces map-workspaces
 libnpmversion             | library to do the…   | =nlf…           | 2020-11-04 | 1.0.7    |
 @types/libnpmsearch       | TypeScript…          | =types          | 2019-09-26 | 2.0.1    |
+pkg-no-desc               |                      | =lukekarrys     | 2019-09-26 | 1.0.0    |
 `
 
 exports[`test/lib/commands/search.js TAP search  --color > should have expected search results with color 1`] = `
@@ -38,9 +39,10 @@ NAME                      | DESCRIPTION          | AUTHOR          | DATE
 libnpmhook                | programmatic API…    | =nlf…           | 2020-11-03 | 6.0.1    | npm hooks registry npm api
 libnpmpublish             | Programmatic API…    | =nlf…           | 2020-11-03 | 4.0.0    | 
 libnpmfund                | Programmatic API…    | =nlf…           | 2020-12-08 | 1.0.2    | npm npmcli libnpm cli git fund gitfund
-@npmcli/map-workspaces    | Retrieves a…         | =nlf…           | 2020-09-30 | 1.0.1    | npm npmcli libnpm cli workspaces map-workspaces
+@npmcli/map-workspaces    | Retrieves a…         | =nlf…           | 2020-09-30 | 1.0.1    | npm  bad map npmcli libnpm cli workspaces map-workspaces
 libnpmversion             | library to do the…   | =nlf…           | 2020-11-04 | 1.0.7    | 
 @types/libnpmsearch       | TypeScript…          | =types          | 2019-09-26 | 2.0.1    | 
+pkg-no-desc               |                      | =lukekarrys     | 2019-09-26 | 1.0.0    | 
 `
 
 exports[`test/lib/commands/search.js TAP search  --parseable > should have expected search results as parseable 1`] = `
@@ -54,9 +56,10 @@ libnpmteam	npm Team management APIs	=nlf =ruyadorno =darcyclarke =isaacs	2020-11
 libnpmhook	programmatic API for managing npm registry hooks	=nlf =ruyadorno =darcyclarke =isaacs	2020-11-03 	6.0.1	npm hooks registry npm api
 libnpmpublish	Programmatic API for the bits behind npm publish and unpublish	=nlf =ruyadorno =darcyclarke =isaacs	2020-11-03 	4.0.0
 libnpmfund	Programmatic API for npm fund	=nlf =ruyadorno =darcyclarke =isaacs	2020-12-08 	1.0.2	npm npmcli libnpm cli git fund gitfund
-@npmcli/map-workspaces	Retrieves a name:pathname Map for a given workspaces config	=nlf =ruyadorno =darcyclarke =isaacs	2020-09-30 	1.0.1	npm npmcli libnpm cli workspaces map-workspaces
+@npmcli/map-workspaces	Retrieves a name:pathname Map for a given workspaces config	=nlf =ruyadorno =darcyclarke =isaacs	2020-09-30 	1.0.1	npm  bad map npmcli libnpm cli workspaces map-workspaces
 libnpmversion	library to do the things that 'npm version' does	=nlf =ruyadorno =darcyclarke =isaacs	2020-11-04 	1.0.7
 @types/libnpmsearch	TypeScript definitions for libnpmsearch	=types	2019-09-26 	2.0.1
+pkg-no-desc		=lukekarrys	2019-09-26 	1.0.0
 `
 
 exports[`test/lib/commands/search.js TAP search  > should have filtered expected search results 1`] = `
@@ -77,9 +80,10 @@ libnpmteam                | npm Team management… | =nlf…           | 2020-11
 libnpmhook                | programmatic API…    | =nlf…           | 2020-11-03 | 6.0.1    | npm hooks registry npm api
 libnpmpublish             | Programmatic API…    | =nlf…           | 2020-11-03 | 4.0.0    |
 libnpmfund                | Programmatic API…    | =nlf…           | 2020-12-08 | 1.0.2    | npm npmcli libnpm cli git fund gitfund
-@npmcli/map-workspaces    | Retrieves a…         | =nlf…           | 2020-09-30 | 1.0.1    | npm npmcli libnpm cli workspaces map-workspaces
+@npmcli/map-workspaces    | Retrieves a…         | =nlf…           | 2020-09-30 | 1.0.1    | npm  bad map npmcli libnpm cli workspaces map-workspaces
 libnpmversion             | library to do the…   | =nlf…           | 2020-11-04 | 1.0.7    |
 @types/libnpmsearch       | TypeScript…          | =types          | 2019-09-26 | 2.0.1    |
+pkg-no-desc               |                      | =lukekarrys     | 2019-09-26 | 1.0.0    |
 `
 
 exports[`test/lib/commands/search.js TAP search exclude forward slash > results should not have libnpmversion 1`] = `
@@ -94,8 +98,9 @@ libnpmteam                | npm Team management… | =nlf…           | 2020-11
 libnpmhook                | programmatic API…    | =nlf…           | 2020-11-03 | 6.0.1    | npm hooks registry npm api
 libnpmpublish             | Programmatic API…    | =nlf…           | 2020-11-03 | 4.0.0    |
 libnpmfund                | Programmatic API…    | =nlf…           | 2020-12-08 | 1.0.2    | npm npmcli libnpm cli git fund gitfund
-@npmcli/map-workspaces    | Retrieves a…         | =nlf…           | 2020-09-30 | 1.0.1    | npm npmcli libnpm cli workspaces map-workspaces
+@npmcli/map-workspaces    | Retrieves a…         | =nlf…           | 2020-09-30 | 1.0.1    | npm  bad map npmcli libnpm cli workspaces map-workspaces
 @types/libnpmsearch       | TypeScript…          | =types          | 2019-09-26 | 2.0.1    |
+pkg-no-desc               |                      | =lukekarrys     | 2019-09-26 | 1.0.0    |
 `
 
 exports[`test/lib/commands/search.js TAP search exclude regex > results should not have libnpmversion 1`] = `
@@ -110,8 +115,9 @@ libnpmteam                | npm Team management… | =nlf…           | 2020-11
 libnpmhook                | programmatic API…    | =nlf…           | 2020-11-03 | 6.0.1    | npm hooks registry npm api
 libnpmpublish             | Programmatic API…    | =nlf…           | 2020-11-03 | 4.0.0    |
 libnpmfund                | Programmatic API…    | =nlf…           | 2020-12-08 | 1.0.2    | npm npmcli libnpm cli git fund gitfund
-@npmcli/map-workspaces    | Retrieves a…         | =nlf…           | 2020-09-30 | 1.0.1    | npm npmcli libnpm cli workspaces map-workspaces
+@npmcli/map-workspaces    | Retrieves a…         | =nlf…           | 2020-09-30 | 1.0.1    | npm  bad map npmcli libnpm cli workspaces map-workspaces
 @types/libnpmsearch       | TypeScript…          | =types          | 2019-09-26 | 2.0.1    |
+pkg-no-desc               |                      | =lukekarrys     | 2019-09-26 | 1.0.0    |
 `
 
 exports[`test/lib/commands/search.js TAP search exclude string > results should not have libnpmversion 1`] = `
@@ -126,8 +132,9 @@ libnpmteam                | npm Team management… | =nlf…           | 2020-11
 libnpmhook                | programmatic API…    | =nlf…           | 2020-11-03 | 6.0.1    | npm hooks registry npm api
 libnpmpublish             | Programmatic API…    | =nlf…           | 2020-11-03 | 4.0.0    |
 libnpmfund                | Programmatic API…    | =nlf…           | 2020-12-08 | 1.0.2    | npm npmcli libnpm cli git fund gitfund
-@npmcli/map-workspaces    | Retrieves a…         | =nlf…           | 2020-09-30 | 1.0.1    | npm npmcli libnpm cli workspaces map-workspaces
+@npmcli/map-workspaces    | Retrieves a…         | =nlf…           | 2020-09-30 | 1.0.1    | npm  bad map npmcli libnpm cli workspaces map-workspaces
 @types/libnpmsearch       | TypeScript…          | =types          | 2019-09-26 | 2.0.1    |
+pkg-no-desc               |                      | =lukekarrys     | 2019-09-26 | 1.0.0    |
 `
 
 exports[`test/lib/commands/search.js TAP search exclude username with upper case letters > results should not have nlf 1`] = `
@@ -135,4 +142,5 @@ NAME                      | DESCRIPTION          | AUTHOR          | DATE
 @evocateur/libnpmaccess   | programmatic…        | =evocateur      | 2019-07-16 | 3.1.2    |
 @evocateur/libnpmpublish  | Programmatic API…    | =evocateur      | 2019-07-16 | 1.2.2    |
 @types/libnpmsearch       | TypeScript…          | =types          | 2019-09-26 | 2.0.1    |
+pkg-no-desc               |                      | =lukekarrys     | 2019-09-26 | 1.0.0    |
 `
diff --git a/deps/npm/tap-snapshots/test/lib/commands/view.js.test.cjs b/deps/npm/tap-snapshots/test/lib/commands/view.js.test.cjs
index d5b7a3b4a79068..5248d439afad95 100644
--- a/deps/npm/tap-snapshots/test/lib/commands/view.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/commands/view.js.test.cjs
@@ -315,6 +315,10 @@ maintainers[0].name = 'claudia'
 maintainers[1].name = 'isaacs'
 `
 
+exports[`test/lib/commands/view.js TAP specific field names fields with empty values > must match snapshot 1`] = `
+
+`
+
 exports[`test/lib/commands/view.js TAP specific field names maintainers with email > must match snapshot 1`] = `
 maintainers = [
   { name: 'claudia', email: 'c@yellow.com', twitter: 'cyellow' },
diff --git a/deps/npm/tap-snapshots/test/lib/docs.js.test.cjs b/deps/npm/tap-snapshots/test/lib/docs.js.test.cjs
index 4875ebae6952b2..55397121bc0da8 100644
--- a/deps/npm/tap-snapshots/test/lib/docs.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/docs.js.test.cjs
@@ -145,6 +145,7 @@ Array [
   "restart",
   "root",
   "run-script",
+  "sbom",
   "search",
   "set",
   "shrinkwrap",
@@ -392,6 +393,16 @@ Run git commit hooks when using the \`npm version\` command.
 
 
 
+#### \`cpu\`
+
+* Default: null
+* Type: null or String
+
+Override CPU architecture of native modules to install. Acceptable values
+are same as \`cpu\` field of package.json, which comes from \`process.arch\`.
+
+
+
 #### \`depth\`
 
 * Default: \`Infinity\` if \`--all\` is set, otherwise \`1\`
@@ -1085,6 +1096,16 @@ time.
 
 
 
+#### \`os\`
+
+* Default: null
+* Type: null or String
+
+Override OS of native modules to install. Acceptable values are same as \`os\`
+field of package.json, which comes from \`process.platform\`.
+
+
+
 #### \`otp\`
 
 * Default: null
@@ -1385,6 +1406,26 @@ or \`--save-optional\` are true.
 
 
 
+#### \`sbom-format\`
+
+* Default: null
+* Type: "cyclonedx" or "spdx"
+
+SBOM format to use when generating SBOMs.
+
+
+
+#### \`sbom-type\`
+
+* Default: "library"
+* Type: "library", "application", or "framework"
+
+The type of package described by the generated SBOM. For SPDX, this is the
+value for the \`primaryPackagePurpose\` fieled. For CycloneDX, this is the
+value for the \`type\` field.
+
+
+
 #### \`scope\`
 
 * Default: the scope of the current project, if any, or ""
@@ -1822,20 +1863,6 @@ registry-scoped "certfile" path like
 
 
 
-#### \`ci-name\`
-
-* Default: The name of the current CI system, or \`null\` when not on a known CI
-  platform.
-* Type: null or String
-* DEPRECATED: This config is deprecated and will not be changeable in future
-  version of npm.
-
-The name of a continuous integration system. If not set explicitly, npm will
-detect the current CI environment using the
-[\`ci-info\`](http://npm.im/ci-info) module.
-
-
-
 #### \`dev\`
 
 * Default: false
@@ -1995,20 +2022,6 @@ Alias for \`--omit=dev\`
 Alias for --package-lock
 
 
-
-#### \`tmp\`
-
-* Default: The value returned by the Node.js \`os.tmpdir()\` method
-  
-* Type: Path
-* DEPRECATED: This setting is no longer used. npm stores temporary files in a
-  special location in the cache, and they are managed by
-  [\`cacache\`](http://npm.im/cacache).
-
-Historically, the location where temporary files were stored. No longer
-relevant.
-
-
 `
 
 exports[`test/lib/docs.js TAP config > all keys 1`] = `
@@ -2031,10 +2044,11 @@ Array [
   "cafile",
   "call",
   "cert",
-  "ci-name",
   "cidr",
   "color",
   "commit-hooks",
+  "cpu",
+  "os",
   "depth",
   "description",
   "dev",
@@ -2090,6 +2104,8 @@ Array [
   "legacy-peer-deps",
   "link",
   "local-address",
+  "sbom-format",
+  "sbom-type",
   "location",
   "lockfile-version",
   "loglevel",
@@ -2148,7 +2164,6 @@ Array [
   "tag",
   "tag-version-prefix",
   "timing",
-  "tmp",
   "umask",
   "unicode",
   "update-notifier",
@@ -2186,10 +2201,11 @@ Array [
   "cafile",
   "call",
   "cert",
-  "ci-name",
   "cidr",
   "color",
   "commit-hooks",
+  "cpu",
+  "os",
   "depth",
   "description",
   "dev",
@@ -2232,6 +2248,8 @@ Array [
   "legacy-bundling",
   "legacy-peer-deps",
   "local-address",
+  "sbom-format",
+  "sbom-type",
   "location",
   "lockfile-version",
   "loglevel",
@@ -2314,7 +2332,6 @@ Array [
   "node-options",
   "prefix",
   "timing",
-  "tmp",
   "update-notifier",
   "usage",
   "userconfig",
@@ -2343,9 +2360,9 @@ Object {
   "call": "",
   "cert": null,
   "cidr": null,
-  "ciName": "{ci}",
   "color": false,
   "commitHooks": true,
+  "cpu": null,
   "defaultTag": "latest",
   "depth": null,
   "diff": Array [],
@@ -2367,7 +2384,6 @@ Object {
   "gitTagVersion": true,
   "global": false,
   "globalconfig": "{CWD}/global/etc/npmrc",
-  "hashAlgorithm": "sha1",
   "heading": "npm",
   "httpsProxy": null,
   "ifPresent": false,
@@ -2388,13 +2404,14 @@ Object {
   "nodeBin": "{NODE}",
   "nodeVersion": "2.2.2",
   "noProxy": "",
-  "npmBin": "{CWD}/{TESTDIR}/docs.js",
+  "npmBin": "{CWD}/other/bin/npm-cli.js",
   "npmCommand": "version",
   "npmVersion": "3.3.3",
   "npxCache": "{CWD}/cache/_npx",
   "offline": false,
   "omit": Array [],
   "omitLockfileRegistryResolved": false,
+  "os": null,
   "otp": null,
   "package": Array [],
   "packageLock": true,
@@ -2423,6 +2440,8 @@ Object {
   "save": true,
   "saveBundle": false,
   "savePrefix": "^",
+  "sbomFormat": null,
+  "sbomType": "library",
   "scope": "",
   "scriptShell": undefined,
   "search": Object {
@@ -2560,8 +2579,9 @@ npm audit [fix|signatures]
 
 Options:
 [--audit-level ] [--dry-run] [-f|--force]
-[--json] [--package-lock-only]
+[--json] [--package-lock-only] [--no-package-lock]
 [--omit  [--omit  ...]]
+[--include  [--include  ...]]
 [--foreground-scripts] [--ignore-scripts]
 [-w|--workspace  [-w|--workspace  ...]]
 [-ws|--workspaces] [--include-workspace-root] [--install-links]
@@ -2577,7 +2597,9 @@ npm audit [fix|signatures]
 #### \`force\`
 #### \`json\`
 #### \`package-lock-only\`
+#### \`package-lock\`
 #### \`omit\`
+#### \`include\`
 #### \`foreground-scripts\`
 #### \`ignore-scripts\`
 #### \`workspace\`
@@ -2649,6 +2671,7 @@ npm ci
 Options:
 [--install-strategy ] [--legacy-bundling]
 [--global-style] [--omit  [--omit  ...]]
+[--include  [--include  ...]]
 [--strict-peer-deps] [--foreground-scripts] [--ignore-scripts] [--no-audit]
 [--no-bin-links] [--no-fund] [--dry-run]
 [-w|--workspace  [-w|--workspace  ...]]
@@ -2668,6 +2691,7 @@ aliases: clean-install, ic, install-clean, isntall-clean
 #### \`legacy-bundling\`
 #### \`global-style\`
 #### \`omit\`
+#### \`include\`
 #### \`strict-peer-deps\`
 #### \`foreground-scripts\`
 #### \`ignore-scripts\`
@@ -2746,8 +2770,9 @@ npm dedupe
 Options:
 [--install-strategy ] [--legacy-bundling]
 [--global-style] [--strict-peer-deps] [--no-package-lock]
-[--omit  [--omit  ...]] [--ignore-scripts]
-[--no-audit] [--no-bin-links] [--no-fund] [--dry-run]
+[--omit  [--omit  ...]]
+[--include  [--include  ...]]
+[--ignore-scripts] [--no-audit] [--no-bin-links] [--no-fund] [--dry-run]
 [-w|--workspace  [-w|--workspace  ...]]
 [-ws|--workspaces] [--include-workspace-root] [--install-links]
 
@@ -2767,6 +2792,7 @@ alias: ddp
 #### \`strict-peer-deps\`
 #### \`package-lock\`
 #### \`omit\`
+#### \`include\`
 #### \`ignore-scripts\`
 #### \`audit\`
 #### \`bin-links\`
@@ -2892,7 +2918,7 @@ alias: home
 `
 
 exports[`test/lib/docs.js TAP usage doctor > must match snapshot 1`] = `
-Check your npm environment
+Check the health of your npm environment
 
 Usage:
 npm doctor [ping] [registry] [versions] [environment] [permissions] [cache]
@@ -3017,8 +3043,9 @@ npm find-dupes
 Options:
 [--install-strategy ] [--legacy-bundling]
 [--global-style] [--strict-peer-deps] [--no-package-lock]
-[--omit  [--omit  ...]] [--ignore-scripts]
-[--no-audit] [--no-bin-links] [--no-fund]
+[--omit  [--omit  ...]]
+[--include  [--include  ...]]
+[--ignore-scripts] [--no-audit] [--no-bin-links] [--no-fund]
 [-w|--workspace  [-w|--workspace  ...]]
 [-ws|--workspaces] [--include-workspace-root] [--install-links]
 
@@ -3034,6 +3061,7 @@ npm find-dupes
 #### \`strict-peer-deps\`
 #### \`package-lock\`
 #### \`omit\`
+#### \`include\`
 #### \`ignore-scripts\`
 #### \`audit\`
 #### \`bin-links\`
@@ -3167,7 +3195,9 @@ npm init  (same as \`npx \`)
 npm init <@scope> (same as \`npx <@scope>/create\`)
 
 Options:
-[-y|--yes] [-f|--force] [--scope <@scope>]
+[--init-author-name ] [--init-author-url ] [--init-license ]
+[--init-module ] [--init-version ] [-y|--yes] [-f|--force]
+[--scope <@scope>]
 [-w|--workspace  [-w|--workspace  ...]]
 [-ws|--workspaces] [--no-workspaces-update] [--include-workspace-root]
 
@@ -3182,6 +3212,11 @@ npm init <@scope> (same as \`npx <@scope>/create\`)
 aliases: create, innit
 \`\`\`
 
+#### \`init-author-name\`
+#### \`init-author-url\`
+#### \`init-license\`
+#### \`init-module\`
+#### \`init-version\`
 #### \`yes\`
 #### \`force\`
 #### \`scope\`
@@ -3202,9 +3237,10 @@ Options:
 [-E|--save-exact] [-g|--global]
 [--install-strategy ] [--legacy-bundling]
 [--global-style] [--omit  [--omit  ...]]
+[--include  [--include  ...]]
 [--strict-peer-deps] [--prefer-dedupe] [--no-package-lock] [--package-lock-only]
 [--foreground-scripts] [--ignore-scripts] [--no-audit] [--no-bin-links]
-[--no-fund] [--dry-run]
+[--no-fund] [--dry-run] [--cpu ] [--os ]
 [-w|--workspace  [-w|--workspace  ...]]
 [-ws|--workspaces] [--include-workspace-root] [--install-links]
 
@@ -3225,6 +3261,7 @@ aliases: add, i, in, ins, inst, insta, instal, isnt, isnta, isntal, isntall
 #### \`legacy-bundling\`
 #### \`global-style\`
 #### \`omit\`
+#### \`include\`
 #### \`strict-peer-deps\`
 #### \`prefer-dedupe\`
 #### \`package-lock\`
@@ -3235,6 +3272,8 @@ aliases: add, i, in, ins, inst, insta, instal, isnt, isnta, isntal, isntall
 #### \`bin-links\`
 #### \`fund\`
 #### \`dry-run\`
+#### \`cpu\`
+#### \`os\`
 #### \`workspace\`
 #### \`workspaces\`
 #### \`include-workspace-root\`
@@ -3250,6 +3289,7 @@ npm install-ci-test
 Options:
 [--install-strategy ] [--legacy-bundling]
 [--global-style] [--omit  [--omit  ...]]
+[--include  [--include  ...]]
 [--strict-peer-deps] [--foreground-scripts] [--ignore-scripts] [--no-audit]
 [--no-bin-links] [--no-fund] [--dry-run]
 [-w|--workspace  [-w|--workspace  ...]]
@@ -3269,6 +3309,7 @@ aliases: cit, clean-install-test, sit
 #### \`legacy-bundling\`
 #### \`global-style\`
 #### \`omit\`
+#### \`include\`
 #### \`strict-peer-deps\`
 #### \`foreground-scripts\`
 #### \`ignore-scripts\`
@@ -3293,9 +3334,10 @@ Options:
 [-E|--save-exact] [-g|--global]
 [--install-strategy ] [--legacy-bundling]
 [--global-style] [--omit  [--omit  ...]]
+[--include  [--include  ...]]
 [--strict-peer-deps] [--prefer-dedupe] [--no-package-lock] [--package-lock-only]
 [--foreground-scripts] [--ignore-scripts] [--no-audit] [--no-bin-links]
-[--no-fund] [--dry-run]
+[--no-fund] [--dry-run] [--cpu ] [--os ]
 [-w|--workspace  [-w|--workspace  ...]]
 [-ws|--workspaces] [--include-workspace-root] [--install-links]
 
@@ -3316,6 +3358,7 @@ alias: it
 #### \`legacy-bundling\`
 #### \`global-style\`
 #### \`omit\`
+#### \`include\`
 #### \`strict-peer-deps\`
 #### \`prefer-dedupe\`
 #### \`package-lock\`
@@ -3326,6 +3369,8 @@ alias: it
 #### \`bin-links\`
 #### \`fund\`
 #### \`dry-run\`
+#### \`cpu\`
+#### \`os\`
 #### \`workspace\`
 #### \`workspaces\`
 #### \`include-workspace-root\`
@@ -3343,8 +3388,9 @@ Options:
 [-E|--save-exact] [-g|--global]
 [--install-strategy ] [--legacy-bundling]
 [--global-style] [--strict-peer-deps] [--no-package-lock]
-[--omit  [--omit  ...]] [--ignore-scripts]
-[--no-audit] [--no-bin-links] [--no-fund] [--dry-run]
+[--omit  [--omit  ...]]
+[--include  [--include  ...]]
+[--ignore-scripts] [--no-audit] [--no-bin-links] [--no-fund] [--dry-run]
 [-w|--workspace  [-w|--workspace  ...]]
 [-ws|--workspaces] [--include-workspace-root] [--install-links]
 
@@ -3367,6 +3413,7 @@ alias: ln
 #### \`strict-peer-deps\`
 #### \`package-lock\`
 #### \`omit\`
+#### \`include\`
 #### \`ignore-scripts\`
 #### \`audit\`
 #### \`bin-links\`
@@ -3386,8 +3433,9 @@ npm ll [[<@scope>/] ...]
 
 Options:
 [-a|--all] [--json] [-l|--long] [-p|--parseable] [-g|--global] [--depth ]
-[--omit  [--omit  ...]] [--link]
-[--package-lock-only] [--unicode]
+[--omit  [--omit  ...]]
+[--include  [--include  ...]]
+[--link] [--package-lock-only] [--unicode]
 [-w|--workspace  [-w|--workspace  ...]]
 [-ws|--workspaces] [--include-workspace-root] [--install-links]
 
@@ -3408,6 +3456,7 @@ alias: la
 #### \`global\`
 #### \`depth\`
 #### \`omit\`
+#### \`include\`
 #### \`link\`
 #### \`package-lock-only\`
 #### \`unicode\`
@@ -3468,8 +3517,9 @@ npm ls 
 
 Options:
 [-a|--all] [--json] [-l|--long] [-p|--parseable] [-g|--global] [--depth ]
-[--omit  [--omit  ...]] [--link]
-[--package-lock-only] [--unicode]
+[--omit  [--omit  ...]]
+[--include  [--include  ...]]
+[--link] [--package-lock-only] [--unicode]
 [-w|--workspace  [-w|--workspace  ...]]
 [-ws|--workspaces] [--include-workspace-root] [--install-links]
 
@@ -3490,6 +3540,7 @@ alias: list
 #### \`global\`
 #### \`depth\`
 #### \`omit\`
+#### \`include\`
 #### \`link\`
 #### \`package-lock-only\`
 #### \`unicode\`
@@ -3740,8 +3791,9 @@ Usage:
 npm prune [[<@scope>/]...]
 
 Options:
-[--omit  [--omit  ...]] [--dry-run]
-[--json] [--foreground-scripts] [--ignore-scripts]
+[--omit  [--omit  ...]]
+[--include  [--include  ...]]
+[--dry-run] [--json] [--foreground-scripts] [--ignore-scripts]
 [-w|--workspace  [-w|--workspace  ...]]
 [-ws|--workspaces] [--include-workspace-root] [--install-links]
 
@@ -3752,6 +3804,7 @@ npm prune [[<@scope>/]...]
 \`\`\`
 
 #### \`omit\`
+#### \`include\`
 #### \`dry-run\`
 #### \`json\`
 #### \`foreground-scripts\`
@@ -3800,7 +3853,7 @@ npm query 
 Options:
 [-g|--global]
 [-w|--workspace  [-w|--workspace  ...]]
-[-ws|--workspaces] [--include-workspace-root]
+[-ws|--workspaces] [--include-workspace-root] [--package-lock-only]
 
 Run "npm help query" for more info
 
@@ -3812,6 +3865,7 @@ npm query 
 #### \`workspace\`
 #### \`workspaces\`
 #### \`include-workspace-root\`
+#### \`package-lock-only\`
 `
 
 exports[`test/lib/docs.js TAP usage rebuild > must match snapshot 1`] = `
@@ -3938,6 +3992,33 @@ aliases: run, rum, urn
 #### \`script-shell\`
 `
 
+exports[`test/lib/docs.js TAP usage sbom > must match snapshot 1`] = `
+Generate a Software Bill of Materials (SBOM)
+
+Usage:
+npm sbom
+
+Options:
+[--omit  [--omit  ...]]
+[--package-lock-only] [--sbom-format ]
+[--sbom-type ]
+[-w|--workspace  [-w|--workspace  ...]]
+[-ws|--workspaces]
+
+Run "npm help sbom" for more info
+
+\`\`\`bash
+npm sbom
+\`\`\`
+
+#### \`omit\`
+#### \`package-lock-only\`
+#### \`sbom-format\`
+#### \`sbom-type\`
+#### \`workspace\`
+#### \`workspaces\`
+`
+
 exports[`test/lib/docs.js TAP usage search > must match snapshot 1`] = `
 Search for packages
 
@@ -4260,6 +4341,7 @@ Options:
 [-g|--global] [--install-strategy ]
 [--legacy-bundling] [--global-style]
 [--omit  [--omit  ...]]
+[--include  [--include  ...]]
 [--strict-peer-deps] [--no-package-lock] [--foreground-scripts]
 [--ignore-scripts] [--no-audit] [--no-bin-links] [--no-fund] [--dry-run]
 [-w|--workspace  [-w|--workspace  ...]]
@@ -4281,6 +4363,7 @@ aliases: up, upgrade, udpate
 #### \`legacy-bundling\`
 #### \`global-style\`
 #### \`omit\`
+#### \`include\`
 #### \`strict-peer-deps\`
 #### \`package-lock\`
 #### \`foreground-scripts\`
diff --git a/deps/npm/tap-snapshots/test/lib/npm.js.test.cjs b/deps/npm/tap-snapshots/test/lib/npm.js.test.cjs
index 7bebf9b78f2bb4..e29061291137eb 100644
--- a/deps/npm/tap-snapshots/test/lib/npm.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/npm.js.test.cjs
@@ -27,10 +27,10 @@ All commands:
     help-search, hook, init, install, install-ci-test,
     install-test, link, ll, login, logout, ls, org, outdated,
     owner, pack, ping, pkg, prefix, profile, prune, publish,
-    query, rebuild, repo, restart, root, run-script, search,
-    set, shrinkwrap, star, stars, start, stop, team, test,
-    token, uninstall, unpublish, unstar, update, version, view,
-    whoami
+    query, rebuild, repo, restart, root, run-script, sbom,
+    search, set, shrinkwrap, star, stars, start, stop, team,
+    test, token, uninstall, unpublish, unstar, update, version,
+    view, whoami
 
 Specify configs in the ini-formatted file:
     {USERCONFIG}
@@ -76,13 +76,13 @@ All commands:
     profile, prune, publish,
     query, rebuild, repo,
     restart, root,
-    run-script, search, set,
-    shrinkwrap, star, stars,
-    start, stop, team, test,
-    token, uninstall,
-    unpublish, unstar,
-    update, version, view,
-    whoami
+    run-script, sbom,
+    search, set, shrinkwrap,
+    star, stars, start,
+    stop, team, test, token,
+    uninstall, unpublish,
+    unstar, update, version,
+    view, whoami
 
 Specify configs in the ini-formatted file:
     {USERCONFIG}
@@ -128,13 +128,13 @@ All commands:
     profile, prune, publish,
     query, rebuild, repo,
     restart, root,
-    run-script, search, set,
-    shrinkwrap, star, stars,
-    start, stop, team, test,
-    token, uninstall,
-    unpublish, unstar,
-    update, version, view,
-    whoami
+    run-script, sbom,
+    search, set, shrinkwrap,
+    star, stars, start,
+    stop, team, test, token,
+    uninstall, unpublish,
+    unstar, update, version,
+    view, whoami
 
 Specify configs in the ini-formatted file:
     {USERCONFIG}
@@ -168,10 +168,10 @@ All commands:
     help-search, hook, init, install, install-ci-test,
     install-test, link, ll, login, logout, ls, org, outdated,
     owner, pack, ping, pkg, prefix, profile, prune, publish,
-    query, rebuild, repo, restart, root, run-script, search,
-    set, shrinkwrap, star, stars, start, stop, team, test,
-    token, uninstall, unpublish, unstar, update, version, view,
-    whoami
+    query, rebuild, repo, restart, root, run-script, sbom,
+    search, set, shrinkwrap, star, stars, start, stop, team,
+    test, token, uninstall, unpublish, unstar, update, version,
+    view, whoami
 
 Specify configs in the ini-formatted file:
     {USERCONFIG}
@@ -217,13 +217,13 @@ All commands:
     profile, prune, publish,
     query, rebuild, repo,
     restart, root,
-    run-script, search, set,
-    shrinkwrap, star, stars,
-    start, stop, team, test,
-    token, uninstall,
-    unpublish, unstar,
-    update, version, view,
-    whoami
+    run-script, sbom,
+    search, set, shrinkwrap,
+    star, stars, start,
+    stop, team, test, token,
+    uninstall, unpublish,
+    unstar, update, version,
+    view, whoami
 
 Specify configs in the ini-formatted file:
     {USERCONFIG}
@@ -269,13 +269,13 @@ All commands:
     profile, prune, publish,
     query, rebuild, repo,
     restart, root,
-    run-script, search, set,
-    shrinkwrap, star, stars,
-    start, stop, team, test,
-    token, uninstall,
-    unpublish, unstar,
-    update, version, view,
-    whoami
+    run-script, sbom,
+    search, set, shrinkwrap,
+    star, stars, start,
+    stop, team, test, token,
+    uninstall, unpublish,
+    unstar, update, version,
+    view, whoami
 
 Specify configs in the ini-formatted file:
     {USERCONFIG}
@@ -320,10 +320,10 @@ All commands:
     profile, prune, publish,
     query, rebuild, repo,
     restart, root,
-    run-script, search, set,
-    shrinkwrap, star, stars,
-    start, stop, team, test,
-    token, uninstall,
+    run-script, sbom, search,
+    set, shrinkwrap, star,
+    stars, start, stop, team,
+    test, token, uninstall,
     unpublish, unstar,
     update, version, view,
     whoami
@@ -360,10 +360,10 @@ All commands:
     help-search, hook, init, install, install-ci-test,
     install-test, link, ll, login, logout, ls, org, outdated,
     owner, pack, ping, pkg, prefix, profile, prune, publish,
-    query, rebuild, repo, restart, root, run-script, search,
-    set, shrinkwrap, star, stars, start, stop, team, test,
-    token, uninstall, unpublish, unstar, update, version, view,
-    whoami
+    query, rebuild, repo, restart, root, run-script, sbom,
+    search, set, shrinkwrap, star, stars, start, stop, team,
+    test, token, uninstall, unpublish, unstar, update, version,
+    view, whoami
 
 Specify configs in the ini-formatted file:
     {USERCONFIG}
@@ -397,10 +397,10 @@ All commands:
     help-search, hook, init, install, install-ci-test,
     install-test, link, ll, login, logout, ls, org, outdated,
     owner, pack, ping, pkg, prefix, profile, prune, publish,
-    query, rebuild, repo, restart, root, run-script, search,
-    set, shrinkwrap, star, stars, start, stop, team, test,
-    token, uninstall, unpublish, unstar, update, version, view,
-    whoami
+    query, rebuild, repo, restart, root, run-script, sbom,
+    search, set, shrinkwrap, star, stars, start, stop, team,
+    test, token, uninstall, unpublish, unstar, update, version,
+    view, whoami
 
 Specify configs in the ini-formatted file:
     {USERCONFIG}
@@ -434,10 +434,10 @@ All commands:
     help-search, hook, init, install, install-ci-test,
     install-test, link, ll, login, logout, ls, org, outdated,
     owner, pack, ping, pkg, prefix, profile, prune, publish,
-    query, rebuild, repo, restart, root, run-script, search,
-    set, shrinkwrap, star, stars, start, stop, team, test,
-    token, uninstall, unpublish, unstar, update, version, view,
-    whoami
+    query, rebuild, repo, restart, root, run-script, sbom,
+    search, set, shrinkwrap, star, stars, start, stop, team,
+    test, token, uninstall, unpublish, unstar, update, version,
+    view, whoami
 
 Specify configs in the ini-formatted file:
     {USERCONFIG}
diff --git a/deps/npm/tap-snapshots/test/lib/utils/error-message.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/error-message.js.test.cjs
index 1cd3d4cf1ac567..fe581fb6beb291 100644
--- a/deps/npm/tap-snapshots/test/lib/utils/error-message.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/utils/error-message.js.test.cjs
@@ -1137,7 +1137,7 @@ Object {
     Array [
       "",
       String(
-        To correct this please trying logging in again with:
+        To correct this please try logging in again with:
             npm login
       ),
     ],
diff --git a/deps/npm/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs
index 93711275392339..3e7bc4570dd4ad 100644
--- a/deps/npm/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs
+++ b/deps/npm/tap-snapshots/test/lib/utils/exit-handler.js.test.cjs
@@ -63,4 +63,5 @@ verbose exit 1
 timing npm Completed in {TIME}ms
 verbose code 1
 error  A complete log of this run can be found in: {CWD}/cache/_logs/{DATE}-debug-0.log
+silly logfile done cleaning log files
 `
diff --git a/deps/npm/tap-snapshots/test/lib/utils/sbom-cyclonedx.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/sbom-cyclonedx.js.test.cjs
new file mode 100644
index 00000000000000..878dfd4be4705b
--- /dev/null
+++ b/deps/npm/tap-snapshots/test/lib/utils/sbom-cyclonedx.js.test.cjs
@@ -0,0 +1,1021 @@
+/* IMPORTANT
+ * This snapshot file is auto-generated, but designed for humans.
+ * It should be checked into source control and tracked carefully.
+ * Re-generate by setting TAP_SNAPSHOT=1 and running tests.
+ * Make sure to inspect the output below.  Do not ignore changes!
+ */
+'use strict'
+exports[`test/lib/utils/sbom-cyclonedx.js TAP node - with deps > must match snapshot 1`] = `
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.5",
+  "serialNumber": "urn:uuid:00000000-0000-0000-0000-000000000000",
+  "version": 1,
+  "metadata": {
+    "timestamp": "2020-01-01T00:00:00.000Z",
+    "lifecycles": [
+      {
+        "phase": "build"
+      }
+    ],
+    "tools": [
+      {
+        "vendor": "npm",
+        "name": "cli",
+        "version": "10.0.0 "
+      }
+    ],
+    "component": {
+      "bom-ref": "root@1.0.0",
+      "type": "library",
+      "name": "root",
+      "version": "1.0.0",
+      "scope": "required",
+      "author": "Author",
+      "purl": "pkg:npm/root@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": ""
+        }
+      ],
+      "externalReferences": []
+    }
+  },
+  "components": [
+    {
+      "bom-ref": "dep1@0.0.1",
+      "type": "library",
+      "name": "dep1",
+      "version": "0.0.1",
+      "scope": "required",
+      "purl": "pkg:npm/dep1@0.0.1",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": "node_modules/dep1"
+        }
+      ],
+      "externalReferences": []
+    },
+    {
+      "bom-ref": "dep2@0.0.2",
+      "type": "library",
+      "name": "dep2",
+      "version": "0.0.2",
+      "scope": "required",
+      "purl": "pkg:npm/dep2@0.0.2",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": "node_modules/dep2"
+        }
+      ],
+      "externalReferences": []
+    }
+  ],
+  "dependencies": [
+    {
+      "ref": "root@1.0.0",
+      "dependsOn": [
+        "dep1@0.0.1",
+        "dep2@0.0.2"
+      ]
+    },
+    {
+      "ref": "dep1@0.0.1",
+      "dependsOn": []
+    },
+    {
+      "ref": "dep2@0.0.2",
+      "dependsOn": [
+        "dep1@0.0.1"
+      ]
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-cyclonedx.js TAP single node - application package type > must match snapshot 1`] = `
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.5",
+  "serialNumber": "urn:uuid:00000000-0000-0000-0000-000000000000",
+  "version": 1,
+  "metadata": {
+    "timestamp": "2020-01-01T00:00:00.000Z",
+    "lifecycles": [
+      {
+        "phase": "build"
+      }
+    ],
+    "tools": [
+      {
+        "vendor": "npm",
+        "name": "cli",
+        "version": "10.0.0 "
+      }
+    ],
+    "component": {
+      "bom-ref": "root@1.0.0",
+      "type": "application",
+      "name": "root",
+      "version": "1.0.0",
+      "scope": "required",
+      "author": "Author",
+      "purl": "pkg:npm/root@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": ""
+        }
+      ],
+      "externalReferences": []
+    }
+  },
+  "components": [],
+  "dependencies": [
+    {
+      "ref": "root@1.0.0",
+      "dependsOn": []
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-cyclonedx.js TAP single node - bundled > must match snapshot 1`] = `
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.5",
+  "serialNumber": "urn:uuid:00000000-0000-0000-0000-000000000000",
+  "version": 1,
+  "metadata": {
+    "timestamp": "2020-01-01T00:00:00.000Z",
+    "lifecycles": [
+      {
+        "phase": "build"
+      }
+    ],
+    "tools": [
+      {
+        "vendor": "npm",
+        "name": "cli",
+        "version": "10.0.0 "
+      }
+    ],
+    "component": {
+      "bom-ref": "root@1.0.0",
+      "type": "library",
+      "name": "root",
+      "version": "1.0.0",
+      "scope": "required",
+      "author": "Author",
+      "purl": "pkg:npm/root@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": ""
+        },
+        {
+          "name": "cdx:npm:package:bundled",
+          "value": "true"
+        }
+      ],
+      "externalReferences": []
+    }
+  },
+  "components": [],
+  "dependencies": [
+    {
+      "ref": "root@1.0.0",
+      "dependsOn": []
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-cyclonedx.js TAP single node - development > must match snapshot 1`] = `
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.5",
+  "serialNumber": "urn:uuid:00000000-0000-0000-0000-000000000000",
+  "version": 1,
+  "metadata": {
+    "timestamp": "2020-01-01T00:00:00.000Z",
+    "lifecycles": [
+      {
+        "phase": "build"
+      }
+    ],
+    "tools": [
+      {
+        "vendor": "npm",
+        "name": "cli",
+        "version": "10.0.0 "
+      }
+    ],
+    "component": {
+      "bom-ref": "root@1.0.0",
+      "type": "library",
+      "name": "root",
+      "version": "1.0.0",
+      "scope": "required",
+      "author": "Author",
+      "purl": "pkg:npm/root@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": ""
+        },
+        {
+          "name": "cdx:npm:package:development",
+          "value": "true"
+        }
+      ],
+      "externalReferences": []
+    }
+  },
+  "components": [],
+  "dependencies": [
+    {
+      "ref": "root@1.0.0",
+      "dependsOn": []
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-cyclonedx.js TAP single node - extraneous > must match snapshot 1`] = `
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.5",
+  "serialNumber": "urn:uuid:00000000-0000-0000-0000-000000000000",
+  "version": 1,
+  "metadata": {
+    "timestamp": "2020-01-01T00:00:00.000Z",
+    "lifecycles": [
+      {
+        "phase": "build"
+      }
+    ],
+    "tools": [
+      {
+        "vendor": "npm",
+        "name": "cli",
+        "version": "10.0.0 "
+      }
+    ],
+    "component": {
+      "bom-ref": "root@1.0.0",
+      "type": "library",
+      "name": "root",
+      "version": "1.0.0",
+      "scope": "required",
+      "author": "Author",
+      "purl": "pkg:npm/root@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": ""
+        },
+        {
+          "name": "cdx:npm:package:extraneous",
+          "value": "true"
+        }
+      ],
+      "externalReferences": []
+    }
+  },
+  "components": [],
+  "dependencies": [
+    {
+      "ref": "root@1.0.0",
+      "dependsOn": []
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-cyclonedx.js TAP single node - from git url > must match snapshot 1`] = `
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.5",
+  "serialNumber": "urn:uuid:00000000-0000-0000-0000-000000000000",
+  "version": 1,
+  "metadata": {
+    "timestamp": "2020-01-01T00:00:00.000Z",
+    "lifecycles": [
+      {
+        "phase": "build"
+      }
+    ],
+    "tools": [
+      {
+        "vendor": "npm",
+        "name": "cli",
+        "version": "10.0.0 "
+      }
+    ],
+    "component": {
+      "bom-ref": "root@1.0.0",
+      "type": "library",
+      "name": "root",
+      "version": "1.0.0",
+      "scope": "required",
+      "author": "Author",
+      "purl": "pkg:npm/root@1.0.0?vcs_url=https://github.com/foo/bar#1234",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": ""
+        }
+      ],
+      "externalReferences": [
+        {
+          "type": "distribution",
+          "url": "https://github.com/foo/bar#1234"
+        }
+      ]
+    }
+  },
+  "components": [],
+  "dependencies": [
+    {
+      "ref": "root@1.0.0",
+      "dependsOn": []
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-cyclonedx.js TAP single node - no package info > must match snapshot 1`] = `
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.5",
+  "serialNumber": "urn:uuid:00000000-0000-0000-0000-000000000000",
+  "version": 1,
+  "metadata": {
+    "timestamp": "2020-01-01T00:00:00.000Z",
+    "lifecycles": [
+      {
+        "phase": "build"
+      }
+    ],
+    "tools": [
+      {
+        "vendor": "npm",
+        "name": "cli",
+        "version": "10.0.0 "
+      }
+    ],
+    "component": {
+      "bom-ref": "root@1.0.0",
+      "type": "library",
+      "name": "root",
+      "version": "1.0.0",
+      "scope": "required",
+      "purl": "pkg:npm/root@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": ""
+        }
+      ],
+      "externalReferences": []
+    }
+  },
+  "components": [],
+  "dependencies": [
+    {
+      "ref": "root@1.0.0",
+      "dependsOn": []
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-cyclonedx.js TAP single node - optional > must match snapshot 1`] = `
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.5",
+  "serialNumber": "urn:uuid:00000000-0000-0000-0000-000000000000",
+  "version": 1,
+  "metadata": {
+    "timestamp": "2020-01-01T00:00:00.000Z",
+    "lifecycles": [
+      {
+        "phase": "build"
+      }
+    ],
+    "tools": [
+      {
+        "vendor": "npm",
+        "name": "cli",
+        "version": "10.0.0 "
+      }
+    ],
+    "component": {
+      "bom-ref": "root@1.0.0",
+      "type": "library",
+      "name": "root",
+      "version": "1.0.0",
+      "scope": "optional",
+      "author": "Author",
+      "purl": "pkg:npm/root@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": ""
+        }
+      ],
+      "externalReferences": []
+    }
+  },
+  "components": [],
+  "dependencies": [
+    {
+      "ref": "root@1.0.0",
+      "dependsOn": []
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-cyclonedx.js TAP single node - package lock only > must match snapshot 1`] = `
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.5",
+  "serialNumber": "urn:uuid:00000000-0000-0000-0000-000000000000",
+  "version": 1,
+  "metadata": {
+    "timestamp": "2020-01-01T00:00:00.000Z",
+    "lifecycles": [
+      {
+        "phase": "pre-build"
+      }
+    ],
+    "tools": [
+      {
+        "vendor": "npm",
+        "name": "cli",
+        "version": "10.0.0 "
+      }
+    ],
+    "component": {
+      "bom-ref": "root@1.0.0",
+      "type": "library",
+      "name": "root",
+      "version": "1.0.0",
+      "scope": "required",
+      "author": "Author",
+      "purl": "pkg:npm/root@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": ""
+        }
+      ],
+      "externalReferences": []
+    }
+  },
+  "components": [],
+  "dependencies": [
+    {
+      "ref": "root@1.0.0",
+      "dependsOn": []
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-cyclonedx.js TAP single node - private > must match snapshot 1`] = `
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.5",
+  "serialNumber": "urn:uuid:00000000-0000-0000-0000-000000000000",
+  "version": 1,
+  "metadata": {
+    "timestamp": "2020-01-01T00:00:00.000Z",
+    "lifecycles": [
+      {
+        "phase": "build"
+      }
+    ],
+    "tools": [
+      {
+        "vendor": "npm",
+        "name": "cli",
+        "version": "10.0.0 "
+      }
+    ],
+    "component": {
+      "bom-ref": "root@1.0.0",
+      "type": "library",
+      "name": "root",
+      "version": "1.0.0",
+      "scope": "required",
+      "author": "Author",
+      "purl": "pkg:npm/root@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": ""
+        },
+        {
+          "name": "cdx:npm:package:private",
+          "value": "true"
+        }
+      ],
+      "externalReferences": []
+    }
+  },
+  "components": [],
+  "dependencies": [
+    {
+      "ref": "root@1.0.0",
+      "dependsOn": []
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-cyclonedx.js TAP single node - with author object > must match snapshot 1`] = `
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.5",
+  "serialNumber": "urn:uuid:00000000-0000-0000-0000-000000000000",
+  "version": 1,
+  "metadata": {
+    "timestamp": "2020-01-01T00:00:00.000Z",
+    "lifecycles": [
+      {
+        "phase": "build"
+      }
+    ],
+    "tools": [
+      {
+        "vendor": "npm",
+        "name": "cli",
+        "version": "10.0.0 "
+      }
+    ],
+    "component": {
+      "bom-ref": "root@1.0.0",
+      "type": "library",
+      "name": "root",
+      "version": "1.0.0",
+      "scope": "required",
+      "author": "Arthur",
+      "purl": "pkg:npm/root@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": ""
+        }
+      ],
+      "externalReferences": []
+    }
+  },
+  "components": [],
+  "dependencies": [
+    {
+      "ref": "root@1.0.0",
+      "dependsOn": []
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-cyclonedx.js TAP single node - with description > must match snapshot 1`] = `
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.5",
+  "serialNumber": "urn:uuid:00000000-0000-0000-0000-000000000000",
+  "version": 1,
+  "metadata": {
+    "timestamp": "2020-01-01T00:00:00.000Z",
+    "lifecycles": [
+      {
+        "phase": "build"
+      }
+    ],
+    "tools": [
+      {
+        "vendor": "npm",
+        "name": "cli",
+        "version": "10.0.0 "
+      }
+    ],
+    "component": {
+      "bom-ref": "root@1.0.0",
+      "type": "library",
+      "name": "root",
+      "version": "1.0.0",
+      "scope": "required",
+      "author": "Author",
+      "description": "Package description",
+      "purl": "pkg:npm/root@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": ""
+        }
+      ],
+      "externalReferences": []
+    }
+  },
+  "components": [],
+  "dependencies": [
+    {
+      "ref": "root@1.0.0",
+      "dependsOn": []
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-cyclonedx.js TAP single node - with distribution url > must match snapshot 1`] = `
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.5",
+  "serialNumber": "urn:uuid:00000000-0000-0000-0000-000000000000",
+  "version": 1,
+  "metadata": {
+    "timestamp": "2020-01-01T00:00:00.000Z",
+    "lifecycles": [
+      {
+        "phase": "build"
+      }
+    ],
+    "tools": [
+      {
+        "vendor": "npm",
+        "name": "cli",
+        "version": "10.0.0 "
+      }
+    ],
+    "component": {
+      "bom-ref": "root@1.0.0",
+      "type": "library",
+      "name": "root",
+      "version": "1.0.0",
+      "scope": "required",
+      "author": "Author",
+      "purl": "pkg:npm/root@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": ""
+        }
+      ],
+      "externalReferences": [
+        {
+          "type": "distribution",
+          "url": "https://registry.npmjs.org/root/-/root-1.0.0.tgz"
+        }
+      ]
+    }
+  },
+  "components": [],
+  "dependencies": [
+    {
+      "ref": "root@1.0.0",
+      "dependsOn": []
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-cyclonedx.js TAP single node - with homepage > must match snapshot 1`] = `
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.5",
+  "serialNumber": "urn:uuid:00000000-0000-0000-0000-000000000000",
+  "version": 1,
+  "metadata": {
+    "timestamp": "2020-01-01T00:00:00.000Z",
+    "lifecycles": [
+      {
+        "phase": "build"
+      }
+    ],
+    "tools": [
+      {
+        "vendor": "npm",
+        "name": "cli",
+        "version": "10.0.0 "
+      }
+    ],
+    "component": {
+      "bom-ref": "root@1.0.0",
+      "type": "library",
+      "name": "root",
+      "version": "1.0.0",
+      "scope": "required",
+      "author": "Author",
+      "purl": "pkg:npm/root@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": ""
+        }
+      ],
+      "externalReferences": [
+        {
+          "type": "website",
+          "url": "https://foo.bar/README.md"
+        }
+      ]
+    }
+  },
+  "components": [],
+  "dependencies": [
+    {
+      "ref": "root@1.0.0",
+      "dependsOn": []
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-cyclonedx.js TAP single node - with integrity > must match snapshot 1`] = `
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.5",
+  "serialNumber": "urn:uuid:00000000-0000-0000-0000-000000000000",
+  "version": 1,
+  "metadata": {
+    "timestamp": "2020-01-01T00:00:00.000Z",
+    "lifecycles": [
+      {
+        "phase": "build"
+      }
+    ],
+    "tools": [
+      {
+        "vendor": "npm",
+        "name": "cli",
+        "version": "10.0.0 "
+      }
+    ],
+    "component": {
+      "bom-ref": "root@1.0.0",
+      "type": "library",
+      "name": "root",
+      "version": "1.0.0",
+      "scope": "required",
+      "author": "Author",
+      "purl": "pkg:npm/root@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": ""
+        }
+      ],
+      "externalReferences": [],
+      "hashes": [
+        {
+          "alg": "SHA-512",
+          "content": "d5191b14650a7b1e25bec07dca121f5a5b493397192947ed07678d6a3683bf7742304a78f62046d0ad78b87f0d9d7f483eec76fa62bb24610e0748e7e3cfc9eb"
+        }
+      ]
+    }
+  },
+  "components": [],
+  "dependencies": [
+    {
+      "ref": "root@1.0.0",
+      "dependsOn": []
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-cyclonedx.js TAP single node - with issue tracker > must match snapshot 1`] = `
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.5",
+  "serialNumber": "urn:uuid:00000000-0000-0000-0000-000000000000",
+  "version": 1,
+  "metadata": {
+    "timestamp": "2020-01-01T00:00:00.000Z",
+    "lifecycles": [
+      {
+        "phase": "build"
+      }
+    ],
+    "tools": [
+      {
+        "vendor": "npm",
+        "name": "cli",
+        "version": "10.0.0 "
+      }
+    ],
+    "component": {
+      "bom-ref": "root@1.0.0",
+      "type": "library",
+      "name": "root",
+      "version": "1.0.0",
+      "scope": "required",
+      "author": "Author",
+      "purl": "pkg:npm/root@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": ""
+        }
+      ],
+      "externalReferences": [
+        {
+          "type": "issue-tracker",
+          "url": "https://foo.bar/issues"
+        }
+      ]
+    }
+  },
+  "components": [],
+  "dependencies": [
+    {
+      "ref": "root@1.0.0",
+      "dependsOn": []
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-cyclonedx.js TAP single node - with license expression > must match snapshot 1`] = `
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.5",
+  "serialNumber": "urn:uuid:00000000-0000-0000-0000-000000000000",
+  "version": 1,
+  "metadata": {
+    "timestamp": "2020-01-01T00:00:00.000Z",
+    "lifecycles": [
+      {
+        "phase": "build"
+      }
+    ],
+    "tools": [
+      {
+        "vendor": "npm",
+        "name": "cli",
+        "version": "10.0.0 "
+      }
+    ],
+    "component": {
+      "bom-ref": "root@1.0.0",
+      "type": "library",
+      "name": "root",
+      "version": "1.0.0",
+      "scope": "required",
+      "author": "Author",
+      "purl": "pkg:npm/root@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": ""
+        }
+      ],
+      "externalReferences": [],
+      "licenses": [
+        {
+          "expression": "(MIT OR Apache-2.0)"
+        }
+      ]
+    }
+  },
+  "components": [],
+  "dependencies": [
+    {
+      "ref": "root@1.0.0",
+      "dependsOn": []
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-cyclonedx.js TAP single node - with repository url > must match snapshot 1`] = `
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.5",
+  "serialNumber": "urn:uuid:00000000-0000-0000-0000-000000000000",
+  "version": 1,
+  "metadata": {
+    "timestamp": "2020-01-01T00:00:00.000Z",
+    "lifecycles": [
+      {
+        "phase": "build"
+      }
+    ],
+    "tools": [
+      {
+        "vendor": "npm",
+        "name": "cli",
+        "version": "10.0.0 "
+      }
+    ],
+    "component": {
+      "bom-ref": "root@1.0.0",
+      "type": "library",
+      "name": "root",
+      "version": "1.0.0",
+      "scope": "required",
+      "author": "Author",
+      "purl": "pkg:npm/root@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": ""
+        }
+      ],
+      "externalReferences": [
+        {
+          "type": "vcs",
+          "url": "https://foo.bar"
+        }
+      ]
+    }
+  },
+  "components": [],
+  "dependencies": [
+    {
+      "ref": "root@1.0.0",
+      "dependsOn": []
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-cyclonedx.js TAP single node - with single license > must match snapshot 1`] = `
+{
+  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+  "bomFormat": "CycloneDX",
+  "specVersion": "1.5",
+  "serialNumber": "urn:uuid:00000000-0000-0000-0000-000000000000",
+  "version": 1,
+  "metadata": {
+    "timestamp": "2020-01-01T00:00:00.000Z",
+    "lifecycles": [
+      {
+        "phase": "build"
+      }
+    ],
+    "tools": [
+      {
+        "vendor": "npm",
+        "name": "cli",
+        "version": "10.0.0 "
+      }
+    ],
+    "component": {
+      "bom-ref": "root@1.0.0",
+      "type": "library",
+      "name": "root",
+      "version": "1.0.0",
+      "scope": "required",
+      "author": "Author",
+      "purl": "pkg:npm/root@1.0.0",
+      "properties": [
+        {
+          "name": "cdx:npm:package:path",
+          "value": ""
+        }
+      ],
+      "externalReferences": [],
+      "licenses": [
+        {
+          "license": {
+            "id": "ISC"
+          }
+        }
+      ]
+    }
+  },
+  "components": [],
+  "dependencies": [
+    {
+      "ref": "root@1.0.0",
+      "dependsOn": []
+    }
+  ]
+}
+`
diff --git a/deps/npm/tap-snapshots/test/lib/utils/sbom-spdx.js.test.cjs b/deps/npm/tap-snapshots/test/lib/utils/sbom-spdx.js.test.cjs
new file mode 100644
index 00000000000000..890bd29b7d2639
--- /dev/null
+++ b/deps/npm/tap-snapshots/test/lib/utils/sbom-spdx.js.test.cjs
@@ -0,0 +1,506 @@
+/* IMPORTANT
+ * This snapshot file is auto-generated, but designed for humans.
+ * It should be checked into source control and tracked carefully.
+ * Re-generate by setting TAP_SNAPSHOT=1 and running tests.
+ * Make sure to inspect the output below.  Do not ignore changes!
+ */
+'use strict'
+exports[`test/lib/utils/sbom-spdx.js TAP node - with deps > must match snapshot 1`] = `
+{
+  "spdxVersion": "SPDX-2.3",
+  "dataLicense": "CC0-1.0",
+  "SPDXID": "SPDXRef-DOCUMENT",
+  "name": "root@1.0.0",
+  "documentNamespace": "docns",
+  "creationInfo": {
+    "created": "2020-01-01T00:00:00.000Z",
+    "creators": [
+      "Tool: npm/cli-10.0.0 "
+    ]
+  },
+  "documentDescribes": [
+    "SPDXRef-Package-root-1.0.0"
+  ],
+  "packages": [
+    {
+      "name": "root",
+      "SPDXID": "SPDXRef-Package-root-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/root@1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "dep1",
+      "SPDXID": "SPDXRef-Package-dep1-0.0.1",
+      "versionInfo": "0.0.1",
+      "packageFileName": "node_modules/dep1",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/dep1@0.0.1"
+        }
+      ]
+    },
+    {
+      "name": "dep2",
+      "SPDXID": "SPDXRef-Package-dep2-0.0.2",
+      "versionInfo": "0.0.2",
+      "packageFileName": "node_modules/dep2",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/dep2@0.0.2"
+        }
+      ]
+    },
+    {
+      "name": "dep3",
+      "SPDXID": "SPDXRef-Package-dep3-0.0.3",
+      "versionInfo": "0.0.3",
+      "packageFileName": "node_modules/dep3",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/dep3@0.0.3"
+        }
+      ]
+    },
+    {
+      "name": "dep4",
+      "SPDXID": "SPDXRef-Package-dep4-0.0.4",
+      "versionInfo": "0.0.4",
+      "packageFileName": "node_modules/dep4",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/dep4@0.0.4"
+        }
+      ]
+    },
+    {
+      "name": "dep5",
+      "SPDXID": "SPDXRef-Package-dep5-0.0.5",
+      "versionInfo": "0.0.5",
+      "packageFileName": "node_modules/dep5",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/dep5@0.0.5"
+        }
+      ]
+    },
+    {
+      "name": "dep6",
+      "SPDXID": "SPDXRef-Package-dep6-0.0.6",
+      "versionInfo": "0.0.6",
+      "packageFileName": "node_modules/dep6",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/dep6@0.0.6"
+        }
+      ]
+    }
+  ],
+  "relationships": [
+    {
+      "spdxElementId": "SPDXRef-DOCUMENT",
+      "relatedSpdxElement": "SPDXRef-Package-root-1.0.0",
+      "relationshipType": "DESCRIBES"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-root-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-dep1-0.0.1",
+      "relationshipType": "HAS_PREREQUISITE"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-root-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-dep2-0.0.2",
+      "relationshipType": "OPTIONAL_DEPENDENCY_OF"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-root-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-dep3-0.0.3",
+      "relationshipType": "DEV_DEPENDENCY_OF"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-root-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-dep4-0.0.4",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-dep4-0.0.4",
+      "relatedSpdxElement": "SPDXRef-Package-dep5-0.0.5",
+      "relationshipType": "DEPENDS_ON"
+    },
+    {
+      "spdxElementId": "SPDXRef-Package-root-1.0.0",
+      "relatedSpdxElement": "SPDXRef-Package-dep6-0.0.6",
+      "relationshipType": "OPTIONAL_DEPENDENCY_OF"
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-spdx.js TAP single node - application package type > must match snapshot 1`] = `
+{
+  "spdxVersion": "SPDX-2.3",
+  "dataLicense": "CC0-1.0",
+  "SPDXID": "SPDXRef-DOCUMENT",
+  "name": "root@1.0.0",
+  "documentNamespace": "docns",
+  "creationInfo": {
+    "created": "2020-01-01T00:00:00.000Z",
+    "creators": [
+      "Tool: npm/cli-10.0.0 "
+    ]
+  },
+  "documentDescribes": [
+    "SPDXRef-Package-root-1.0.0"
+  ],
+  "packages": [
+    {
+      "name": "root",
+      "SPDXID": "SPDXRef-Package-root-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "",
+      "primaryPackagePurpose": "APPLICATION",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/root@1.0.0"
+        }
+      ]
+    }
+  ],
+  "relationships": [
+    {
+      "spdxElementId": "SPDXRef-DOCUMENT",
+      "relatedSpdxElement": "SPDXRef-Package-root-1.0.0",
+      "relationshipType": "DESCRIBES"
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-spdx.js TAP single node - from git url > must match snapshot 1`] = `
+{
+  "spdxVersion": "SPDX-2.3",
+  "dataLicense": "CC0-1.0",
+  "SPDXID": "SPDXRef-DOCUMENT",
+  "name": "root@1.0.0",
+  "documentNamespace": "docns",
+  "creationInfo": {
+    "created": "2020-01-01T00:00:00.000Z",
+    "creators": [
+      "Tool: npm/cli-10.0.0 "
+    ]
+  },
+  "documentDescribes": [
+    "SPDXRef-Package-root-1.0.0"
+  ],
+  "packages": [
+    {
+      "name": "root",
+      "SPDXID": "SPDXRef-Package-root-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "",
+      "downloadLocation": "https://github.com/foo/bar#1234",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/root@1.0.0?vcs_url=https://github.com/foo/bar#1234"
+        }
+      ]
+    }
+  ],
+  "relationships": [
+    {
+      "spdxElementId": "SPDXRef-DOCUMENT",
+      "relatedSpdxElement": "SPDXRef-Package-root-1.0.0",
+      "relationshipType": "DESCRIBES"
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-spdx.js TAP single node - linked > must match snapshot 1`] = `
+{
+  "spdxVersion": "SPDX-2.3",
+  "dataLicense": "CC0-1.0",
+  "SPDXID": "SPDXRef-DOCUMENT",
+  "name": "root@1.0.0",
+  "documentNamespace": "docns",
+  "creationInfo": {
+    "created": "2020-01-01T00:00:00.000Z",
+    "creators": [
+      "Tool: npm/cli-10.0.0 "
+    ]
+  },
+  "documentDescribes": [
+    "SPDXRef-Package-root-1.0.0"
+  ],
+  "packages": [
+    {
+      "name": "root",
+      "SPDXID": "SPDXRef-Package-root-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/root@1.0.0"
+        }
+      ]
+    }
+  ],
+  "relationships": [
+    {
+      "spdxElementId": "SPDXRef-DOCUMENT",
+      "relatedSpdxElement": "SPDXRef-Package-root-1.0.0",
+      "relationshipType": "DESCRIBES"
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-spdx.js TAP single node - with description > must match snapshot 1`] = `
+{
+  "spdxVersion": "SPDX-2.3",
+  "dataLicense": "CC0-1.0",
+  "SPDXID": "SPDXRef-DOCUMENT",
+  "name": "root@1.0.0",
+  "documentNamespace": "docns",
+  "creationInfo": {
+    "created": "2020-01-01T00:00:00.000Z",
+    "creators": [
+      "Tool: npm/cli-10.0.0 "
+    ]
+  },
+  "documentDescribes": [
+    "SPDXRef-Package-root-1.0.0"
+  ],
+  "packages": [
+    {
+      "name": "root",
+      "SPDXID": "SPDXRef-Package-root-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "",
+      "description": "Package description",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/root@1.0.0"
+        }
+      ]
+    }
+  ],
+  "relationships": [
+    {
+      "spdxElementId": "SPDXRef-DOCUMENT",
+      "relatedSpdxElement": "SPDXRef-Package-root-1.0.0",
+      "relationshipType": "DESCRIBES"
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-spdx.js TAP single node - with distribution url > must match snapshot 1`] = `
+{
+  "spdxVersion": "SPDX-2.3",
+  "dataLicense": "CC0-1.0",
+  "SPDXID": "SPDXRef-DOCUMENT",
+  "name": "root@1.0.0",
+  "documentNamespace": "docns",
+  "creationInfo": {
+    "created": "2020-01-01T00:00:00.000Z",
+    "creators": [
+      "Tool: npm/cli-10.0.0 "
+    ]
+  },
+  "documentDescribes": [
+    "SPDXRef-Package-root-1.0.0"
+  ],
+  "packages": [
+    {
+      "name": "root",
+      "SPDXID": "SPDXRef-Package-root-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "",
+      "downloadLocation": "https://registry.npmjs.org/root/-/root-1.0.0.tgz",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/root@1.0.0"
+        }
+      ]
+    }
+  ],
+  "relationships": [
+    {
+      "spdxElementId": "SPDXRef-DOCUMENT",
+      "relatedSpdxElement": "SPDXRef-Package-root-1.0.0",
+      "relationshipType": "DESCRIBES"
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-spdx.js TAP single node - with homepage > must match snapshot 1`] = `
+{
+  "spdxVersion": "SPDX-2.3",
+  "dataLicense": "CC0-1.0",
+  "SPDXID": "SPDXRef-DOCUMENT",
+  "name": "root@1.0.0",
+  "documentNamespace": "docns",
+  "creationInfo": {
+    "created": "2020-01-01T00:00:00.000Z",
+    "creators": [
+      "Tool: npm/cli-10.0.0 "
+    ]
+  },
+  "documentDescribes": [
+    "SPDXRef-Package-root-1.0.0"
+  ],
+  "packages": [
+    {
+      "name": "root",
+      "SPDXID": "SPDXRef-Package-root-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "https://foo.bar/README.md",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/root@1.0.0"
+        }
+      ]
+    }
+  ],
+  "relationships": [
+    {
+      "spdxElementId": "SPDXRef-DOCUMENT",
+      "relatedSpdxElement": "SPDXRef-Package-root-1.0.0",
+      "relationshipType": "DESCRIBES"
+    }
+  ]
+}
+`
+
+exports[`test/lib/utils/sbom-spdx.js TAP single node - with integrity > must match snapshot 1`] = `
+{
+  "spdxVersion": "SPDX-2.3",
+  "dataLicense": "CC0-1.0",
+  "SPDXID": "SPDXRef-DOCUMENT",
+  "name": "root@1.0.0",
+  "documentNamespace": "docns",
+  "creationInfo": {
+    "created": "2020-01-01T00:00:00.000Z",
+    "creators": [
+      "Tool: npm/cli-10.0.0 "
+    ]
+  },
+  "documentDescribes": [
+    "SPDXRef-Package-root-1.0.0"
+  ],
+  "packages": [
+    {
+      "name": "root",
+      "SPDXID": "SPDXRef-Package-root-1.0.0",
+      "versionInfo": "1.0.0",
+      "packageFileName": "",
+      "downloadLocation": "NOASSERTION",
+      "filesAnalyzed": false,
+      "homepage": "NOASSERTION",
+      "licenseDeclared": "NOASSERTION",
+      "externalRefs": [
+        {
+          "referenceCategory": "PACKAGE-MANAGER",
+          "referenceType": "purl",
+          "referenceLocator": "pkg:npm/root@1.0.0"
+        }
+      ],
+      "checksums": [
+        {
+          "algorithm": "SHA512",
+          "checksumValue": "d5191b14650a7b1e25bec07dca121f5a5b493397192947ed07678d6a3683bf7742304a78f62046d0ad78b87f0d9d7f483eec76fa62bb24610e0748e7e3cfc9eb"
+        }
+      ]
+    }
+  ],
+  "relationships": [
+    {
+      "spdxElementId": "SPDXRef-DOCUMENT",
+      "relatedSpdxElement": "SPDXRef-Package-root-1.0.0",
+      "relationshipType": "DESCRIBES"
+    }
+  ]
+}
+`
diff --git a/deps/npm/test/bin/windows-shims.js b/deps/npm/test/bin/windows-shims.js
index 29c257fc7954d3..5fa6ff142b7377 100644
--- a/deps/npm/test/bin/windows-shims.js
+++ b/deps/npm/test/bin/windows-shims.js
@@ -1,21 +1,23 @@
 const t = require('tap')
 const { spawnSync } = require('child_process')
 const { resolve, join, extname, basename, sep } = require('path')
-const { readFileSync, chmodSync, readdirSync } = require('fs')
+const { copyFileSync, readFileSync, chmodSync, readdirSync, rmSync, statSync } = require('fs')
 const Diff = require('diff')
 const { sync: which } = require('which')
 const { version } = require('../../package.json')
 
-const ROOT = resolve(__dirname, '../..')
-const BIN = join(ROOT, 'bin')
-const NODE = readFileSync(process.execPath)
-const SHIMS = readdirSync(BIN).reduce((acc, shim) => {
-  if (extname(shim) !== '.js') {
-    acc[shim] = readFileSync(join(BIN, shim), 'utf-8')
+const readNonJsFiles = (dir) => readdirSync(dir).reduce((acc, shim) => {
+  const p = join(dir, shim)
+  if (extname(p) !== '.js' && !statSync(p).isDirectory()) {
+    acc[shim] = readFileSync(p, 'utf-8')
   }
   return acc
 }, {})
 
+const ROOT = resolve(__dirname, '../..')
+const BIN = join(ROOT, 'bin')
+const SHIMS = readNonJsFiles(BIN)
+const NODE_GYP = readNonJsFiles(join(BIN, 'node-gyp-bin'))
 const SHIM_EXTS = [...new Set(Object.keys(SHIMS).map(p => extname(p)))]
 
 // windows requires each segment of a command path to be quoted when using shell: true
@@ -64,10 +66,24 @@ t.test('shim contents', t => {
   })
 })
 
+t.test('node-gyp', t => {
+  // these files need to exist to avoid breaking yarn 1.x
+
+  for (const [key, file] of Object.entries(NODE_GYP)) {
+    t.match(file, /npm_config_node_gyp/, `${key} contains env var`)
+    t.match(
+      file,
+      /[\\/]\.\.[\\/]\.\.[\\/]node_modules[\\/]node-gyp[\\/]bin[\\/]node-gyp\.js/,
+      `${key} contains path`
+    )
+  }
+
+  t.end()
+})
+
 t.test('run shims', t => {
   const path = t.testdir({
     ...SHIMS,
-    'node.exe': NODE,
     // simulate the state where one version of npm is installed
     // with node, but we should load the globally installed one
     'global-prefix': {
@@ -92,6 +108,16 @@ t.test('run shims', t => {
     },
   })
 
+  // hacky fix to decrease flakes of this test from `NOTEMPTY: directory not empty, rmdir`
+  // this should get better in tap@18 and we can try removing it then
+  copyFileSync(process.execPath, join(path, 'node.exe'))
+  t.teardown(async () => {
+    rmSync(join(path, 'node.exe'))
+    await new Promise(res => setTimeout(res, 100))
+    // this is superstition
+    rmSync(join(path, 'node.exe'), { force: true })
+  })
+
   const spawnPath = (cmd, args, { log, stdioString = true, ...opts } = {}) => {
     if (cmd.endsWith('bash.exe')) {
       // only cygwin *requires* the -l, but the others are ok with it
diff --git a/deps/npm/test/fixtures/libnpmsearch-stream-result.js b/deps/npm/test/fixtures/libnpmsearch-stream-result.js
index 1ec8b7b113d6b8..68245beff6e46f 100644
--- a/deps/npm/test/fixtures/libnpmsearch-stream-result.js
+++ b/deps/npm/test/fixtures/libnpmsearch-stream-result.js
@@ -217,6 +217,9 @@ module.exports = [
     description: 'Retrieves a name:pathname Map for a given workspaces config',
     keywords: [
       '\x1B[33mnpm\x1B[39m',
+      // eslint-disable-next-line no-octal-escape
+      '\x1b]4;0;?\007',
+      '\u001b[Hbad map',
       'npmcli',
       'libnpm',
       'cli',
@@ -275,4 +278,11 @@ module.exports = [
     publisher: { username: 'types', email: 'ts-npm-types@microsoft.com' },
     maintainers: [{ username: 'types', email: 'ts-npm-types@microsoft.com' }],
   },
+  {
+    name: 'pkg-no-desc',
+    scope: 'unscoped',
+    version: '1.0.0',
+    date: '2019-09-26T22:24:28.713Z',
+    maintainers: [{ username: 'lukekarrys', email: 'lukekarrys' }],
+  },
 ]
diff --git a/deps/npm/test/fixtures/sandbox.js b/deps/npm/test/fixtures/sandbox.js
index 2c4e5c2968a38c..5be02fcf80c1eb 100644
--- a/deps/npm/test/fixtures/sandbox.js
+++ b/deps/npm/test/fixtures/sandbox.js
@@ -42,11 +42,6 @@ const _get = Symbol('sandbox.proxy.get')
 const _set = Symbol('sandbox.proxy.set')
 const _logs = Symbol('sandbox.logs')
 
-// these config keys can be redacted widely
-const redactedDefaults = [
-  'tmp',
-]
-
 // we can't just replace these values everywhere because they're known to be
 // very short strings that could be present all over the place, so we only
 // replace them if they're located within quotes for now
@@ -161,12 +156,6 @@ class Sandbox extends EventEmitter {
     // and we replaced the node version first, the real execPath we're trying
     // to replace would no longer be represented, and be missed.
     if (this[_npm]) {
-      // replace default config values with placeholders
-      for (const name of redactedDefaults) {
-        const value = this[_npm].config.defaults[name]
-        clean = clean.split(normalize(value)).join(`{${name.toUpperCase()}}`)
-      }
-
       // replace vague default config values that are present within quotes
       // with placeholders
       for (const name of vagueRedactedDefaults) {
diff --git a/deps/npm/test/lib/commands/audit.js b/deps/npm/test/lib/commands/audit.js
index 4014e733873519..623c7b6485159f 100644
--- a/deps/npm/test/lib/commands/audit.js
+++ b/deps/npm/test/lib/commands/audit.js
@@ -210,6 +210,18 @@ t.test('audit fix - bulk endpoint', async t => {
   )
 })
 
+t.test('audit fix no package lock', async t => {
+  const { npm } = await loadMockNpm(t, {
+    config: {
+      'package-lock': false,
+    },
+  })
+  await t.rejects(
+    npm.exec('audit', ['fix']),
+    { code: 'EUSAGE' }
+  )
+})
+
 t.test('completion', async t => {
   const { audit } = await loadMockNpm(t, { command: 'audit' })
   t.test('fix', async t => {
@@ -1381,7 +1393,7 @@ t.test('audit signatures', async t => {
 
     await t.rejects(
       npm.exec('audit', ['signatures']),
-      /found no dependencies to audit that where installed from a supported registry/
+      /found no dependencies to audit that were installed from a supported registry/
     )
   })
 
@@ -1412,7 +1424,7 @@ t.test('audit signatures', async t => {
 
     await t.rejects(
       npm.exec('audit', ['signatures']),
-      /found no dependencies to audit that where installed from a supported registry/
+      /found no dependencies to audit that were installed from a supported registry/
     )
   })
 
@@ -1699,16 +1711,12 @@ t.test('audit signatures', async t => {
     const { npm } = await loadMockNpm(t, {
       prefixDir: installWithMultipleDeps,
       mocks: {
-        sigstore: {
-          sigstore: {
-            tuf: {
-              client: async () => ({
-                getTarget: async () => {
-                  throw new Error('error refreshing TUF metadata')
-                },
-              }),
+        '@sigstore/tuf': {
+          initTUF: async () => ({
+            getTarget: async () => {
+              throw new Error('error refreshing TUF metadata')
             },
-          },
+          }),
         },
       },
     })
@@ -1758,7 +1766,7 @@ t.test('audit signatures', async t => {
 
     await t.rejects(
       npm.exec('audit', ['signatures']),
-      /found no dependencies to audit that where installed from a supported registry/
+      /found no dependencies to audit that were installed from a supported registry/
     )
   })
 
@@ -1779,7 +1787,7 @@ t.test('audit signatures', async t => {
 
     await t.rejects(
       npm.exec('audit', ['signatures']),
-      /found no dependencies to audit that where installed from a supported registry/
+      /found no dependencies to audit that were installed from a supported registry/
     )
   })
 
@@ -1807,7 +1815,7 @@ t.test('audit signatures', async t => {
 
     await t.rejects(
       npm.exec('audit', ['signatures']),
-      /found no dependencies to audit that where installed from a supported registry/
+      /found no dependencies to audit that were installed from a supported registry/
     )
   })
 
@@ -1836,7 +1844,7 @@ t.test('audit signatures', async t => {
 
     await t.rejects(
       npm.exec('audit', ['signatures']),
-      /found no dependencies to audit that where installed from a supported registry/
+      /found no dependencies to audit that were installed from a supported registry/
     )
   })
 
@@ -1877,9 +1885,7 @@ t.test('audit signatures', async t => {
       prefixDir: installWithValidAttestations,
       mocks: {
         pacote: t.mock('pacote', {
-          sigstore: {
-            sigstore: { verify: async () => true },
-          },
+          sigstore: { verify: async () => true },
         }),
       },
     })
@@ -1904,9 +1910,7 @@ t.test('audit signatures', async t => {
       prefixDir: installWithMultipleValidAttestations,
       mocks: {
         pacote: t.mock('pacote', {
-          sigstore: {
-            sigstore: { verify: async () => true },
-          },
+          sigstore: { verify: async () => true },
         }),
       },
     })
@@ -1937,10 +1941,8 @@ t.test('audit signatures', async t => {
       mocks: {
         pacote: t.mock('pacote', {
           sigstore: {
-            sigstore: {
-              verify: async () => {
-                throw new Error(`artifact signature verification failed`)
-              },
+            verify: async () => {
+              throw new Error(`artifact signature verification failed`)
             },
           },
         }),
@@ -1974,10 +1976,8 @@ t.test('audit signatures', async t => {
       mocks: {
         pacote: t.mock('pacote', {
           sigstore: {
-            sigstore: {
-              verify: async () => {
-                throw new Error(`artifact signature verification failed`)
-              },
+            verify: async () => {
+              throw new Error(`artifact signature verification failed`)
             },
           },
         }),
@@ -2005,10 +2005,8 @@ t.test('audit signatures', async t => {
       mocks: {
         pacote: t.mock('pacote', {
           sigstore: {
-            sigstore: {
-              verify: async () => {
-                throw new Error(`artifact signature verification failed`)
-              },
+            verify: async () => {
+              throw new Error(`artifact signature verification failed`)
             },
           },
         }),
diff --git a/deps/npm/test/lib/commands/bugs.js b/deps/npm/test/lib/commands/bugs.js
index 953c8e6345a2a7..e2ebfb53065748 100644
--- a/deps/npm/test/lib/commands/bugs.js
+++ b/deps/npm/test/lib/commands/bugs.js
@@ -6,6 +6,10 @@ const pacote = {
     return spec === 'nobugs' ? {
       name: 'nobugs',
       version: '1.2.3',
+    } : spec === 'nullbugs' ? {
+      name: 'nullbugs',
+      version: '1.2.3',
+      bugs: null,
     } : spec === 'bugsurl' ? {
       name: 'bugsurl',
       version: '1.2.3',
@@ -66,6 +70,7 @@ t.test('open bugs urls & emails', async t => {
   const expected = {
     '.': 'https://example.com',
     nobugs: 'https://www.npmjs.com/package/nobugs',
+    nullbugs: 'https://www.npmjs.com/package/nullbugs',
     'bugsobj-nourl': 'https://www.npmjs.com/package/bugsobj-nourl',
     bugsurl: 'https://bugzilla.localhost/bugsurl',
     bugsobj: 'https://bugzilla.localhost/bugsobj',
diff --git a/deps/npm/test/lib/commands/hook.js b/deps/npm/test/lib/commands/hook.js
index e4e1214b812f3b..d3de4f5c55efad 100644
--- a/deps/npm/test/lib/commands/hook.js
+++ b/deps/npm/test/lib/commands/hook.js
@@ -243,7 +243,7 @@ t.test('npm hook ls', async t => {
     'received the correct arguments'
   )
   t.equal(outputs[0][0], 'You have 3 hooks configured.', 'prints the correct header')
-  const out = require('../../../lib/utils/ansi-trim')(outputs[1][0])
+  const out = require('strip-ansi')(outputs[1][0])
   t.match(out, /semver.*https:\/\/google.com.*\n.*\n.*never triggered/, 'prints package hook')
   t.match(out, /@npmcli.*https:\/\/google.com.*\n.*\n.*triggered just now/, 'prints scope hook')
   t.match(out, /~npm.*https:\/\/google.com.*\n.*\n.*never triggered/, 'prints owner hook')
@@ -292,7 +292,7 @@ t.test('npm hook ls, single result', async t => {
     'received the correct arguments'
   )
   t.equal(outputs[0][0], 'You have one hook configured.', 'prints the correct header')
-  const out = require('../../../lib/utils/ansi-trim')(outputs[1][0])
+  const out = require('strip-ansi')(outputs[1][0])
   t.match(out, /semver.*https:\/\/google.com.*\n.*\n.*never triggered/, 'prints package hook')
 })
 
diff --git a/deps/npm/test/lib/commands/link.js b/deps/npm/test/lib/commands/link.js
index 65792fd141acba..85bada28d67b1e 100644
--- a/deps/npm/test/lib/commands/link.js
+++ b/deps/npm/test/lib/commands/link.js
@@ -369,6 +369,40 @@ t.test('link pkg already in global space when prefix is a symlink', async t => {
   t.matchSnapshot(await printLinks(), 'should create a local symlink to global pkg')
 })
 
+t.test('should not save link to package file', async t => {
+  const { link, prefix } = await mockLink(t, {
+    globalPrefixDir: {
+      node_modules: {
+        '@myscope': {
+          linked: t.fixture('symlink', '../../../other/scoped-linked'),
+        },
+      },
+    },
+    otherDirs: {
+      'scoped-linked': {
+        'package.json': JSON.stringify({
+          name: '@myscope/linked',
+          version: '1.0.0',
+        }),
+      },
+    },
+    prefixDir: {
+      'package.json': JSON.stringify({
+        name: 'my-project',
+        version: '1.0.0',
+      }),
+    },
+    config: { save: false },
+  })
+
+  await link.exec(['@myscope/linked'])
+  t.match(
+    require(resolve(prefix, 'package.json')).dependencies,
+    undefined,
+    'should not save to package.json upon linking'
+  )
+})
+
 t.test('should not prune dependencies when linking packages', async t => {
   const { link, prefix } = await mockLink(t, {
     globalPrefixDir: {
diff --git a/deps/npm/test/lib/commands/logout.js b/deps/npm/test/lib/commands/logout.js
index 4ff21665f30354..881003729ab4a1 100644
--- a/deps/npm/test/lib/commands/logout.js
+++ b/deps/npm/test/lib/commands/logout.js
@@ -1,170 +1,154 @@
 const t = require('tap')
 const fs = require('fs/promises')
-const npmFetch = require('npm-registry-fetch')
-const mockNpm = require('../../fixtures/mock-npm')
+const { load: loadMockNpm } = require('../../fixtures/mock-npm.js')
+const MockRegistry = require('@npmcli/mock-registry')
 const { join } = require('path')
 
-const mockLogout = async (t, { userRc = [], ...npmOpts } = {}) => {
-  let result = null
-
-  const mock = await mockNpm(t, {
-    command: 'logout',
-    mocks: {
-      // XXX: refactor to use mock registry
-      'npm-registry-fetch': Object.assign(async (url, opts) => {
-        result = { url, opts }
-      }, npmFetch),
-    },
-    ...npmOpts,
+t.test('token logout - user config', async t => {
+  const { npm, home, logs } = await loadMockNpm(t, {
     homeDir: {
-      '.npmrc': userRc.join('\n'),
+      '.npmrc': [
+        '//registry.npmjs.org/:_authToken=@foo/',
+        'other-config=true',
+      ].join('\n'),
     },
   })
 
-  return {
-    ...mock,
-    result: () => result,
-    // get only the message portion of the verbose log from the command
-    logMsg: () => mock.logs.verbose.find(l => l[0] === 'logout')[1],
-    userRc: () => fs.readFile(join(mock.home, '.npmrc'), 'utf-8').then(r => r.trim()),
-  }
-}
-
-t.test('token logout', async t => {
-  const { logout, logMsg, result, userRc } = await mockLogout(t, {
-    userRc: [
-      '//registry.npmjs.org/:_authToken=@foo/',
-      'other-config=true',
-    ],
-  })
-
-  await logout.exec([])
-
+  const mockRegistry = new MockRegistry({ tap: t, registry: 'https://registry.npmjs.org/' })
+  mockRegistry.logout('@foo/')
+  await npm.exec('logout', [])
   t.equal(
-    logMsg(),
+    logs.verbose.find(l => l[0] === 'logout')[1],
     'clearing token for https://registry.npmjs.org/',
     'should log message with correct registry'
   )
+  const userRc = await fs.readFile(join(home, '.npmrc'), 'utf-8')
+  t.equal(userRc.trim(), 'other-config=true')
+})
 
-  t.match(
-    result(),
-    {
-      url: '/-/user/token/%40foo%2F',
-      opts: {
-        registry: 'https://registry.npmjs.org/',
-        scope: '',
-        '//registry.npmjs.org/:_authToken': '@foo/',
-        method: 'DELETE',
-        ignoreBody: true,
-      },
+t.test('token scoped logout - user config', async t => {
+  const { npm, home, logs } = await loadMockNpm(t, {
+    config: {
+      scope: '@myscope',
     },
-    'should call npm-registry-fetch with expected values'
-  )
-
-  t.equal(await userRc(), 'other-config=true')
-})
+    homeDir: {
+      '.npmrc': [
+        '//diff-registry.npmjs.com/:_authToken=@bar/',
+        '//registry.npmjs.org/:_authToken=@foo/',
+        '@myscope:registry=https://diff-registry.npmjs.com/',
 
-t.test('token scoped logout', async t => {
-  const { logout, logMsg, result, userRc } = await mockLogout(t, {
-    config: { scope: '@myscope' },
-    userRc: [
-      '//diff-registry.npmjs.com/:_authToken=@bar/',
-      '//registry.npmjs.org/:_authToken=@foo/',
-      '@myscope:registry=https://diff-registry.npmjs.com/',
-    ],
+      ].join('\n'),
+    },
   })
 
-  await logout.exec([])
-
+  const mockRegistry = new MockRegistry({ tap: t, registry: 'https://diff-registry.npmjs.com/' })
+  mockRegistry.logout('@bar/')
+  await npm.exec('logout', [])
   t.equal(
-    logMsg(),
+    logs.verbose.find(l => l[0] === 'logout')[1],
     'clearing token for https://diff-registry.npmjs.com/',
     'should log message with correct registry'
   )
 
-  t.match(
-    result(),
-    {
-      url: '/-/user/token/%40bar%2F',
-      opts: {
-        registry: 'https://registry.npmjs.org/',
-        '@myscope:registry': 'https://diff-registry.npmjs.com/',
-        scope: '@myscope',
-        '//registry.npmjs.org/:_authToken': '@foo/', // <- removed by npm-registry-fetch
-        '//diff-registry.npmjs.com/:_authToken': '@bar/',
-        method: 'DELETE',
-        ignoreBody: true,
-      },
-    },
-    'should call npm-registry-fetch with expected values'
-  )
-
-  t.equal(await userRc(), '//registry.npmjs.org/:_authToken=@foo/')
+  const userRc = await fs.readFile(join(home, '.npmrc'), 'utf-8')
+  t.equal(userRc.trim(), '//registry.npmjs.org/:_authToken=@foo/')
 })
 
-t.test('user/pass logout', async t => {
-  const { logout, logMsg, userRc } = await mockLogout(t, {
-    userRc: [
-      '//registry.npmjs.org/:username=foo',
-      '//registry.npmjs.org/:_password=bar',
-      'other-config=true',
-    ],
+t.test('user/pass logout - user config', async t => {
+  const { npm, home, logs } = await loadMockNpm(t, {
+    homeDir: {
+      '.npmrc': [
+        '//registry.npmjs.org/:username=foo',
+        '//registry.npmjs.org/:_password=bar',
+        'other-config=true',
+      ].join('\n'),
+    },
   })
 
-  await logout.exec([])
-
+  await npm.exec('logout', [])
   t.equal(
-    logMsg(),
+    logs.verbose.find(l => l[0] === 'logout')[1],
     'clearing user credentials for https://registry.npmjs.org/',
     'should log message with correct registry'
   )
 
-  t.equal(await userRc(), 'other-config=true')
+  const userRc = await fs.readFile(join(home, '.npmrc'), 'utf-8')
+  t.equal(userRc.trim(), 'other-config=true')
 })
 
 t.test('missing credentials', async t => {
-  const { logout } = await mockLogout(t)
+  const { npm } = await loadMockNpm(t)
 
   await t.rejects(
-    logout.exec([]),
+    npm.exec('logout', []),
     {
       code: 'ENEEDAUTH',
       message: /not logged in to https:\/\/registry.npmjs.org\/, so can't log out!/,
     },
-    'should throw with expected error code'
+    'should reject with expected error code'
   )
 })
 
 t.test('ignore invalid scoped registry config', async t => {
-  const { logout, logMsg, result, userRc } = await mockLogout(t, {
+  const { npm, home, logs } = await loadMockNpm(t, {
     config: { scope: '@myscope' },
-    userRc: [
-      '//registry.npmjs.org/:_authToken=@foo/',
-      'other-config=true',
-    ],
+    homeDir: {
+      '.npmrc': [
+        '//registry.npmjs.org/:_authToken=@foo/',
+        'other-config=true',
+
+      ].join('\n'),
+    },
   })
 
-  await logout.exec([])
+  const mockRegistry = new MockRegistry({ tap: t, registry: 'https://registry.npmjs.org/' })
+  mockRegistry.logout('@foo/')
+  await npm.exec('logout', [])
 
   t.equal(
-    logMsg(),
+    logs.verbose.find(l => l[0] === 'logout')[1],
     'clearing token for https://registry.npmjs.org/',
     'should log message with correct registry'
   )
+  const userRc = await fs.readFile(join(home, '.npmrc'), 'utf-8')
+  t.equal(userRc.trim(), 'other-config=true')
+})
 
-  t.match(
-    result(),
-    {
-      url: '/-/user/token/%40foo%2F',
-      opts: {
-        '//registry.npmjs.org/:_authToken': '@foo/',
-        registry: 'https://registry.npmjs.org/',
-        method: 'DELETE',
-        ignoreBody: true,
-      },
+t.test('token logout - project config', async t => {
+  const { npm, home, logs, prefix } = await loadMockNpm(t, {
+    homeDir: {
+      '.npmrc': [
+        '//registry.npmjs.org/:_authToken=@foo/',
+        'other-config=true',
+      ].join('\n'),
     },
-    'should call npm-registry-fetch with expected values'
-  )
+    prefixDir: {
+      '.npmrc': [
+        '//registry.npmjs.org/:_authToken=@bar/',
+        'other-config=true',
+      ].join('\n'),
+    },
+  })
 
-  t.equal(await userRc(), 'other-config=true')
+  const mockRegistry = new MockRegistry({ tap: t, registry: 'https://registry.npmjs.org/' })
+  mockRegistry.logout('@bar/')
+  await npm.exec('logout', [])
+
+  t.equal(
+    logs.verbose.find(l => l[0] === 'logout')[1],
+    'clearing token for https://registry.npmjs.org/',
+    'should log message with correct registry'
+  )
+  const userRc = await fs.readFile(join(home, '.npmrc'), 'utf-8')
+  t.equal(userRc.trim(), [
+    '//registry.npmjs.org/:_authToken=@foo/',
+    'other-config=true',
+  ].join('\n'), 'leaves user config alone')
+  t.equal(
+    logs.verbose.find(l => l[0] === 'logout')[1],
+    'clearing token for https://registry.npmjs.org/',
+    'should log message with correct registry'
+  )
+  const projectRc = await fs.readFile(join(prefix, '.npmrc'), 'utf-8')
+  t.equal(projectRc.trim(), 'other-config=true', 'removes project config')
 })
diff --git a/deps/npm/test/lib/commands/org.js b/deps/npm/test/lib/commands/org.js
index 511251e1bb096e..5c239295c33432 100644
--- a/deps/npm/test/lib/commands/org.js
+++ b/deps/npm/test/lib/commands/org.js
@@ -1,5 +1,5 @@
 const t = require('tap')
-const ansiTrim = require('../../../lib/utils/ansi-trim.js')
+const ansiTrim = require('strip-ansi')
 const mockNpm = require('../../fixtures/mock-npm')
 
 const mockOrg = async (t, { orgSize = 1, orgList = {}, ...npmOpts } = {}) => {
diff --git a/deps/npm/test/lib/commands/pkg.js b/deps/npm/test/lib/commands/pkg.js
index e915ef942410f5..f3401bde5226a8 100644
--- a/deps/npm/test/lib/commands/pkg.js
+++ b/deps/npm/test/lib/commands/pkg.js
@@ -83,6 +83,50 @@ t.test('get single arg', async t => {
   )
 })
 
+t.test('get multiple arg', async t => {
+  const { pkg, OUTPUT } = await mockNpm(t, {
+    prefixDir: {
+      'package.json': JSON.stringify({
+        name: 'foo',
+        version: '1.1.1',
+      }),
+    },
+  })
+
+  await pkg('get', 'name', 'version')
+
+  t.strictSame(
+    JSON.parse(OUTPUT()),
+    {
+      name: 'foo',
+      version: '1.1.1',
+    },
+    'should print retrieved package.json field'
+  )
+})
+
+t.test('get multiple arg with empty value', async t => {
+  const { pkg, OUTPUT } = await mockNpm(t, {
+    prefixDir: {
+      'package.json': JSON.stringify({
+        name: 'foo',
+        author: '',
+      }),
+    },
+  })
+
+  await pkg('get', 'name', 'author')
+
+  t.strictSame(
+    JSON.parse(OUTPUT()),
+    {
+      name: 'foo',
+      author: '',
+    },
+    'should print retrieved package.json field regardless of empty value'
+  )
+})
+
 t.test('get nested arg', async t => {
   const { pkg, OUTPUT } = await mockNpm(t, {
     prefixDir: {
diff --git a/deps/npm/test/lib/commands/query.js b/deps/npm/test/lib/commands/query.js
index 2b9a5b49763235..adf617316772e5 100644
--- a/deps/npm/test/lib/commands/query.js
+++ b/deps/npm/test/lib/commands/query.js
@@ -179,3 +179,61 @@ t.test('global', async t => {
   await npm.exec('query', ['[name=lorem]'])
   t.matchSnapshot(joinedOutput(), 'should return global package')
 })
+
+t.test('package-lock-only', t => {
+  t.test('no package lock', async t => {
+    const { npm } = await loadMockNpm(t, {
+      config: {
+        'package-lock-only': true,
+      },
+      prefixDir: {
+        'package.json': JSON.stringify({
+          name: 'project',
+          dependencies: {
+            a: '^1.0.0',
+          },
+        }),
+      },
+    })
+    await t.rejects(npm.exec('query', [':root, :root > *']), { code: 'EUSAGE' })
+  })
+
+  t.test('with package lock', async t => {
+    const { npm, joinedOutput } = await loadMockNpm(t, {
+      config: {
+        'package-lock-only': true,
+      },
+      prefixDir: {
+        'package.json': JSON.stringify({
+          name: 'project',
+          dependencies: {
+            a: '^1.0.0',
+          },
+        }),
+        'package-lock.json': JSON.stringify({
+          name: 'project',
+          lockfileVersion: 3,
+          requires: true,
+          packages: {
+            '': {
+              dependencies: {
+                a: '^1.0.0',
+              },
+            },
+            'node_modules/a': {
+              version: '1.2.3',
+              resolved: 'https://dummy.npmjs.org/a/-/a-1.2.3.tgz',
+              integrity: 'sha512-dummy',
+              engines: {
+                node: '>=14.17',
+              },
+            },
+          },
+        }),
+      },
+    })
+    await npm.exec('query', ['*'])
+    t.matchSnapshot(joinedOutput(), 'should return valid response with only lock info')
+  })
+  t.end()
+})
diff --git a/deps/npm/test/lib/commands/run-script.js b/deps/npm/test/lib/commands/run-script.js
index cb54a7f51e9002..24f51400e8dfc3 100644
--- a/deps/npm/test/lib/commands/run-script.js
+++ b/deps/npm/test/lib/commands/run-script.js
@@ -781,12 +781,7 @@ t.test('workspaces', async t => {
   t.test('missing scripts in all workspaces', async t => {
     const { runScript, RUN_SCRIPTS, cleanLogs } = await mockWorkspaces(t, { exec: null })
 
-    await t.rejects(
-      runScript.exec(['missing-script']),
-      /Missing script: missing-script/,
-      'should throw missing script error'
-    )
-
+    await runScript.exec(['missing-script'])
     t.match(RUN_SCRIPTS(), [])
     t.strictSame(
       cleanLogs(),
diff --git a/deps/npm/test/lib/commands/sbom.js b/deps/npm/test/lib/commands/sbom.js
new file mode 100644
index 00000000000000..3c79ed82cf8370
--- /dev/null
+++ b/deps/npm/test/lib/commands/sbom.js
@@ -0,0 +1,503 @@
+const t = require('tap')
+const mockNpm = require('../../fixtures/mock-npm.js')
+
+const FAKE_TIMESTAMP = '2020-01-01T00:00:00.000Z'
+const FAKE_UUID = '00000000-0000-0000-0000-000000000000'
+
+t.cleanSnapshot = s => {
+  let sbom
+
+  try {
+    sbom = JSON.parse(s)
+  } catch (e) {
+    return s
+  }
+
+  // Clean dynamic values from snapshots. SPDX and CycloneDX have different
+  // formats for these values, so we need to do it separately.
+  if (sbom.SPDXID) {
+    sbom.documentNamespace = `http://spdx.org/spdxdocs/test-npm-sbom-1.0.0-${FAKE_UUID}`
+
+    if (sbom.creationInfo) {
+      sbom.creationInfo.created = FAKE_TIMESTAMP
+      sbom.creationInfo.creators = ['Tool: npm/cli-10.0.0']
+    }
+  } else {
+    sbom.serialNumber = `urn:uuid:${FAKE_UUID}`
+
+    if (sbom.metadata) {
+      sbom.metadata.timestamp = FAKE_TIMESTAMP
+      sbom.metadata.tools[0].version = '10.0.0'
+    }
+  }
+
+  return JSON.stringify(sbom, null, 2)
+}
+
+const simpleNmFixture = {
+  node_modules: {
+    foo: {
+      'package.json': JSON.stringify({
+        name: 'foo',
+        version: '1.0.0',
+        dependencies: {
+          dog: '^1.0.0',
+        },
+      }),
+      node_modules: {
+        dog: {
+          'package.json': JSON.stringify({
+            name: 'dog',
+            version: '1.0.0',
+          }),
+        },
+      },
+    },
+    chai: {
+      'package.json': JSON.stringify({
+        name: 'chai',
+        version: '1.0.0',
+      }),
+    },
+  },
+}
+
+const mockSbom = async (t, { mocks, config, ...opts } = {}) => {
+  const mock = await mockNpm(t, {
+    ...opts,
+    config: {
+      ...config,
+    },
+    command: 'sbom',
+    mocks: {
+      path: {
+        ...require('path'),
+        sep: '/',
+      },
+      ...mocks,
+    },
+  })
+
+  return {
+    ...mock,
+    result: () => mock.joinedOutput(),
+  }
+}
+
+t.test('sbom', async t => {
+  t.test('basic sbom - spdx', async t => {
+    const config = {
+      'sbom-format': 'spdx',
+    }
+    const { result, sbom } = await mockSbom(t, {
+      config,
+      prefixDir: {
+        'package.json': JSON.stringify({
+          name: 'test-npm-sbom',
+          version: '1.0.0',
+          dependencies: {
+            foo: '^1.0.0',
+            chai: '^1.0.0',
+          },
+        }),
+        ...simpleNmFixture,
+      },
+    })
+    await sbom.exec([])
+    t.matchSnapshot(result())
+  })
+
+  t.test('basic sbom - cyclonedx', async t => {
+    const config = {
+      'sbom-format': 'cyclonedx',
+      'sbom-type': 'application',
+    }
+    const { result, sbom } = await mockSbom(t, {
+      config,
+      prefixDir: {
+        'package.json': JSON.stringify({
+          name: 'test-npm-sbom',
+          version: '1.0.0',
+          dependencies: {
+            foo: '^1.0.0',
+            chai: '^1.0.0',
+          },
+        }),
+        ...simpleNmFixture,
+      },
+    })
+    await sbom.exec([])
+    t.matchSnapshot(result())
+  })
+
+  t.test('--omit dev', async t => {
+    const config = {
+      'sbom-format': 'spdx',
+      omit: ['dev'],
+    }
+    const { result, sbom } = await mockSbom(t, {
+      config,
+      prefixDir: {
+        'package.json': JSON.stringify({
+          name: 'test-npm-sbom',
+          version: '1.0.0',
+          dependencies: {
+            foo: '^1.0.0',
+          },
+          devDependencies: {
+            chai: '^1.0.0',
+          },
+        }),
+        ...simpleNmFixture,
+      },
+    })
+    await sbom.exec([])
+    t.matchSnapshot(result())
+  })
+
+  t.test('--omit optional', async t => {
+    const config = {
+      'sbom-format': 'spdx',
+      omit: ['optional'],
+    }
+    const { result, sbom } = await mockSbom(t, {
+      config,
+      prefixDir: {
+        'package.json': JSON.stringify({
+          name: 'test-npm-sbom',
+          version: '1.0.0',
+          dependencies: {
+            chai: '^1.0.0',
+          },
+          optionalDependencies: {
+            foo: '^1.0.0',
+          },
+        }),
+        ...simpleNmFixture,
+      },
+    })
+    await sbom.exec([])
+    t.matchSnapshot(result())
+  })
+
+  t.test('--omit peer', async t => {
+    const config = {
+      'sbom-format': 'spdx',
+      omit: ['peer'],
+    }
+    const { result, sbom } = await mockSbom(t, {
+      config,
+      prefixDir: {
+        'package.json': JSON.stringify({
+          name: 'test-npm-sbom',
+          version: '1.0.0',
+          dependencies: {
+            chai: '^1.0.0',
+          },
+          peerDependencies: {
+            foo: '^1.0.0',
+          },
+        }),
+        ...simpleNmFixture,
+      },
+    })
+    await sbom.exec([])
+    t.matchSnapshot(result())
+  })
+
+  t.test('missing format', async t => {
+    const config = {}
+    const { result, sbom } = await mockSbom(t, {
+      config,
+      prefixDir: {
+        'package.json': JSON.stringify({
+          name: 'test-npm-sbom',
+          version: '1.0.0',
+          dependencies: {
+            foo: '^1.0.0',
+            chai: '^1.0.0',
+          },
+        }),
+        ...simpleNmFixture,
+      },
+    })
+    await t.rejects(sbom.exec([]), {
+      code: 'EUSAGE',
+      message: 'Must specify --sbom-format flag with one of: cyclonedx, spdx.',
+    },
+    'should throw error')
+
+    t.matchSnapshot(result())
+  })
+
+  t.test('invalid dep', async t => {
+    const config = {
+      'sbom-format': 'spdx',
+    }
+    const { sbom } = await mockSbom(t, {
+      config,
+      prefixDir: {
+        'package.json': JSON.stringify({
+          name: 'test-npm-ls',
+          version: '1.0.0',
+          dependencies: {
+            foo: '^2.0.0',
+          },
+        }),
+        ...simpleNmFixture,
+      },
+    })
+    await t.rejects(
+      sbom.exec([]),
+      { code: 'ESBOMPROBLEMS', message: /invalid: foo@1.0.0/ },
+      'should list dep problems'
+    )
+  })
+
+  t.test('missing dep', async t => {
+    const config = {
+      'sbom-format': 'spdx',
+    }
+    const { sbom } = await mockSbom(t, {
+      config,
+      prefixDir: {
+        'package.json': JSON.stringify({
+          name: 'test-npm-ls',
+          version: '1.0.0',
+          dependencies: {
+            ipsum: '^1.0.0',
+          },
+        }),
+        ...simpleNmFixture,
+      },
+    })
+    await t.rejects(
+      sbom.exec([]),
+      { code: 'ESBOMPROBLEMS', message: /missing: ipsum@\^1.0.0/ },
+      'should list dep problems'
+    )
+  })
+
+  t.test('missing (optional) dep', async t => {
+    const config = {
+      'sbom-format': 'spdx',
+    }
+    const { result, sbom } = await mockSbom(t, {
+      config,
+      prefixDir: {
+        'package.json': JSON.stringify({
+          name: 'test-npm-ls',
+          version: '1.0.0',
+          dependencies: {
+            foo: '^1.0.0',
+            chai: '^1.0.0',
+          },
+          optionalDependencies: {
+            ipsum: '^1.0.0',
+          },
+        }),
+        ...simpleNmFixture,
+      },
+    })
+    await sbom.exec([])
+    t.matchSnapshot(result())
+  })
+
+  t.test('extraneous dep', async t => {
+    const config = {
+      'sbom-format': 'spdx',
+    }
+    const { result, sbom } = await mockSbom(t, {
+      config,
+      prefixDir: {
+        'package.json': JSON.stringify({
+          name: 'test-npm-ls',
+          version: '1.0.0',
+          dependencies: {
+            foo: '^1.0.0',
+          },
+        }),
+        ...simpleNmFixture,
+      },
+    })
+    await sbom.exec([])
+    t.matchSnapshot(result())
+  })
+
+  t.test('lock file only', async t => {
+    const config = {
+      'sbom-format': 'spdx',
+      'package-lock-only': true,
+    }
+    const { result, sbom } = await mockSbom(t, {
+      config,
+      prefixDir: {
+        'package.json': JSON.stringify({
+          name: 'test-npm-ls',
+          version: '1.0.0',
+          dependencies: {
+            foo: '^1.0.0',
+            chai: '^1.0.0',
+          },
+        }),
+        'package-lock.json': JSON.stringify({
+          dependencies: {
+            foo: {
+              version: '1.0.0',
+              requires: {
+                dog: '^1.0.0',
+              },
+            },
+            dog: {
+              version: '1.0.0',
+            },
+            chai: {
+              version: '1.0.0',
+            },
+          },
+        }),
+      },
+    })
+    await sbom.exec([])
+    t.matchSnapshot(result())
+  })
+
+  t.test('lock file only - missing lock file', async t => {
+    const config = {
+      'sbom-format': 'spdx',
+      'package-lock-only': true,
+    }
+    const { result, sbom } = await mockSbom(t, {
+      config,
+      prefixDir: {
+        'package.json': JSON.stringify({
+          name: 'test-npm-ls',
+          version: '1.0.0',
+          dependencies: {
+            foo: '^1.0.0',
+            chai: '^1.0.0',
+          },
+        }),
+      },
+    })
+    await t.rejects(sbom.exec([]), {
+      code: 'EUSAGE',
+      message: 'A package lock or shrinkwrap file is required in package-lock-only mode',
+    },
+    'should throw error')
+
+    t.matchSnapshot(result())
+  })
+
+  t.test('loading a tree containing workspaces', async t => {
+    const mockWorkspaces = async (t, exec = [], config = {}) => {
+      const { result, sbom } = await mockSbom(t, {
+        config,
+        prefixDir: {
+          'package.json': JSON.stringify({
+            name: 'workspaces-tree',
+            version: '1.0.0',
+            workspaces: ['./a', './b', './d', './group/*'],
+            dependencies: { pacote: '1.0.0' },
+          }),
+          node_modules: {
+            a: t.fixture('symlink', '../a'),
+            b: t.fixture('symlink', '../b'),
+            c: {
+              'package.json': JSON.stringify({
+                name: 'c',
+                version: '1.0.0',
+              }),
+            },
+            d: t.fixture('symlink', '../d'),
+            e: t.fixture('symlink', '../group/e'),
+            f: t.fixture('symlink', '../group/f'),
+            foo: {
+              'package.json': JSON.stringify({
+                name: 'foo',
+                version: '1.1.1',
+                dependencies: {
+                  bar: '^1.0.0',
+                },
+              }),
+            },
+            bar: {
+              'package.json': JSON.stringify({ name: 'bar', version: '1.0.0' }),
+            },
+            baz: {
+              'package.json': JSON.stringify({ name: 'baz', version: '1.0.0' }),
+            },
+            pacote: {
+              'package.json': JSON.stringify({ name: 'pacote', version: '1.0.0' }),
+            },
+          },
+          a: {
+            'package.json': JSON.stringify({
+              name: 'a',
+              version: '1.0.0',
+              dependencies: {
+                c: '^1.0.0',
+                d: '^1.0.0',
+              },
+              devDependencies: {
+                baz: '^1.0.0',
+              },
+            }),
+          },
+          b: {
+            'package.json': JSON.stringify({
+              name: 'b',
+              version: '1.0.0',
+            }),
+          },
+          d: {
+            'package.json': JSON.stringify({
+              name: 'd',
+              version: '1.0.0',
+              dependencies: {
+                foo: '^1.1.1',
+              },
+            }),
+          },
+          group: {
+            e: {
+              'package.json': JSON.stringify({
+                name: 'e',
+                version: '1.0.0',
+              }),
+            },
+            f: {
+              'package.json': JSON.stringify({
+                name: 'f',
+                version: '1.0.0',
+              }),
+            },
+          },
+        },
+      })
+
+      await sbom.exec(exec)
+
+      t.matchSnapshot(result())
+    }
+
+    t.test('should list workspaces properly with default configs', t => mockWorkspaces(t, [], {
+      'sbom-format': 'spdx',
+    }))
+
+    t.test('should not list workspaces with --no-workspaces', t => mockWorkspaces(t, [], {
+      'sbom-format': 'spdx',
+      workspaces: false,
+    }))
+
+    t.test('should filter worksapces with --workspace', t => mockWorkspaces(t, [], {
+      'sbom-format': 'spdx',
+      workspace: 'a',
+    }))
+
+    t.test('should filter workspaces with multiple --workspace flags', t => mockWorkspaces(t, [], {
+      'sbom-format': 'spdx',
+      workspace: ['e', 'f'],
+    }))
+  })
+})
diff --git a/deps/npm/test/lib/commands/view.js b/deps/npm/test/lib/commands/view.js
index ca07ef9eec2ff6..a99c8d6242212c 100644
--- a/deps/npm/test/lib/commands/view.js
+++ b/deps/npm/test/lib/commands/view.js
@@ -101,6 +101,7 @@ const packument = (nv, opts) => {
         email: 'foo@yellow.com',
         twitter: 'foo',
       },
+      empty: '',
       readme: 'a very useful readme',
       versions: {
         '1.0.0': {
@@ -425,6 +426,11 @@ t.test('specific field names', async t => {
     await view.exec(['yellow@1.x.x', 'maintainers.name'])
     t.matchSnapshot(outputs.join('\n'))
   })
+
+  t.test('fields with empty values', async t => {
+    await view.exec(['yellow', 'empty'])
+    t.matchSnapshot(outputs.join('\n'))
+  })
 })
 
 t.test('throw error if global mode', async t => {
diff --git a/deps/npm/test/lib/utils/ansi-trim.js b/deps/npm/test/lib/utils/ansi-trim.js
deleted file mode 100644
index 5a9e3b0c87cba7..00000000000000
--- a/deps/npm/test/lib/utils/ansi-trim.js
+++ /dev/null
@@ -1,8 +0,0 @@
-const t = require('tap')
-const ansiTrim = require('../../../lib/utils/ansi-trim.js')
-
-t.test('basic', async t => {
-  const chalk = await import('chalk').then(v => v.default)
-  t.equal(ansiTrim('foo'), 'foo', 'does nothing if no ansis')
-  t.equal(ansiTrim(chalk.red('foo')), 'foo', 'strips out ansis')
-})
diff --git a/deps/npm/test/lib/utils/exit-handler.js b/deps/npm/test/lib/utils/exit-handler.js
index f553e1a2ea518d..3eb5840985b8f5 100644
--- a/deps/npm/test/lib/utils/exit-handler.js
+++ b/deps/npm/test/lib/utils/exit-handler.js
@@ -132,6 +132,8 @@ t.test('handles unknown error with logs and debug file', async (t) => {
   const { exitHandler, debugFile, logs } = await mockExitHandler(t)
 
   await exitHandler(err('Unknown error', 'ECODE'))
+  // force logfile cleaning logs to happen since those are purposefully not awaited
+  await require('timers/promises').setTimeout(200)
 
   const fileLogs = await debugFile()
   const fileLines = fileLogs.split('\n')
@@ -141,14 +143,19 @@ t.test('handles unknown error with logs and debug file', async (t) => {
 
   t.equal(process.exitCode, 1)
 
+  let skippedLogs = 0
   logs.forEach((logItem, i) => {
     const logLines = format(i, ...logItem).trim().split(os.EOL)
-    logLines.forEach((line) => {
+    for (const line of logLines) {
+      if (line.includes('logfile') && line.includes('cleaning')) {
+        skippedLogs++
+        continue
+      }
       t.match(fileLogs.trim(), line, 'log appears in debug file')
-    })
+    }
   })
 
-  t.equal(logs.length, parseInt(lastLog) + 1)
+  t.equal(logs.length - skippedLogs, parseInt(lastLog) + 1)
   t.match(logs.error, [
     ['code', 'ECODE'],
     ['ERR SUMMARY', 'Unknown error'],
diff --git a/deps/npm/test/lib/utils/sbom-cyclonedx.js b/deps/npm/test/lib/utils/sbom-cyclonedx.js
new file mode 100644
index 00000000000000..540feb9eb0ee34
--- /dev/null
+++ b/deps/npm/test/lib/utils/sbom-cyclonedx.js
@@ -0,0 +1,245 @@
+const t = require('tap')
+const Ajv = require('ajv')
+const applyFormats = require('ajv-formats')
+const applyDraftFormats = require('ajv-formats-draft2019')
+const { cyclonedxOutput } = require('../../../lib/utils/sbom-cyclonedx.js')
+
+const FAKE_UUID = 'urn:uuid:00000000-0000-0000-0000-000000000000'
+
+t.cleanSnapshot = s => {
+  let sbom
+  try {
+    sbom = JSON.parse(s)
+  } catch (e) {
+    return s
+  }
+
+  sbom.serialNumber = FAKE_UUID
+  if (sbom.metadata) {
+    sbom.metadata.timestamp = '2020-01-01T00:00:00.000Z'
+  }
+
+  return JSON.stringify(sbom, null, 2)
+}
+
+const npm = { version: '10.0.0 ' }
+
+const rootPkg = {
+  author: 'Author',
+}
+
+const root = {
+  name: 'root',
+  packageName: 'root',
+  version: '1.0.0',
+  pkgid: 'root@1.0.0',
+  isRoot: true,
+  package: rootPkg,
+  location: '',
+  edgesOut: [],
+}
+
+const dep1 = {
+  name: 'dep1',
+  packageName: 'dep1',
+  version: '0.0.1',
+  pkgid: 'dep1@0.0.1',
+  package: {},
+  location: 'node_modules/dep1',
+  edgesOut: [],
+}
+
+const dep2 = {
+  name: 'dep2',
+  packageName: 'dep2',
+  version: '0.0.2',
+  pkgid: 'npm@npm:dep2@0.0.2',
+  package: {},
+  location: 'node_modules/dep2',
+  edgesOut: [{ to: dep1 }],
+}
+
+const dep2Link = {
+  name: 'dep2',
+  packageName: 'dep2',
+  version: '0.0.2',
+  pkgid: 'dep2@0.0.2',
+  package: {},
+  location: 'node_modules/dep2',
+  edgesOut: [],
+  isLink: true,
+  target: dep2,
+}
+
+t.test('single node - application package type', t => {
+  const res = cyclonedxOutput({ npm, nodes: [root], packageType: 'application' })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - package lock only', t => {
+  const res = cyclonedxOutput({ npm, nodes: [root], packageLockOnly: true })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - optional ', t => {
+  const node = { ...root, optional: true }
+  const res = cyclonedxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - with description', t => {
+  const pkg = { ...rootPkg, description: 'Package description' }
+  const node = { ...root, package: pkg }
+  const res = cyclonedxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - with author object', t => {
+  const pkg = { ...rootPkg, author: { name: 'Arthur' } }
+  const node = { ...root, package: pkg }
+  const res = cyclonedxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - with integrity', t => {
+  /* eslint-disable-next-line max-len */
+  const node = { ...root, integrity: 'sha512-1RkbFGUKex4lvsB9yhIfWltJM5cZKUftB2eNajaDv3dCMEp49iBG0K14uH8NnX9IPux2+mK7JGEOB0jn48/J6w==' }
+  const res = cyclonedxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - development', t => {
+  const node = { ...root, dev: true }
+  const res = cyclonedxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - extraneous', t => {
+  const node = { ...root, extraneous: true }
+  const res = cyclonedxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - bundled', t => {
+  const node = { ...root, inBundle: true }
+  const res = cyclonedxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - private', t => {
+  const pkg = { ...rootPkg, private: true }
+  const node = { ...root, package: pkg }
+  const res = cyclonedxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - with repository url', t => {
+  const pkg = { ...rootPkg, repository: { url: 'https://foo.bar' } }
+  const node = { ...root, package: pkg }
+  const res = cyclonedxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - with homepage', t => {
+  const pkg = { ...rootPkg, homepage: 'https://foo.bar/README.md' }
+  const node = { ...root, package: pkg }
+  const res = cyclonedxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - with issue tracker', t => {
+  const pkg = { ...rootPkg, bugs: { url: 'https://foo.bar/issues' } }
+  const node = { ...root, package: pkg }
+  const res = cyclonedxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - with distribution url', t => {
+  const node = { ...root, resolved: 'https://registry.npmjs.org/root/-/root-1.0.0.tgz' }
+  const res = cyclonedxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - with single license', t => {
+  const pkg = { ...rootPkg, license: 'ISC' }
+  const node = { ...root, package: pkg }
+  const res = cyclonedxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - with license expression', t => {
+  const pkg = { ...rootPkg, license: '(MIT OR Apache-2.0)' }
+  const node = { ...root, package: pkg }
+  const res = cyclonedxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - from git url', t => {
+  const node = { ...root, type: 'git', resolved: 'https://github.com/foo/bar#1234' }
+  const res = cyclonedxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - no package info', t => {
+  const node = { ...root, package: undefined }
+  const res = cyclonedxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('node - with deps', t => {
+  const node = { ...root,
+    edgesOut: [
+      { to: dep1 },
+      { to: dep2 },
+      { to: undefined },
+      { to: { pkgid: 'foo' } },
+    ] }
+  const res = cyclonedxOutput({ npm, nodes: [node, dep1, dep2, dep2Link] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+// Check that all of the generated test snapshots validate against the CycloneDX schema
+t.test('schema validation', t => {
+  // Load schemas
+  const cdxSchema = require('../../schemas/cyclonedx/bom-1.5.schema.json')
+  const spdxLicenseSchema = require('../../schemas/cyclonedx/spdx.schema.json')
+  const jsfSchema = require('../../schemas/cyclonedx/jsf-0.82.schema.json')
+
+  const ajv = new Ajv({
+    strict: false,
+    schemas: [spdxLicenseSchema, jsfSchema, cdxSchema],
+  })
+  applyFormats(ajv)
+  applyDraftFormats(ajv)
+
+  // Retrieve compiled schema
+  const validate = ajv.getSchema('http://cyclonedx.org/schema/bom-1.5.schema.json')
+
+  // Load snapshots for all tests in this file
+  const sboms = require('../../../tap-snapshots/test/lib/utils/sbom-cyclonedx.js.test.cjs')
+
+  // Check that all snapshots validate against the CycloneDX schema
+  Object.entries(sboms).forEach(([name, sbom]) => {
+    t.ok(validate(JSON.parse(sbom)), { snapshot: name, error: validate.errors?.[0] })
+  })
+  t.end()
+})
diff --git a/deps/npm/test/lib/utils/sbom-spdx.js b/deps/npm/test/lib/utils/sbom-spdx.js
new file mode 100644
index 00000000000000..74f6c3f34e71c4
--- /dev/null
+++ b/deps/npm/test/lib/utils/sbom-spdx.js
@@ -0,0 +1,188 @@
+const t = require('tap')
+const Ajv = require('ajv')
+const { spdxOutput } = require('../../../lib/utils/sbom-spdx.js')
+
+t.cleanSnapshot = s => {
+  let sbom
+  try {
+    sbom = JSON.parse(s)
+  } catch (e) {
+    return s
+  }
+
+  sbom.documentNamespace = 'docns'
+
+  if (sbom.creationInfo) {
+    sbom.creationInfo.created = '2020-01-01T00:00:00.000Z'
+  }
+
+  return JSON.stringify(sbom, null, 2)
+}
+
+const npm = { version: '10.0.0 ' }
+
+const rootPkg = {
+  author: 'Author',
+}
+
+const root = {
+  packageName: 'root',
+  version: '1.0.0',
+  pkgid: 'root@1.0.0',
+  isRoot: true,
+  package: rootPkg,
+  location: '',
+  edgesOut: [],
+}
+
+const dep1 = {
+  packageName: 'dep1',
+  version: '0.0.1',
+  pkgid: 'dep1@0.0.1',
+  package: {},
+  location: 'node_modules/dep1',
+  edgesOut: [],
+}
+
+const dep2 = {
+  packageName: 'dep2',
+  version: '0.0.2',
+  pkgid: 'dep2@0.0.2',
+  package: {},
+  location: 'node_modules/dep2',
+  edgesOut: [],
+}
+
+const dep3 = {
+  packageName: 'dep3',
+  version: '0.0.3',
+  pkgid: 'dep3@0.0.3',
+  package: {},
+  location: 'node_modules/dep3',
+  edgesOut: [],
+}
+
+const dep5 = {
+  packageName: 'dep5',
+  version: '0.0.5',
+  pkgid: 'dep5@0.0.5',
+  package: {},
+  location: 'node_modules/dep5',
+  edgesOut: [],
+}
+
+const dep4 = {
+  packageName: 'dep4',
+  version: '0.0.4',
+  pkgid: 'npm@npm:dep4@0.0.4',
+  package: {},
+  location: 'dep4',
+  isWorkspace: true,
+  edgesOut: [{ to: dep5 }],
+}
+
+const dep4Link = {
+  packageName: 'dep4',
+  version: '0.0.4',
+  pkgid: 'dep4@0.0.4',
+  package: {},
+  location: 'node_modules/dep4',
+  isLink: true,
+  target: dep4,
+}
+
+dep4.linksIn = new Set([dep4Link])
+
+const dep6 = {
+  packageName: 'dep6',
+  version: '0.0.6',
+  pkgid: 'dep6@0.0.6',
+  extraneous: true,
+  package: {},
+  location: 'node_modules/dep6',
+  edgesOut: [],
+}
+
+t.test('single node - application package type', t => {
+  const res = spdxOutput({ npm, nodes: [root], packageType: 'application' })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - with description', t => {
+  const pkg = { ...rootPkg, description: 'Package description' }
+  const node = { ...root, package: pkg }
+  const res = spdxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - with distribution url', t => {
+  const node = { ...root, resolved: 'https://registry.npmjs.org/root/-/root-1.0.0.tgz' }
+  const res = spdxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - with homepage', t => {
+  const pkg = { ...rootPkg, homepage: 'https://foo.bar/README.md' }
+  const node = { ...root, package: pkg }
+  const res = spdxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - with integrity', t => {
+  /* eslint-disable-next-line max-len */
+  const node = { ...root, integrity: 'sha512-1RkbFGUKex4lvsB9yhIfWltJM5cZKUftB2eNajaDv3dCMEp49iBG0K14uH8NnX9IPux2+mK7JGEOB0jn48/J6w==' }
+  const res = spdxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - from git url', t => {
+  const node = { ...root, type: 'git', resolved: 'https://github.com/foo/bar#1234' }
+  const res = spdxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('single node - linked', t => {
+  const node = { ...root, isLink: true, target: { edgesOut: [] } }
+  const res = spdxOutput({ npm, nodes: [node] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+t.test('node - with deps', t => {
+  const node = { ...root,
+    edgesOut: [
+      { to: dep1, type: 'peer' },
+      { to: dep2, type: 'optional' },
+      { to: dep3, type: 'dev' },
+      { to: dep4 },
+      { to: undefined },
+      { to: { packageName: 'foo' } },
+    ] }
+  const res = spdxOutput({ npm, nodes: [node, dep1, dep2, dep3, dep4Link, dep4, dep5, dep6] })
+  t.matchSnapshot(JSON.stringify(res))
+  t.end()
+})
+
+// Check that all of the generated test snapshots validate against the SPDX schema
+t.test('schema validation', t => {
+  const ajv = new Ajv()
+
+  // Compile schema
+  const spdxSchema = require('../../schemas/spdx/spdx-2.3.schema.json')
+  const validate = ajv.compile(spdxSchema)
+
+  // Load snapshots for all tests in this file
+  const sboms = require('../../../tap-snapshots/test/lib/utils/sbom-spdx.js.test.cjs')
+
+  // Check that all snapshots validate against the SPDX schema
+  Object.entries(sboms).forEach(([name, sbom]) => {
+    t.ok(validate(JSON.parse(sbom)), { snapshot: name, error: validate.errors?.[0] })
+  })
+  t.end()
+})
diff --git a/deps/npm/test/schemas/cyclonedx/bom-1.5.schema.json b/deps/npm/test/schemas/cyclonedx/bom-1.5.schema.json
new file mode 100644
index 00000000000000..3ecc1dcdb47557
--- /dev/null
+++ b/deps/npm/test/schemas/cyclonedx/bom-1.5.schema.json
@@ -0,0 +1,3799 @@
+{
+  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$id": "http://cyclonedx.org/schema/bom-1.5.schema.json",
+  "type": "object",
+  "title": "CycloneDX Software Bill of Materials Standard",
+  "$comment" : "CycloneDX JSON schema is published under the terms of the Apache License 2.0.",
+  "required": [
+    "bomFormat",
+    "specVersion"
+  ],
+  "additionalProperties": false,
+  "properties": {
+    "$schema": {
+      "type": "string",
+      "enum": [
+        "http://cyclonedx.org/schema/bom-1.5.schema.json"
+      ]
+    },
+    "bomFormat": {
+      "type": "string",
+      "title": "BOM Format",
+      "description": "Specifies the format of the BOM. This helps to identify the file as CycloneDX since BOMs do not have a filename convention nor does JSON schema support namespaces. This value MUST be \"CycloneDX\".",
+      "enum": [
+        "CycloneDX"
+      ]
+    },
+    "specVersion": {
+      "type": "string",
+      "title": "CycloneDX Specification Version",
+      "description": "The version of the CycloneDX specification a BOM conforms to (starting at version 1.2).",
+      "examples": ["1.5"]
+    },
+    "serialNumber": {
+      "type": "string",
+      "title": "BOM Serial Number",
+      "description": "Every BOM generated SHOULD have a unique serial number, even if the contents of the BOM have not changed over time. If specified, the serial number MUST conform to RFC-4122. Use of serial numbers are RECOMMENDED.",
+      "examples": ["urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79"],
+      "pattern": "^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
+    },
+    "version": {
+      "type": "integer",
+      "title": "BOM Version",
+      "description": "Whenever an existing BOM is modified, either manually or through automated processes, the version of the BOM SHOULD be incremented by 1. When a system is presented with multiple BOMs with identical serial numbers, the system SHOULD use the most recent version of the BOM. The default version is '1'.",
+      "minimum": 1,
+      "default": 1,
+      "examples": [1]
+    },
+    "metadata": {
+      "$ref": "#/definitions/metadata",
+      "title": "BOM Metadata",
+      "description": "Provides additional information about a BOM."
+    },
+    "components": {
+      "type": "array",
+      "items": {"$ref": "#/definitions/component"},
+      "uniqueItems": true,
+      "title": "Components",
+      "description": "A list of software and hardware components."
+    },
+    "services": {
+      "type": "array",
+      "items": {"$ref": "#/definitions/service"},
+      "uniqueItems": true,
+      "title": "Services",
+      "description": "A list of services. This may include microservices, function-as-a-service, and other types of network or intra-process services."
+    },
+    "externalReferences": {
+      "type": "array",
+      "items": {"$ref": "#/definitions/externalReference"},
+      "title": "External References",
+      "description": "External references provide a way to document systems, sites, and information that may be relevant, but are not included with the BOM. They may also establish specific relationships within or external to the BOM."
+    },
+    "dependencies": {
+      "type": "array",
+      "items": {"$ref": "#/definitions/dependency"},
+      "uniqueItems": true,
+      "title": "Dependencies",
+      "description": "Provides the ability to document dependency relationships."
+    },
+    "compositions": {
+      "type": "array",
+      "items": {"$ref": "#/definitions/compositions"},
+      "uniqueItems": true,
+      "title": "Compositions",
+      "description": "Compositions describe constituent parts (including components, services, and dependency relationships) and their completeness. The completeness of vulnerabilities expressed in a BOM may also be described."
+    },
+    "vulnerabilities": {
+      "type": "array",
+      "items": {"$ref": "#/definitions/vulnerability"},
+      "uniqueItems": true,
+      "title": "Vulnerabilities",
+      "description": "Vulnerabilities identified in components or services."
+    },
+    "annotations": {
+      "type": "array",
+      "items": {"$ref": "#/definitions/annotations"},
+      "uniqueItems": true,
+      "title": "Annotations",
+      "description": "Comments made by people, organizations, or tools about any object with a bom-ref, such as components, services, vulnerabilities, or the BOM itself. Unlike inventory information, annotations may contain opinion or commentary from various stakeholders. Annotations may be inline (with inventory) or externalized via BOM-Link, and may optionally be signed."
+    },
+    "formulation": {
+      "type": "array",
+      "items": {"$ref": "#/definitions/formula"},
+      "uniqueItems": true,
+      "title": "Formulation",
+      "description": "Describes how a component or service was manufactured or deployed. This is achieved through the use of formulas, workflows, tasks, and steps, which declare the precise steps to reproduce along with the observed formulas describing the steps which transpired in the manufacturing process."
+    },
+    "properties": {
+      "type": "array",
+      "title": "Properties",
+      "description": "Provides the ability to document properties in a name-value store. This provides flexibility to include data not officially supported in the standard without having to use additional namespaces or create extensions. Unlike key-value stores, properties support duplicate names, each potentially having different values. Property names of interest to the general public are encouraged to be registered in the [CycloneDX Property Taxonomy](https://github.com/CycloneDX/cyclonedx-property-taxonomy). Formal registration is OPTIONAL.",
+      "items": {
+        "$ref": "#/definitions/property"
+      }
+    },
+    "signature": {
+      "$ref": "#/definitions/signature",
+      "title": "Signature",
+      "description": "Enveloped signature in [JSON Signature Format (JSF)](https://cyberphone.github.io/doc/security/jsf.html)."
+    }
+  },
+  "definitions": {
+    "refType": {
+      "description": "Identifier for referable and therefore interlink-able elements.",
+      "type": "string",
+      "minLength": 1,
+      "$comment": "value SHOULD not start with the BOM-Link intro 'urn:cdx:'"
+    },
+    "refLinkType": {
+      "description": "Descriptor for an element identified by the attribute 'bom-ref' in the same BOM document.\nIn contrast to `bomLinkElementType`.",
+      "allOf": [{"$ref": "#/definitions/refType"}]
+    },
+    "bomLinkDocumentType": {
+      "title": "BOM-Link Document",
+      "description": "Descriptor for another BOM document. See https://cyclonedx.org/capabilities/bomlink/",
+      "type": "string",
+      "format": "iri-reference",
+      "pattern": "^urn:cdx:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/[1-9][0-9]*$",
+      "$comment": "part of the pattern is based on `bom.serialNumber`'s pattern"
+    },
+    "bomLinkElementType": {
+      "title": "BOM-Link Element",
+      "description": "Descriptor for an element in a BOM document. See https://cyclonedx.org/capabilities/bomlink/",
+      "type": "string",
+      "format": "iri-reference",
+      "pattern": "^urn:cdx:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/[1-9][0-9]*#.+$",
+      "$comment": "part of the pattern is based on `bom.serialNumber`'s pattern"
+    },
+    "bomLink": {
+      "anyOf": [
+        {
+          "title": "BOM-Link Document",
+          "$ref": "#/definitions/bomLinkDocumentType"
+        },
+        {
+          "title": "BOM-Link Element",
+          "$ref": "#/definitions/bomLinkElementType"
+        }
+      ]
+    },
+    "metadata": {
+      "type": "object",
+      "title": "BOM Metadata Object",
+      "additionalProperties": false,
+      "properties": {
+        "timestamp": {
+          "type": "string",
+          "format": "date-time",
+          "title": "Timestamp",
+          "description": "The date and time (timestamp) when the BOM was created."
+        },
+        "lifecycles": {
+          "type": "array",
+          "title": "Lifecycles",
+          "description": "",
+          "items": {
+            "type": "object",
+            "title": "Lifecycle",
+            "description": "The product lifecycle(s) that this BOM represents.",
+            "oneOf": [
+              {
+                "required": ["phase"],
+                "additionalProperties": false,
+                "properties": {
+                  "phase": {
+                    "type": "string",
+                    "title": "Phase",
+                    "description": "A pre-defined phase in the product lifecycle.\n\n* __design__ = BOM produced early in the development lifecycle containing inventory of components and services that are proposed or planned to be used. The inventory may need to be procured, retrieved, or resourced prior to use.\n* __pre-build__ = BOM consisting of information obtained prior to a build process and may contain source files and development artifacts and manifests. The inventory may need to be resolved and retrieved prior to use.\n* __build__ = BOM consisting of information obtained during a build process where component inventory is available for use. The precise versions of resolved components are usually available at this time as well as the provenance of where the components were retrieved from.\n* __post-build__ = BOM consisting of information obtained after a build process has completed and the resulting components(s) are available for further analysis. Built components may exist as the result of a CI/CD process, may have been installed or deployed to a system or device, and may need to be retrieved or extracted from the system or device.\n* __operations__ = BOM produced that represents inventory that is running and operational. This may include staging or production environments and will generally encompass multiple SBOMs describing the applications and operating system, along with HBOMs describing the hardware that makes up the system. Operations Bill of Materials (OBOM) can provide full-stack inventory of runtime environments, configurations, and additional dependencies.\n* __discovery__ = BOM consisting of information observed through network discovery providing point-in-time enumeration of embedded, on-premise, and cloud-native services such as server applications, connected devices, microservices, and serverless functions.\n* __decommission__ = BOM containing inventory that will be, or has been retired from operations.",
+                    "enum": [
+                      "design",
+                      "pre-build",
+                      "build",
+                      "post-build",
+                      "operations",
+                      "discovery",
+                      "decommission"
+                    ]
+                  }
+                }
+              },
+              {
+                "required": ["name"],
+                "additionalProperties": false,
+                "properties": {
+                  "name": {
+                    "type": "string",
+                    "title": "Name",
+                    "description": "The name of the lifecycle phase"
+                  },
+                  "description": {
+                    "type": "string",
+                    "title": "Description",
+                    "description": "The description of the lifecycle phase"
+                  }
+                }
+              }
+            ]
+          }
+      },
+        "tools": {
+          "oneOf": [
+            {
+              "type": "object",
+              "title": "Creation Tools",
+              "description": "The tool(s) used in the creation of the BOM.",
+              "additionalProperties": false,
+              "properties": {
+                "components": {
+                  "type": "array",
+                  "items": {"$ref": "#/definitions/component"},
+                  "uniqueItems": true,
+                  "title": "Components",
+                  "description": "A list of software and hardware components used as tools"
+                },
+                "services": {
+                  "type": "array",
+                  "items": {"$ref": "#/definitions/service"},
+                  "uniqueItems": true,
+                  "title": "Services",
+                  "description": "A list of services used as tools. This may include microservices, function-as-a-service, and other types of network or intra-process services."
+                }
+              }
+            },
+            {
+              "type": "array",
+              "title": "Creation Tools (legacy)",
+              "description": "[Deprecated] The tool(s) used in the creation of the BOM.",
+              "items": {"$ref": "#/definitions/tool"}
+            }
+          ]
+        },
+        "authors" :{
+          "type": "array",
+          "title": "Authors",
+          "description": "The person(s) who created the BOM. Authors are common in BOMs created through manual processes. BOMs created through automated means may not have authors.",
+          "items": {"$ref": "#/definitions/organizationalContact"}
+        },
+        "component": {
+          "title": "Component",
+          "description": "The component that the BOM describes.",
+          "$ref": "#/definitions/component"
+        },
+        "manufacture": {
+          "title": "Manufacture",
+          "description": "The organization that manufactured the component that the BOM describes.",
+          "$ref": "#/definitions/organizationalEntity"
+        },
+        "supplier": {
+          "title": "Supplier",
+          "description": " The organization that supplied the component that the BOM describes. The supplier may often be the manufacturer, but may also be a distributor or repackager.",
+          "$ref": "#/definitions/organizationalEntity"
+        },
+        "licenses": {
+          "title": "BOM License(s)",
+          "$ref": "#/definitions/licenseChoice"
+        },
+        "properties": {
+          "type": "array",
+          "title": "Properties",
+          "description": "Provides the ability to document properties in a name-value store. This provides flexibility to include data not officially supported in the standard without having to use additional namespaces or create extensions. Unlike key-value stores, properties support duplicate names, each potentially having different values. Property names of interest to the general public are encouraged to be registered in the [CycloneDX Property Taxonomy](https://github.com/CycloneDX/cyclonedx-property-taxonomy). Formal registration is OPTIONAL.",
+          "items": {"$ref": "#/definitions/property"}
+        }
+      }
+    },
+    "tool": {
+      "type": "object",
+      "title": "Tool",
+      "description": "[Deprecated] - DO NOT USE. This will be removed in a future version. This will be removed in a future version. Use component or service instead. Information about the automated or manual tool used",
+      "additionalProperties": false,
+      "properties": {
+        "vendor": {
+          "type": "string",
+          "title": "Tool Vendor",
+          "description": "The name of the vendor who created the tool"
+        },
+        "name": {
+          "type": "string",
+          "title": "Tool Name",
+          "description": "The name of the tool"
+        },
+        "version": {
+          "type": "string",
+          "title": "Tool Version",
+          "description": "The version of the tool"
+        },
+        "hashes": {
+          "type": "array",
+          "items": {"$ref": "#/definitions/hash"},
+          "title": "Hashes",
+          "description": "The hashes of the tool (if applicable)."
+        },
+        "externalReferences": {
+          "type": "array",
+          "items": {"$ref": "#/definitions/externalReference"},
+          "title": "External References",
+          "description": "External references provide a way to document systems, sites, and information that may be relevant, but are not included with the BOM. They may also establish specific relationships within or external to the BOM."
+        }
+      }
+    },
+    "organizationalEntity": {
+      "type": "object",
+      "title": "Organizational Entity Object",
+      "description": "",
+      "additionalProperties": false,
+      "properties": {
+        "bom-ref": {
+          "$ref": "#/definitions/refType",
+          "title": "BOM Reference",
+          "description": "An optional identifier which can be used to reference the object elsewhere in the BOM. Every bom-ref MUST be unique within the BOM."
+        },
+        "name": {
+          "type": "string",
+          "title": "Name",
+          "description": "The name of the organization",
+          "examples": [
+            "Example Inc."
+          ]
+        },
+        "url": {
+          "type": "array",
+          "items": {
+            "type": "string",
+            "format": "iri-reference"
+          },
+          "title": "URL",
+          "description": "The URL of the organization. Multiple URLs are allowed.",
+          "examples": ["https://example.com"]
+        },
+        "contact": {
+          "type": "array",
+          "title": "Contact",
+          "description": "A contact at the organization. Multiple contacts are allowed.",
+          "items": {"$ref": "#/definitions/organizationalContact"}
+        }
+      }
+    },
+    "organizationalContact": {
+      "type": "object",
+      "title": "Organizational Contact Object",
+      "description": "",
+      "additionalProperties": false,
+      "properties": {
+        "bom-ref": {
+          "$ref": "#/definitions/refType",
+          "title": "BOM Reference",
+          "description": "An optional identifier which can be used to reference the object elsewhere in the BOM. Every bom-ref MUST be unique within the BOM."
+        },
+        "name": {
+          "type": "string",
+          "title": "Name",
+          "description": "The name of a contact",
+          "examples": ["Contact name"]
+        },
+        "email": {
+          "type": "string",
+          "format": "idn-email",
+          "title": "Email Address",
+          "description": "The email address of the contact.",
+          "examples": ["firstname.lastname@example.com"]
+        },
+        "phone": {
+          "type": "string",
+          "title": "Phone",
+          "description": "The phone number of the contact.",
+          "examples": ["800-555-1212"]
+        }
+      }
+    },
+    "component": {
+      "type": "object",
+      "title": "Component Object",
+      "required": [
+        "type",
+        "name"
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "type": {
+          "type": "string",
+          "enum": [
+            "application",
+            "framework",
+            "library",
+            "container",
+            "platform",
+            "operating-system",
+            "device",
+            "device-driver",
+            "firmware",
+            "file",
+            "machine-learning-model",
+            "data"
+          ],
+          "title": "Component Type",
+          "description": "Specifies the type of component. For software components, classify as application if no more specific appropriate classification is available or cannot be determined for the component. Types include:\n\n* __application__ = A software application. Refer to [https://en.wikipedia.org/wiki/Application_software](https://en.wikipedia.org/wiki/Application_software) for information about applications.\n* __framework__ = A software framework. Refer to [https://en.wikipedia.org/wiki/Software_framework](https://en.wikipedia.org/wiki/Software_framework) for information on how frameworks vary slightly from libraries.\n* __library__ = A software library. Refer to [https://en.wikipedia.org/wiki/Library_(computing)](https://en.wikipedia.org/wiki/Library_(computing))\n for information about libraries. All third-party and open source reusable components will likely be a library. If the library also has key features of a framework, then it should be classified as a framework. If not, or is unknown, then specifying library is RECOMMENDED.\n* __container__ = A packaging and/or runtime format, not specific to any particular technology, which isolates software inside the container from software outside of a container through virtualization technology. Refer to [https://en.wikipedia.org/wiki/OS-level_virtualization](https://en.wikipedia.org/wiki/OS-level_virtualization)\n* __platform__ = A runtime environment which interprets or executes software. This may include runtimes such as those that execute bytecode or low-code/no-code application platforms.\n* __operating-system__ = A software operating system without regard to deployment model (i.e. installed on physical hardware, virtual machine, image, etc) Refer to [https://en.wikipedia.org/wiki/Operating_system](https://en.wikipedia.org/wiki/Operating_system)\n* __device__ = A hardware device such as a processor, or chip-set. A hardware device containing firmware SHOULD include a component for the physical hardware itself, and another component of type 'firmware' or 'operating-system' (whichever is relevant), describing information about the software running on the device.\n  See also the list of [known device properties](https://github.com/CycloneDX/cyclonedx-property-taxonomy/blob/main/cdx/device.md).\n* __device-driver__ = A special type of software that operates or controls a particular type of device. Refer to [https://en.wikipedia.org/wiki/Device_driver](https://en.wikipedia.org/wiki/Device_driver)\n* __firmware__ = A special type of software that provides low-level control over a devices hardware. Refer to [https://en.wikipedia.org/wiki/Firmware](https://en.wikipedia.org/wiki/Firmware)\n* __file__ = A computer file. Refer to [https://en.wikipedia.org/wiki/Computer_file](https://en.wikipedia.org/wiki/Computer_file) for information about files.\n* __machine-learning-model__ = A model based on training data that can make predictions or decisions without being explicitly programmed to do so.\n* __data__ = A collection of discrete values that convey information.",
+          "examples": ["library"]
+        },
+        "mime-type": {
+          "type": "string",
+          "title": "Mime-Type",
+          "description": "The optional mime-type of the component. When used on file components, the mime-type can provide additional context about the kind of file being represented such as an image, font, or executable. Some library or framework components may also have an associated mime-type.",
+          "examples": ["image/jpeg"],
+          "pattern": "^[-+a-z0-9.]+/[-+a-z0-9.]+$"
+        },
+        "bom-ref": {
+          "$ref": "#/definitions/refType",
+          "title": "BOM Reference",
+          "description": "An optional identifier which can be used to reference the component elsewhere in the BOM. Every bom-ref MUST be unique within the BOM."
+        },
+        "supplier": {
+          "title": "Component Supplier",
+          "description": " The organization that supplied the component. The supplier may often be the manufacturer, but may also be a distributor or repackager.",
+          "$ref": "#/definitions/organizationalEntity"
+        },
+        "author": {
+          "type": "string",
+          "title": "Component Author",
+          "description": "The person(s) or organization(s) that authored the component",
+          "examples": ["Acme Inc"]
+        },
+        "publisher": {
+          "type": "string",
+          "title": "Component Publisher",
+          "description": "The person(s) or organization(s) that published the component",
+          "examples": ["Acme Inc"]
+        },
+        "group": {
+          "type": "string",
+          "title": "Component Group",
+          "description": "The grouping name or identifier. This will often be a shortened, single name of the company or project that produced the component, or the source package or domain name. Whitespace and special characters should be avoided. Examples include: apache, org.apache.commons, and apache.org.",
+          "examples": ["com.acme"]
+        },
+        "name": {
+          "type": "string",
+          "title": "Component Name",
+          "description": "The name of the component. This will often be a shortened, single name of the component. Examples: commons-lang3 and jquery",
+          "examples": ["tomcat-catalina"]
+        },
+        "version": {
+          "type": "string",
+          "title": "Component Version",
+          "description": "The component version. The version should ideally comply with semantic versioning but is not enforced.",
+          "examples": ["9.0.14"]
+        },
+        "description": {
+          "type": "string",
+          "title": "Component Description",
+          "description": "Specifies a description for the component"
+        },
+        "scope": {
+          "type": "string",
+          "enum": [
+            "required",
+            "optional",
+            "excluded"
+          ],
+          "title": "Component Scope",
+          "description": "Specifies the scope of the component. If scope is not specified, 'required' scope SHOULD be assumed by the consumer of the BOM.",
+          "default": "required"
+        },
+        "hashes": {
+          "type": "array",
+          "title": "Component Hashes",
+          "items": {"$ref": "#/definitions/hash"}
+        },
+        "licenses": {
+          "$ref": "#/definitions/licenseChoice",
+          "title": "Component License(s)"
+        },
+        "copyright": {
+          "type": "string",
+          "title": "Component Copyright",
+          "description": "A copyright notice informing users of the underlying claims to copyright ownership in a published work.",
+          "examples": ["Acme Inc"]
+        },
+        "cpe": {
+          "type": "string",
+          "title": "Component Common Platform Enumeration (CPE)",
+          "description": "Specifies a well-formed CPE name that conforms to the CPE 2.2 or 2.3 specification. See [https://nvd.nist.gov/products/cpe](https://nvd.nist.gov/products/cpe)",
+          "examples": ["cpe:2.3:a:acme:component_framework:-:*:*:*:*:*:*:*"]
+        },
+        "purl": {
+          "type": "string",
+          "title": "Component Package URL (purl)",
+          "description": "Specifies the package-url (purl). The purl, if specified, MUST be valid and conform to the specification defined at: [https://github.com/package-url/purl-spec](https://github.com/package-url/purl-spec)",
+          "examples": ["pkg:maven/com.acme/tomcat-catalina@9.0.14?packaging=jar"]
+        },
+        "swid": {
+          "$ref": "#/definitions/swid",
+          "title": "SWID Tag",
+          "description": "Specifies metadata and content for [ISO-IEC 19770-2 Software Identification (SWID) Tags](https://www.iso.org/standard/65666.html)."
+        },
+        "modified": {
+          "type": "boolean",
+          "title": "Component Modified From Original",
+          "description": "[Deprecated] - DO NOT USE. This will be removed in a future version. Use the pedigree element instead to supply information on exactly how the component was modified. A boolean value indicating if the component has been modified from the original. A value of true indicates the component is a derivative of the original. A value of false indicates the component has not been modified from the original."
+        },
+        "pedigree": {
+          "type": "object",
+          "title": "Component Pedigree",
+          "description": "Component pedigree is a way to document complex supply chain scenarios where components are created, distributed, modified, redistributed, combined with other components, etc. Pedigree supports viewing this complex chain from the beginning, the end, or anywhere in the middle. It also provides a way to document variants where the exact relation may not be known.",
+          "additionalProperties": false,
+          "properties": {
+            "ancestors": {
+              "type": "array",
+              "title": "Ancestors",
+              "description": "Describes zero or more components in which a component is derived from. This is commonly used to describe forks from existing projects where the forked version contains a ancestor node containing the original component it was forked from. For example, Component A is the original component. Component B is the component being used and documented in the BOM. However, Component B contains a pedigree node with a single ancestor documenting Component A - the original component from which Component B is derived from.",
+              "items": {"$ref": "#/definitions/component"}
+            },
+            "descendants": {
+              "type": "array",
+              "title": "Descendants",
+              "description": "Descendants are the exact opposite of ancestors. This provides a way to document all forks (and their forks) of an original or root component.",
+              "items": {"$ref": "#/definitions/component"}
+            },
+            "variants": {
+              "type": "array",
+              "title": "Variants",
+              "description": "Variants describe relations where the relationship between the components are not known. For example, if Component A contains nearly identical code to Component B. They are both related, but it is unclear if one is derived from the other, or if they share a common ancestor.",
+              "items": {"$ref": "#/definitions/component"}
+            },
+            "commits": {
+              "type": "array",
+              "title": "Commits",
+              "description": "A list of zero or more commits which provide a trail describing how the component deviates from an ancestor, descendant, or variant.",
+              "items": {"$ref": "#/definitions/commit"}
+            },
+            "patches": {
+              "type": "array",
+              "title": "Patches",
+              "description": ">A list of zero or more patches describing how the component deviates from an ancestor, descendant, or variant. Patches may be complimentary to commits or may be used in place of commits.",
+              "items": {"$ref": "#/definitions/patch"}
+            },
+            "notes": {
+              "type": "string",
+              "title": "Notes",
+              "description": "Notes, observations, and other non-structured commentary describing the components pedigree."
+            }
+          }
+        },
+        "externalReferences": {
+          "type": "array",
+          "items": {"$ref": "#/definitions/externalReference"},
+          "title": "External References",
+          "description": "External references provide a way to document systems, sites, and information that may be relevant, but are not included with the BOM. They may also establish specific relationships within or external to the BOM."
+        },
+        "components": {
+          "type": "array",
+          "items": {"$ref": "#/definitions/component"},
+          "uniqueItems": true,
+          "title": "Components",
+          "description": "A list of software and hardware components included in the parent component. This is not a dependency tree. It provides a way to specify a hierarchical representation of component assemblies, similar to system → subsystem → parts assembly in physical supply chains."
+        },
+        "evidence": {
+          "$ref": "#/definitions/componentEvidence",
+          "title": "Evidence",
+          "description": "Provides the ability to document evidence collected through various forms of extraction or analysis."
+        },
+        "releaseNotes": {
+          "$ref": "#/definitions/releaseNotes",
+          "title": "Release notes",
+          "description": "Specifies optional release notes."
+        },
+         "modelCard": {
+          "$ref": "#/definitions/modelCard",
+          "title": "Machine Learning Model Card"
+        },
+        "data": {
+          "type": "array",
+          "items": {"$ref": "#/definitions/componentData"},
+          "title": "Data",
+          "description": "This object SHOULD be specified for any component of type `data` and MUST NOT be specified for other component types."
+        },
+        "properties": {
+          "type": "array",
+          "title": "Properties",
+          "description": "Provides the ability to document properties in a name-value store. This provides flexibility to include data not officially supported in the standard without having to use additional namespaces or create extensions. Unlike key-value stores, properties support duplicate names, each potentially having different values. Property names of interest to the general public are encouraged to be registered in the [CycloneDX Property Taxonomy](https://github.com/CycloneDX/cyclonedx-property-taxonomy). Formal registration is OPTIONAL.",
+          "items": {"$ref": "#/definitions/property"}
+        },
+        "signature": {
+          "$ref": "#/definitions/signature",
+          "title": "Signature",
+          "description": "Enveloped signature in [JSON Signature Format (JSF)](https://cyberphone.github.io/doc/security/jsf.html)."
+        }
+      }
+    },
+    "swid": {
+      "type": "object",
+      "title": "SWID Tag",
+      "description": "Specifies metadata and content for ISO-IEC 19770-2 Software Identification (SWID) Tags.",
+      "required": [
+        "tagId",
+        "name"
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "tagId": {
+          "type": "string",
+          "title": "Tag ID",
+          "description": "Maps to the tagId of a SoftwareIdentity."
+        },
+        "name": {
+          "type": "string",
+          "title": "Name",
+          "description": "Maps to the name of a SoftwareIdentity."
+        },
+        "version": {
+          "type": "string",
+          "title": "Version",
+          "default": "0.0",
+          "description": "Maps to the version of a SoftwareIdentity."
+        },
+        "tagVersion": {
+          "type": "integer",
+          "title": "Tag Version",
+          "default": 0,
+          "description": "Maps to the tagVersion of a SoftwareIdentity."
+        },
+        "patch": {
+          "type": "boolean",
+          "title": "Patch",
+          "default": false,
+          "description": "Maps to the patch of a SoftwareIdentity."
+        },
+        "text": {
+          "title": "Attachment text",
+          "description": "Specifies the metadata and content of the SWID tag.",
+          "$ref": "#/definitions/attachment"
+        },
+        "url": {
+          "type": "string",
+          "title": "URL",
+          "description": "The URL to the SWID file.",
+          "format": "iri-reference"
+        }
+      }
+    },
+    "attachment": {
+      "type": "object",
+      "title": "Attachment",
+      "description": "Specifies the metadata and content for an attachment.",
+      "required": [
+        "content"
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "contentType": {
+          "type": "string",
+          "title": "Content-Type",
+          "description": "Specifies the content type of the text. Defaults to text/plain if not specified.",
+          "default": "text/plain"
+        },
+        "encoding": {
+          "type": "string",
+          "title": "Encoding",
+          "description": "Specifies the optional encoding the text is represented in.",
+          "enum": [
+            "base64"
+          ]
+        },
+        "content": {
+          "type": "string",
+          "title": "Attachment Text",
+          "description": "The attachment data. Proactive controls such as input validation and sanitization should be employed to prevent misuse of attachment text."
+        }
+      }
+    },
+    "hash": {
+      "type": "object",
+      "title": "Hash Objects",
+      "required": [
+        "alg",
+        "content"
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "alg": {
+          "$ref": "#/definitions/hash-alg"
+        },
+        "content": {
+          "$ref": "#/definitions/hash-content"
+        }
+      }
+    },
+    "hash-alg": {
+      "type": "string",
+      "enum": [
+        "MD5",
+        "SHA-1",
+        "SHA-256",
+        "SHA-384",
+        "SHA-512",
+        "SHA3-256",
+        "SHA3-384",
+        "SHA3-512",
+        "BLAKE2b-256",
+        "BLAKE2b-384",
+        "BLAKE2b-512",
+        "BLAKE3"
+      ],
+      "title": "Hash Algorithm"
+    },
+    "hash-content": {
+      "type": "string",
+      "title": "Hash Content (value)",
+      "examples": ["3942447fac867ae5cdb3229b658f4d48"],
+      "pattern": "^([a-fA-F0-9]{32}|[a-fA-F0-9]{40}|[a-fA-F0-9]{64}|[a-fA-F0-9]{96}|[a-fA-F0-9]{128})$"
+    },
+    "license": {
+      "type": "object",
+      "title": "License Object",
+      "oneOf": [
+        {
+          "required": ["id"]
+        },
+        {
+          "required": ["name"]
+        }
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "bom-ref": {
+          "$ref": "#/definitions/refType",
+          "title": "BOM Reference",
+          "description": "An optional identifier which can be used to reference the license elsewhere in the BOM. Every bom-ref MUST be unique within the BOM."
+        },
+        "id": {
+          "$ref": "spdx.schema.json",
+          "title": "License ID (SPDX)",
+          "description": "A valid SPDX license ID",
+          "examples": ["Apache-2.0"]
+        },
+        "name": {
+          "type": "string",
+          "title": "License Name",
+          "description": "If SPDX does not define the license used, this field may be used to provide the license name",
+          "examples": ["Acme Software License"]
+        },
+        "text": {
+          "title": "License text",
+          "description": "An optional way to include the textual content of a license.",
+          "$ref": "#/definitions/attachment"
+        },
+        "url": {
+          "type": "string",
+          "title": "License URL",
+          "description": "The URL to the license file. If specified, a 'license' externalReference should also be specified for completeness",
+          "examples": ["https://www.apache.org/licenses/LICENSE-2.0.txt"],
+          "format": "iri-reference"
+        },
+        "licensing": {
+          "type": "object",
+          "title": "Licensing information",
+          "description": "Licensing details describing the licensor/licensee, license type, renewal and expiration dates, and other important metadata",
+          "additionalProperties": false,
+          "properties": {
+            "altIds": {
+              "type": "array",
+              "title": "Alternate License Identifiers",
+              "description": "License identifiers that may be used to manage licenses and their lifecycle",
+              "items": {
+                "type": "string"
+              }
+            },
+            "licensor": {
+              "title": "Licensor",
+              "description": "The individual or organization that grants a license to another individual or organization",
+              "type": "object",
+              "additionalProperties": false,
+              "properties": {
+                "organization": {
+                  "title": "Licensor (Organization)",
+                  "description": "The organization that granted the license",
+                  "$ref": "#/definitions/organizationalEntity"
+                },
+                "individual": {
+                  "title": "Licensor (Individual)",
+                  "description": "The individual, not associated with an organization, that granted the license",
+                  "$ref": "#/definitions/organizationalContact"
+                }
+              },
+              "oneOf":[
+                {
+                  "required": ["organization"]
+                },
+                {
+                  "required": ["individual"]
+                }
+              ]
+            },
+            "licensee": {
+              "title": "Licensee",
+              "description": "The individual or organization for which a license was granted to",
+              "type": "object",
+              "additionalProperties": false,
+              "properties": {
+                "organization": {
+                  "title": "Licensee (Organization)",
+                  "description": "The organization that was granted the license",
+                  "$ref": "#/definitions/organizationalEntity"
+                },
+                "individual": {
+                  "title": "Licensee (Individual)",
+                  "description": "The individual, not associated with an organization, that was granted the license",
+                  "$ref": "#/definitions/organizationalContact"
+                }
+              },
+              "oneOf":[
+                {
+                  "required": ["organization"]
+                },
+                {
+                  "required": ["individual"]
+                }
+              ]
+            },
+            "purchaser": {
+              "title": "Purchaser",
+              "description": "The individual or organization that purchased the license",
+              "type": "object",
+              "additionalProperties": false,
+              "properties": {
+                "organization": {
+                  "title": "Purchaser (Organization)",
+                  "description": "The organization that purchased the license",
+                  "$ref": "#/definitions/organizationalEntity"
+                },
+                "individual": {
+                  "title": "Purchaser (Individual)",
+                  "description": "The individual, not associated with an organization, that purchased the license",
+                  "$ref": "#/definitions/organizationalContact"
+                }
+              },
+              "oneOf":[
+                {
+                  "required": ["organization"]
+                },
+                {
+                  "required": ["individual"]
+                }
+              ]
+            },
+            "purchaseOrder": {
+              "type": "string",
+              "title": "Purchase Order",
+              "description": "The purchase order identifier the purchaser sent to a supplier or vendor to authorize a purchase"
+            },
+            "licenseTypes": {
+              "type": "array",
+              "title": "License Type",
+              "description": "The type of license(s) that was granted to the licensee\n\n* __academic__ = A license that grants use of software solely for the purpose of education or research.\n* __appliance__ = A license covering use of software embedded in a specific piece of hardware.\n* __client-access__ = A Client Access License (CAL) allows client computers to access services provided by server software.\n* __concurrent-user__ = A Concurrent User license (aka floating license) limits the number of licenses for a software application and licenses are shared among a larger number of users.\n* __core-points__ = A license where the core of a computer's processor is assigned a specific number of points.\n* __custom-metric__ = A license for which consumption is measured by non-standard metrics.\n* __device__ = A license that covers a defined number of installations on computers and other types of devices.\n* __evaluation__ = A license that grants permission to install and use software for trial purposes.\n* __named-user__ = A license that grants access to the software to one or more pre-defined users.\n* __node-locked__ = A license that grants access to the software on one or more pre-defined computers or devices.\n* __oem__ = An Original Equipment Manufacturer license that is delivered with hardware, cannot be transferred to other hardware, and is valid for the life of the hardware.\n* __perpetual__ = A license where the software is sold on a one-time basis and the licensee can use a copy of the software indefinitely.\n* __processor-points__ = A license where each installation consumes points per processor.\n* __subscription__ = A license where the licensee pays a fee to use the software or service.\n* __user__ = A license that grants access to the software or service by a specified number of users.\n* __other__ = Another license type.\n",
+              "items": {
+                "type": "string",
+                "enum": [
+                  "academic",
+                  "appliance",
+                  "client-access",
+                  "concurrent-user",
+                  "core-points",
+                  "custom-metric",
+                  "device",
+                  "evaluation",
+                  "named-user",
+                  "node-locked",
+                  "oem",
+                  "perpetual",
+                  "processor-points",
+                  "subscription",
+                  "user",
+                  "other"
+                ]
+              }
+            },
+            "lastRenewal": {
+              "type": "string",
+              "format": "date-time",
+              "title": "Last Renewal",
+              "description": "The timestamp indicating when the license was last renewed. For new purchases, this is often the purchase or acquisition date. For non-perpetual licenses or subscriptions, this is the timestamp of when the license was last renewed."
+            },
+            "expiration": {
+              "type": "string",
+              "format": "date-time",
+              "title": "Expiration",
+              "description": "The timestamp indicating when the current license expires (if applicable)."
+            }
+          }
+        },
+        "properties": {
+          "type": "array",
+          "title": "Properties",
+          "description": "Provides the ability to document properties in a name-value store. This provides flexibility to include data not officially supported in the standard without having to use additional namespaces or create extensions. Unlike key-value stores, properties support duplicate names, each potentially having different values. Property names of interest to the general public are encouraged to be registered in the [CycloneDX Property Taxonomy](https://github.com/CycloneDX/cyclonedx-property-taxonomy). Formal registration is OPTIONAL.",
+          "items": {"$ref": "#/definitions/property"}
+        }
+      }
+    },
+    "licenseChoice": {
+      "title": "License Choice",
+      "description": "EITHER (list of SPDX licenses and/or named licenses) OR (tuple of one SPDX License Expression)",
+      "type": "array",
+      "oneOf": [
+        {
+          "title": "Multiple licenses",
+          "description": "A list of SPDX licenses and/or named licenses.",
+          "type": "array",
+          "items": {
+            "type": "object",
+            "required": ["license"],
+            "additionalProperties": false,
+            "properties": {
+              "license": {"$ref": "#/definitions/license"}
+            }
+          }
+        },
+        {
+          "title": "SPDX License Expression",
+          "description": "A tuple of exactly one SPDX License Expression.",
+          "type": "array",
+          "additionalItems": false,
+          "minItems": 1,
+          "maxItems": 1,
+          "items": [{
+            "type": "object",
+            "additionalProperties": false,
+            "required": ["expression"],
+            "properties": {
+              "expression": {
+                "type": "string",
+                "title": "SPDX License Expression",
+                "examples": [
+                  "Apache-2.0 AND (MIT OR GPL-2.0-only)",
+                  "GPL-3.0-only WITH Classpath-exception-2.0"
+                ]
+              },
+              "bom-ref": {
+                "$ref": "#/definitions/refType",
+                "title": "BOM Reference",
+                "description": "An optional identifier which can be used to reference the license elsewhere in the BOM. Every bom-ref MUST be unique within the BOM."
+              }
+            }
+          }]
+        }
+      ]
+    },
+    "commit": {
+      "type": "object",
+      "title": "Commit",
+      "description": "Specifies an individual commit",
+      "additionalProperties": false,
+      "properties": {
+        "uid": {
+          "type": "string",
+          "title": "UID",
+          "description": "A unique identifier of the commit. This may be version control specific. For example, Subversion uses revision numbers whereas git uses commit hashes."
+        },
+        "url": {
+          "type": "string",
+          "title": "URL",
+          "description": "The URL to the commit. This URL will typically point to a commit in a version control system.",
+          "format": "iri-reference"
+        },
+        "author": {
+          "title": "Author",
+          "description": "The author who created the changes in the commit",
+          "$ref": "#/definitions/identifiableAction"
+        },
+        "committer": {
+          "title": "Committer",
+          "description": "The person who committed or pushed the commit",
+          "$ref": "#/definitions/identifiableAction"
+        },
+        "message": {
+          "type": "string",
+          "title": "Message",
+          "description": "The text description of the contents of the commit"
+        }
+      }
+    },
+    "patch": {
+      "type": "object",
+      "title": "Patch",
+      "description": "Specifies an individual patch",
+      "required": [
+        "type"
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "type": {
+          "type": "string",
+          "enum": [
+            "unofficial",
+            "monkey",
+            "backport",
+            "cherry-pick"
+          ],
+          "title": "Type",
+          "description": "Specifies the purpose for the patch including the resolution of defects, security issues, or new behavior or functionality.\n\n* __unofficial__ = A patch which is not developed by the creators or maintainers of the software being patched. Refer to [https://en.wikipedia.org/wiki/Unofficial_patch](https://en.wikipedia.org/wiki/Unofficial_patch)\n* __monkey__ = A patch which dynamically modifies runtime behavior. Refer to [https://en.wikipedia.org/wiki/Monkey_patch](https://en.wikipedia.org/wiki/Monkey_patch)\n* __backport__ = A patch which takes code from a newer version of software and applies it to older versions of the same software. Refer to [https://en.wikipedia.org/wiki/Backporting](https://en.wikipedia.org/wiki/Backporting)\n* __cherry-pick__ = A patch created by selectively applying commits from other versions or branches of the same software."
+        },
+        "diff": {
+          "title": "Diff",
+          "description": "The patch file (or diff) that show changes. Refer to [https://en.wikipedia.org/wiki/Diff](https://en.wikipedia.org/wiki/Diff)",
+          "$ref": "#/definitions/diff"
+        },
+        "resolves": {
+          "type": "array",
+          "items": {"$ref": "#/definitions/issue"},
+          "title": "Resolves",
+          "description": "A collection of issues the patch resolves"
+        }
+      }
+    },
+    "diff": {
+      "type": "object",
+      "title": "Diff",
+      "description": "The patch file (or diff) that show changes. Refer to https://en.wikipedia.org/wiki/Diff",
+      "additionalProperties": false,
+      "properties": {
+        "text": {
+          "title": "Diff text",
+          "description": "Specifies the optional text of the diff",
+          "$ref": "#/definitions/attachment"
+        },
+        "url": {
+          "type": "string",
+          "title": "URL",
+          "description": "Specifies the URL to the diff",
+          "format": "iri-reference"
+        }
+      }
+    },
+    "issue": {
+      "type": "object",
+      "title": "Diff",
+      "description": "An individual issue that has been resolved.",
+      "required": [
+        "type"
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "type": {
+          "type": "string",
+          "enum": [
+            "defect",
+            "enhancement",
+            "security"
+          ],
+          "title": "Type",
+          "description": "Specifies the type of issue"
+        },
+        "id": {
+          "type": "string",
+          "title": "ID",
+          "description": "The identifier of the issue assigned by the source of the issue"
+        },
+        "name": {
+          "type": "string",
+          "title": "Name",
+          "description": "The name of the issue"
+        },
+        "description": {
+          "type": "string",
+          "title": "Description",
+          "description": "A description of the issue"
+        },
+        "source": {
+          "type": "object",
+          "title": "Source",
+          "description": "The source of the issue where it is documented",
+          "additionalProperties": false,
+          "properties": {
+            "name": {
+              "type": "string",
+              "title": "Name",
+              "description": "The name of the source. For example 'National Vulnerability Database', 'NVD', and 'Apache'"
+            },
+            "url": {
+              "type": "string",
+              "title": "URL",
+              "description": "The url of the issue documentation as provided by the source",
+              "format": "iri-reference"
+            }
+          }
+        },
+        "references": {
+          "type": "array",
+          "items": {
+            "type": "string",
+            "format": "iri-reference"
+          },
+          "title": "References",
+          "description": "A collection of URL's for reference. Multiple URLs are allowed.",
+          "examples": ["https://example.com"]
+        }
+      }
+    },
+    "identifiableAction": {
+      "type": "object",
+      "title": "Identifiable Action",
+      "description": "Specifies an individual commit",
+      "additionalProperties": false,
+      "properties": {
+        "timestamp": {
+          "type": "string",
+          "format": "date-time",
+          "title": "Timestamp",
+          "description": "The timestamp in which the action occurred"
+        },
+        "name": {
+          "type": "string",
+          "title": "Name",
+          "description": "The name of the individual who performed the action"
+        },
+        "email": {
+          "type": "string",
+          "format": "idn-email",
+          "title": "E-mail",
+          "description": "The email address of the individual who performed the action"
+        }
+      }
+    },
+    "externalReference": {
+      "type": "object",
+      "title": "External Reference",
+      "description": "External references provide a way to document systems, sites, and information that may be relevant, but are not included with the BOM. They may also establish specific relationships within or external to the BOM.",
+      "required": [
+        "url",
+        "type"
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "url": {
+          "anyOf": [
+            {
+              "title": "URL",
+              "type": "string",
+              "format": "iri-reference"
+            },
+            {
+              "title": "BOM-Link",
+              "$ref": "#/definitions/bomLink"
+            }
+          ],
+          "title": "URL",
+          "description": "The URI (URL or URN) to the external reference. External references are URIs and therefore can accept any URL scheme including https ([RFC-7230](https://www.ietf.org/rfc/rfc7230.txt)), mailto ([RFC-2368](https://www.ietf.org/rfc/rfc2368.txt)), tel ([RFC-3966](https://www.ietf.org/rfc/rfc3966.txt)), and dns ([RFC-4501](https://www.ietf.org/rfc/rfc4501.txt)). External references may also include formally registered URNs such as [CycloneDX BOM-Link](https://cyclonedx.org/capabilities/bomlink/) to reference CycloneDX BOMs or any object within a BOM. BOM-Link transforms applicable external references into relationships that can be expressed in a BOM or across BOMs."
+        },
+        "comment": {
+          "type": "string",
+          "title": "Comment",
+          "description": "An optional comment describing the external reference"
+        },
+        "type": {
+          "type": "string",
+          "title": "Type",
+          "description": "Specifies the type of external reference.\n\n* __vcs__ = Version Control System\n* __issue-tracker__ = Issue or defect tracking system, or an Application Lifecycle Management (ALM) system\n* __website__ = Website\n* __advisories__ = Security advisories\n* __bom__ = Bill of Materials (SBOM, OBOM, HBOM, SaaSBOM, etc)\n* __mailing-list__ = Mailing list or discussion group\n* __social__ = Social media account\n* __chat__ = Real-time chat platform\n* __documentation__ = Documentation, guides, or how-to instructions\n* __support__ = Community or commercial support\n* __distribution__ = Direct or repository download location\n* __distribution-intake__ = The location where a component was published to. This is often the same as \"distribution\" but may also include specialized publishing processes that act as an intermediary\n* __license__ = The URL to the license file. If a license URL has been defined in the license node, it should also be defined as an external reference for completeness\n* __build-meta__ = Build-system specific meta file (i.e. pom.xml, package.json, .nuspec, etc)\n* __build-system__ = URL to an automated build system\n* __release-notes__ = URL to release notes\n* __security-contact__ = Specifies a way to contact the maintainer, supplier, or provider in the event of a security incident. Common URIs include links to a disclosure procedure, a mailto (RFC-2368) that specifies an email address, a tel (RFC-3966) that specifies a phone number, or dns (RFC-4501) that specifies the records containing DNS Security TXT\n* __model-card__ = A model card describes the intended uses of a machine learning model, potential limitations, biases, ethical considerations, training parameters, datasets used to train the model, performance metrics, and other relevant data useful for ML transparency\n* __log__ = A record of events that occurred in a computer system or application, such as problems, errors, or information on current operations\n* __configuration__ = Parameters or settings that may be used by other components or services\n* __evidence__ = Information used to substantiate a claim\n* __formulation__ = Describes how a component or service was manufactured or deployed\n* __attestation__ = Human or machine-readable statements containing facts, evidence, or testimony\n* __threat-model__ = An enumeration of identified weaknesses, threats, and countermeasures, dataflow diagram (DFD), attack tree, and other supporting documentation in human-readable or machine-readable format\n* __adversary-model__ = The defined assumptions, goals, and capabilities of an adversary.\n* __risk-assessment__ = Identifies and analyzes the potential of future events that may negatively impact individuals, assets, and/or the environment. Risk assessments may also include judgments on the tolerability of each risk.\n* __vulnerability-assertion__ = A Vulnerability Disclosure Report (VDR) which asserts the known and previously unknown vulnerabilities that affect a component, service, or product including the analysis and findings describing the impact (or lack of impact) that the reported vulnerability has on a component, service, or product.\n* __exploitability-statement__ = A Vulnerability Exploitability eXchange (VEX) which asserts the known vulnerabilities that do not affect a product, product family, or organization, and optionally the ones that do. The VEX should include the analysis and findings describing the impact (or lack of impact) that the reported vulnerability has on the product, product family, or organization.\n* __pentest-report__ = Results from an authorized simulated cyberattack on a component or service, otherwise known as a penetration test\n* __static-analysis-report__ = SARIF or proprietary machine or human-readable report for which static analysis has identified code quality, security, and other potential issues with the source code\n* __dynamic-analysis-report__ = Dynamic analysis report that has identified issues such as vulnerabilities and misconfigurations\n* __runtime-analysis-report__ = Report generated by analyzing the call stack of a running application\n* __component-analysis-report__ = Report generated by Software Composition Analysis (SCA), container analysis, or other forms of component analysis\n* __maturity-report__ = Report containing a formal assessment of an organization, business unit, or team against a maturity model\n* __certification-report__ = Industry, regulatory, or other certification from an accredited (if applicable) certification body\n* __quality-metrics__ = Report or system in which quality metrics can be obtained\n* __codified-infrastructure__ = Code or configuration that defines and provisions virtualized infrastructure, commonly referred to as Infrastructure as Code (IaC)\n* __poam__ = Plans of Action and Milestones (POAM) compliment an \"attestation\" external reference. POAM is defined by NIST as a \"document that identifies tasks needing to be accomplished. It details resources required to accomplish the elements of the plan, any milestones in meeting the tasks and scheduled completion dates for the milestones\".\n* __other__ = Use this if no other types accurately describe the purpose of the external reference",
+          "enum": [
+            "vcs",
+            "issue-tracker",
+            "website",
+            "advisories",
+            "bom",
+            "mailing-list",
+            "social",
+            "chat",
+            "documentation",
+            "support",
+            "distribution",
+            "distribution-intake",
+            "license",
+            "build-meta",
+            "build-system",
+            "release-notes",
+            "security-contact",
+            "model-card",
+            "log",
+            "configuration",
+            "evidence",
+            "formulation",
+            "attestation",
+            "threat-model",
+            "adversary-model",
+            "risk-assessment",
+            "vulnerability-assertion",
+            "exploitability-statement",
+            "pentest-report",
+            "static-analysis-report",
+            "dynamic-analysis-report",
+            "runtime-analysis-report",
+            "component-analysis-report",
+            "maturity-report",
+            "certification-report",
+            "codified-infrastructure",
+            "quality-metrics",
+            "poam",
+            "other"
+          ]
+        },
+        "hashes": {
+          "type": "array",
+          "items": {"$ref": "#/definitions/hash"},
+          "title": "Hashes",
+          "description": "The hashes of the external reference (if applicable)."
+        }
+      }
+    },
+    "dependency": {
+      "type": "object",
+      "title": "Dependency",
+      "description": "Defines the direct dependencies of a component or service. Components or services that do not have their own dependencies MUST be declared as empty elements within the graph. Components or services that are not represented in the dependency graph MAY have unknown dependencies. It is RECOMMENDED that implementations assume this to be opaque and not an indicator of a object being dependency-free. It is RECOMMENDED to leverage compositions to indicate unknown dependency graphs.",
+      "required": [
+        "ref"
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "ref": {
+          "$ref": "#/definitions/refLinkType",
+          "title": "Reference",
+          "description": "References a component or service by its bom-ref attribute"
+        },
+        "dependsOn": {
+          "type": "array",
+          "uniqueItems": true,
+          "items": {
+            "$ref": "#/definitions/refLinkType"
+          },
+          "title": "Depends On",
+          "description": "The bom-ref identifiers of the components or services that are dependencies of this dependency object."
+        }
+      }
+    },
+    "service": {
+      "type": "object",
+      "title": "Service Object",
+      "required": [
+        "name"
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "bom-ref": {
+          "$ref": "#/definitions/refType",
+          "title": "BOM Reference",
+          "description": "An optional identifier which can be used to reference the service elsewhere in the BOM. Every bom-ref MUST be unique within the BOM."
+        },
+        "provider": {
+          "title": "Provider",
+          "description": "The organization that provides the service.",
+          "$ref": "#/definitions/organizationalEntity"
+        },
+        "group": {
+          "type": "string",
+          "title": "Service Group",
+          "description": "The grouping name, namespace, or identifier. This will often be a shortened, single name of the company or project that produced the service or domain name. Whitespace and special characters should be avoided.",
+          "examples": ["com.acme"]
+        },
+        "name": {
+          "type": "string",
+          "title": "Service Name",
+          "description": "The name of the service. This will often be a shortened, single name of the service.",
+          "examples": ["ticker-service"]
+        },
+        "version": {
+          "type": "string",
+          "title": "Service Version",
+          "description": "The service version.",
+          "examples": ["1.0.0"]
+        },
+        "description": {
+          "type": "string",
+          "title": "Service Description",
+          "description": "Specifies a description for the service"
+        },
+        "endpoints": {
+          "type": "array",
+          "items": {
+            "type": "string",
+            "format": "iri-reference"
+          },
+          "title": "Endpoints",
+          "description": "The endpoint URIs of the service. Multiple endpoints are allowed.",
+          "examples": ["https://example.com/api/v1/ticker"]
+        },
+        "authenticated": {
+          "type": "boolean",
+          "title": "Authentication Required",
+          "description": "A boolean value indicating if the service requires authentication. A value of true indicates the service requires authentication prior to use. A value of false indicates the service does not require authentication."
+        },
+        "x-trust-boundary": {
+          "type": "boolean",
+          "title": "Crosses Trust Boundary",
+          "description": "A boolean value indicating if use of the service crosses a trust zone or boundary. A value of true indicates that by using the service, a trust boundary is crossed. A value of false indicates that by using the service, a trust boundary is not crossed."
+        },
+        "trustZone": {
+          "type": "string",
+          "title": "Trust Zone",
+          "description": "The name of the trust zone the service resides in."
+        },
+        "data": {
+          "type": "array",
+          "items": {"$ref": "#/definitions/serviceData"},
+          "title": "Data",
+          "description": "Specifies information about the data including the directional flow of data and the data classification."
+        },
+        "licenses": {
+          "$ref": "#/definitions/licenseChoice",
+          "title": "Component License(s)"
+        },
+        "externalReferences": {
+          "type": "array",
+          "items": {"$ref": "#/definitions/externalReference"},
+          "title": "External References",
+          "description": "External references provide a way to document systems, sites, and information that may be relevant, but are not included with the BOM. They may also establish specific relationships within or external to the BOM."
+        },
+        "services": {
+          "type": "array",
+          "items": {"$ref": "#/definitions/service"},
+          "uniqueItems": true,
+          "title": "Services",
+          "description": "A list of services included or deployed behind the parent service. This is not a dependency tree. It provides a way to specify a hierarchical representation of service assemblies."
+        },
+        "releaseNotes": {
+          "$ref": "#/definitions/releaseNotes",
+          "title": "Release notes",
+          "description": "Specifies optional release notes."
+        },
+        "properties": {
+          "type": "array",
+          "title": "Properties",
+          "description": "Provides the ability to document properties in a name-value store. This provides flexibility to include data not officially supported in the standard without having to use additional namespaces or create extensions. Unlike key-value stores, properties support duplicate names, each potentially having different values. Property names of interest to the general public are encouraged to be registered in the [CycloneDX Property Taxonomy](https://github.com/CycloneDX/cyclonedx-property-taxonomy). Formal registration is OPTIONAL.",
+          "items": {"$ref": "#/definitions/property"}
+        },
+        "signature": {
+          "$ref": "#/definitions/signature",
+          "title": "Signature",
+          "description": "Enveloped signature in [JSON Signature Format (JSF)](https://cyberphone.github.io/doc/security/jsf.html)."
+        }
+      }
+    },
+    "serviceData": {
+      "type": "object",
+      "title": "Hash Objects",
+      "required": [
+        "flow",
+        "classification"
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "flow": {
+          "$ref": "#/definitions/dataFlowDirection",
+          "title": "Directional Flow",
+          "description": "Specifies the flow direction of the data. Direction is relative to the service. Inbound flow states that data enters the service. Outbound flow states that data leaves the service. Bi-directional states that data flows both ways, and unknown states that the direction is not known."
+        },
+        "classification": {
+          "$ref": "#/definitions/dataClassification"
+        },
+        "name": {
+          "type": "string",
+          "title": "Name",
+          "description": "Name for the defined data",
+          "examples": [
+            "Credit card reporting"
+          ]
+        },
+        "description": {
+          "type": "string",
+          "title": "Description",
+          "description": "Short description of the data content and usage",
+          "examples": [
+            "Credit card information being exchanged in between the web app and the database"
+          ]
+        },
+        "governance": {
+          "type": "object",
+          "title": "Data Governance",
+          "$ref": "#/definitions/dataGovernance"
+        },
+        "source": {
+          "type": "array",
+          "items": {
+            "anyOf": [
+              {
+                "title": "URL",
+                "type": "string",
+                "format": "iri-reference"
+              },
+              {
+                "title": "BOM-Link Element",
+                "$ref": "#/definitions/bomLinkElementType"
+              }
+            ]
+          },
+          "title": "Source",
+          "description": "The URI, URL, or BOM-Link of the components or services the data came in from"
+        },
+        "destination": {
+          "type": "array",
+          "items": {
+            "anyOf": [
+              {
+                "title": "URL",
+                "type": "string",
+                "format": "iri-reference"
+              },
+              {
+                "title": "BOM-Link Element",
+                "$ref": "#/definitions/bomLinkElementType"
+              }
+            ]
+          },
+          "title": "Destination",
+          "description": "The URI, URL, or BOM-Link of the components or services the data is sent to"
+        }
+      }
+    },
+    "dataFlowDirection": {
+      "type": "string",
+      "enum": [
+        "inbound",
+        "outbound",
+        "bi-directional",
+        "unknown"
+      ],
+      "title": "Data flow direction",
+      "description": "Specifies the flow direction of the data. Direction is relative to the service. Inbound flow states that data enters the service. Outbound flow states that data leaves the service. Bi-directional states that data flows both ways, and unknown states that the direction is not known."
+    },
+
+    "copyright": {
+      "type": "object",
+      "title": "Copyright",
+      "required": [
+        "text"
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "text": {
+          "type": "string",
+          "title": "Copyright Text"
+        }
+      }
+    },
+    "componentEvidence": {
+      "type": "object",
+      "title": "Evidence",
+      "description": "Provides the ability to document evidence collected through various forms of extraction or analysis.",
+      "additionalProperties": false,
+      "properties": {
+        "identity": {
+          "type": "object",
+          "description": "Evidence that substantiates the identity of a component.",
+          "required": [ "field" ],
+          "additionalProperties": false,
+          "properties": {
+            "field": {
+              "type": "string",
+              "enum": [
+                "group", "name", "version", "purl", "cpe", "swid", "hash"
+              ],
+              "title": "Field",
+              "description": "The identity field of the component which the evidence describes."
+            },
+            "confidence": {
+              "type": "number",
+              "minimum": 0,
+              "maximum": 1,
+              "title": "Confidence",
+              "description": "The overall confidence of the evidence from 0 - 1, where 1 is 100% confidence."
+            },
+            "methods": {
+              "type": "array",
+              "title": "Methods",
+              "description": "The methods used to extract and/or analyze the evidence.",
+              "items": {
+                "type": "object",
+                "required": [
+                  "technique" ,
+                  "confidence"
+                ],
+                "additionalProperties": false,
+                "properties": {
+                  "technique": {
+                    "title": "Technique",
+                    "description": "The technique used in this method of analysis.",
+                    "type": "string",
+                    "enum": [
+                      "source-code-analysis",
+                      "binary-analysis",
+                      "manifest-analysis",
+                      "ast-fingerprint",
+                      "hash-comparison",
+                      "instrumentation",
+                      "dynamic-analysis",
+                      "filename",
+                      "attestation",
+                      "other"
+                    ]
+                  },
+                  "confidence": {
+                    "type": "number",
+                    "minimum": 0,
+                    "maximum": 1,
+                    "title": "Confidence",
+                    "description": "The confidence of the evidence from 0 - 1, where 1 is 100% confidence. Confidence is specific to the technique used. Each technique of analysis can have independent confidence."
+                  },
+                  "value": {
+                    "type": "string",
+                    "title": "Value",
+                    "description": "The value or contents of the evidence."
+                  }
+                }
+              }
+            },
+            "tools": {
+              "type": "array",
+              "uniqueItems": true,
+              "items": {
+                "anyOf": [
+                  {
+                    "title": "Ref",
+                    "$ref": "#/definitions/refLinkType"
+                  },
+                  {
+                    "title": "BOM-Link Element",
+                    "$ref": "#/definitions/bomLinkElementType"
+                  }
+                ]
+              },
+              "title": "BOM References",
+              "description": "The object in the BOM identified by its bom-ref. This is often a component or service, but may be any object type supporting bom-refs. Tools used for analysis should already be defined in the BOM, either in the metadata/tools, components, or formulation."
+            }
+          }
+        },
+        "occurrences": {
+          "type": "array",
+          "title": "Occurrences",
+          "description": "Evidence of individual instances of a component spread across multiple locations.",
+          "items": {
+            "type": "object",
+            "required": [ "location" ],
+            "additionalProperties": false,
+            "properties": {
+              "bom-ref": {
+                "$ref": "#/definitions/refType",
+                "title": "BOM Reference",
+                "description": "An optional identifier which can be used to reference the occurrence elsewhere in the BOM. Every bom-ref MUST be unique within the BOM."
+              },
+              "location": {
+                "type": "string",
+                "title": "Location",
+                "description": "The location or path to where the component was found."
+              }
+            }
+          }
+        },
+        "callstack": {
+          "type": "object",
+          "description": "Evidence of the components use through the callstack.",
+          "additionalProperties": false,
+          "properties": {
+            "frames": {
+              "type": "array",
+              "title": "Methods",
+              "items": {
+                "type": "object",
+                "required": [
+                  "module"
+                ],
+                "additionalProperties": false,
+                "properties": {
+                  "package": {
+                    "title": "Package",
+                    "description": "A package organizes modules into namespaces, providing a unique namespace for each type it contains.",
+                    "type": "string"
+                  },
+                  "module": {
+                    "title": "Module",
+                    "description": "A module or class that encloses functions/methods and other code.",
+                    "type": "string"
+                  },
+                  "function": {
+                    "title": "Function",
+                    "description": "A block of code designed to perform a particular task.",
+                    "type": "string"
+                  },
+                  "parameters": {
+                    "title": "Parameters",
+                    "description": "Optional arguments that are passed to the module or function.",
+                    "type": "array",
+                    "items": {
+                      "type": "string"
+                    }
+                  },
+                  "line": {
+                    "title": "Line",
+                    "description": "The line number the code that is called resides on.",
+                    "type": "integer"
+                  },
+                  "column": {
+                    "title": "Column",
+                    "description": "The column the code that is called resides.",
+                    "type": "integer"
+                  },
+                  "fullFilename": {
+                    "title": "Full Filename",
+                    "description": "The full path and filename of the module.",
+                    "type": "string"
+                  }
+                }
+              }
+            }
+          }
+        },
+        "licenses": {
+          "$ref": "#/definitions/licenseChoice",
+          "title": "Component License(s)"
+        },
+        "copyright": {
+          "type": "array",
+          "items": {"$ref": "#/definitions/copyright"},
+          "title": "Copyright"
+        }
+      }
+    },
+    "compositions": {
+      "type": "object",
+      "title": "Compositions",
+      "required": [
+        "aggregate"
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "bom-ref": {
+          "$ref": "#/definitions/refType",
+          "title": "BOM Reference",
+          "description": "An optional identifier which can be used to reference the composition elsewhere in the BOM. Every bom-ref MUST be unique within the BOM."
+        },
+        "aggregate": {
+          "$ref": "#/definitions/aggregateType",
+          "title": "Aggregate",
+          "description": "Specifies an aggregate type that describe how complete a relationship is.\n\n* __complete__ = The relationship is complete. No further relationships including constituent components, services, or dependencies are known to exist.\n* __incomplete__ = The relationship is incomplete. Additional relationships exist and may include constituent components, services, or dependencies.\n* __incomplete_first_party_only__ = The relationship is incomplete. Only relationships for first-party components, services, or their dependencies are represented.\n* __incomplete_first_party_proprietary_only__ = The relationship is incomplete. Only relationships for first-party components, services, or their dependencies are represented, limited specifically to those that are proprietary.\n* __incomplete_first_party_opensource_only__ = The relationship is incomplete. Only relationships for first-party components, services, or their dependencies are represented, limited specifically to those that are opensource.\n* __incomplete_third_party_only__ = The relationship is incomplete. Only relationships for third-party components, services, or their dependencies are represented.\n* __incomplete_third_party_proprietary_only__ = The relationship is incomplete. Only relationships for third-party components, services, or their dependencies are represented, limited specifically to those that are proprietary.\n* __incomplete_third_party_opensource_only__ = The relationship is incomplete. Only relationships for third-party components, services, or their dependencies are represented, limited specifically to those that are opensource.\n* __unknown__ = The relationship may be complete or incomplete. This usually signifies a 'best-effort' to obtain constituent components, services, or dependencies but the completeness is inconclusive.\n* __not_specified__ = The relationship completeness is not specified.\n"
+        },
+        "assemblies": {
+          "type": "array",
+          "uniqueItems": true,
+          "items": {
+            "anyOf": [
+              {
+                "title": "Ref",
+                "$ref": "#/definitions/refLinkType"
+              },
+              {
+                "title": "BOM-Link Element",
+                "$ref": "#/definitions/bomLinkElementType"
+              }
+            ]
+          },
+          "title": "BOM references",
+          "description": "The bom-ref identifiers of the components or services being described. Assemblies refer to nested relationships whereby a constituent part may include other constituent parts. References do not cascade to child parts. References are explicit for the specified constituent part only."
+        },
+        "dependencies": {
+          "type": "array",
+          "uniqueItems": true,
+          "items": {
+            "type": "string"
+          },
+          "title": "BOM references",
+          "description": "The bom-ref identifiers of the components or services being described. Dependencies refer to a relationship whereby an independent constituent part requires another independent constituent part. References do not cascade to transitive dependencies. References are explicit for the specified dependency only."
+        },
+        "vulnerabilities": {
+          "type": "array",
+          "uniqueItems": true,
+          "items": {
+            "type": "string"
+          },
+          "title": "BOM references",
+          "description": "The bom-ref identifiers of the vulnerabilities being described."
+        },
+        "signature": {
+          "$ref": "#/definitions/signature",
+          "title": "Signature",
+          "description": "Enveloped signature in [JSON Signature Format (JSF)](https://cyberphone.github.io/doc/security/jsf.html)."
+        }
+      }
+    },
+    "aggregateType": {
+      "type": "string",
+      "default": "not_specified",
+      "enum": [
+        "complete",
+        "incomplete",
+        "incomplete_first_party_only",
+        "incomplete_first_party_proprietary_only",
+        "incomplete_first_party_opensource_only",
+        "incomplete_third_party_only",
+        "incomplete_third_party_proprietary_only",
+        "incomplete_third_party_opensource_only",
+        "unknown",
+        "not_specified"
+      ]
+    },
+    "property": {
+      "type": "object",
+      "title": "Lightweight name-value pair",
+      "description": "Provides the ability to document properties in a name-value store. This provides flexibility to include data not officially supported in the standard without having to use additional namespaces or create extensions. Unlike key-value stores, properties support duplicate names, each potentially having different values. Property names of interest to the general public are encouraged to be registered in the [CycloneDX Property Taxonomy](https://github.com/CycloneDX/cyclonedx-property-taxonomy). Formal registration is OPTIONAL.",
+      "properties": {
+        "name": {
+          "type": "string",
+          "title": "Name",
+          "description": "The name of the property. Duplicate names are allowed, each potentially having a different value."
+        },
+        "value": {
+          "type": "string",
+          "title": "Value",
+          "description": "The value of the property."
+        }
+      }
+    },
+    "localeType": {
+      "type": "string",
+      "pattern": "^([a-z]{2})(-[A-Z]{2})?$",
+      "title": "Locale",
+      "description": "Defines a syntax for representing two character language code (ISO-639) followed by an optional two character country code. The language code MUST be lower case. If the country code is specified, the country code MUST be upper case. The language code and country code MUST be separated by a minus sign. Examples: en, en-US, fr, fr-CA"
+    },
+    "releaseType": {
+      "type": "string",
+      "examples": [
+        "major",
+        "minor",
+        "patch",
+        "pre-release",
+        "internal"
+      ],
+      "description": "The software versioning type. It is RECOMMENDED that the release type use one of 'major', 'minor', 'patch', 'pre-release', or 'internal'. Representing all possible software release types is not practical, so standardizing on the recommended values, whenever possible, is strongly encouraged.\n\n* __major__ = A major release may contain significant changes or may introduce breaking changes.\n* __minor__ = A minor release, also known as an update, may contain a smaller number of changes than major releases.\n* __patch__ = Patch releases are typically unplanned and may resolve defects or important security issues.\n* __pre-release__ = A pre-release may include alpha, beta, or release candidates and typically have limited support. They provide the ability to preview a release prior to its general availability.\n* __internal__ = Internal releases are not for public consumption and are intended to be used exclusively by the project or manufacturer that produced it."
+    },
+    "note": {
+      "type": "object",
+      "title": "Note",
+      "description": "A note containing the locale and content.",
+      "required": [
+        "text"
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "locale": {
+          "$ref": "#/definitions/localeType",
+          "title": "Locale",
+          "description": "The ISO-639 (or higher) language code and optional ISO-3166 (or higher) country code. Examples include: \"en\", \"en-US\", \"fr\" and \"fr-CA\""
+        },
+        "text": {
+          "title": "Release note content",
+          "description": "Specifies the full content of the release note.",
+          "$ref": "#/definitions/attachment"
+        }
+      }
+    },
+    "releaseNotes": {
+      "type": "object",
+      "title": "Release notes",
+      "required": [
+        "type"
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "type": {
+          "$ref": "#/definitions/releaseType",
+          "title": "Type",
+          "description": "The software versioning type the release note describes."
+        },
+        "title": {
+          "type": "string",
+          "title": "Title",
+          "description": "The title of the release."
+        },
+        "featuredImage": {
+          "type": "string",
+          "format": "iri-reference",
+          "title": "Featured image",
+          "description": "The URL to an image that may be prominently displayed with the release note."
+        },
+        "socialImage": {
+          "type": "string",
+          "format": "iri-reference",
+          "title": "Social image",
+          "description": "The URL to an image that may be used in messaging on social media platforms."
+        },
+        "description": {
+          "type": "string",
+          "title": "Description",
+          "description": "A short description of the release."
+        },
+        "timestamp": {
+          "type": "string",
+          "format": "date-time",
+          "title": "Timestamp",
+          "description": "The date and time (timestamp) when the release note was created."
+        },
+        "aliases": {
+          "type": "array",
+          "items": {
+            "type": "string"
+          },
+          "title": "Aliases",
+          "description": "One or more alternate names the release may be referred to. This may include unofficial terms used by development and marketing teams (e.g. code names)."
+        },
+        "tags": {
+          "type": "array",
+          "items": {
+            "type": "string"
+          },
+          "title": "Tags",
+          "description": "One or more tags that may aid in search or retrieval of the release note."
+        },
+        "resolves": {
+          "type": "array",
+          "items": {"$ref": "#/definitions/issue"},
+          "title": "Resolves",
+          "description": "A collection of issues that have been resolved."
+        },
+        "notes": {
+          "type": "array",
+          "items": {"$ref": "#/definitions/note"},
+          "title": "Notes",
+          "description": "Zero or more release notes containing the locale and content. Multiple note objects may be specified to support release notes in a wide variety of languages."
+        },
+        "properties": {
+          "type": "array",
+          "title": "Properties",
+          "description": "Provides the ability to document properties in a name-value store. This provides flexibility to include data not officially supported in the standard without having to use additional namespaces or create extensions. Unlike key-value stores, properties support duplicate names, each potentially having different values. Property names of interest to the general public are encouraged to be registered in the [CycloneDX Property Taxonomy](https://github.com/CycloneDX/cyclonedx-property-taxonomy). Formal registration is OPTIONAL.",
+          "items": {"$ref": "#/definitions/property"}
+        }
+      }
+    },
+    "advisory": {
+      "type": "object",
+      "title": "Advisory",
+      "description": "Title and location where advisory information can be obtained. An advisory is a notification of a threat to a component, service, or system.",
+      "required": ["url"],
+      "additionalProperties": false,
+      "properties": {
+        "title": {
+          "type": "string",
+          "title": "Title",
+          "description": "An optional name of the advisory."
+        },
+        "url": {
+          "type": "string",
+          "title": "URL",
+          "format": "iri-reference",
+          "description": "Location where the advisory can be obtained."
+        }
+      }
+    },
+    "cwe": {
+      "type": "integer",
+      "minimum": 1,
+      "title": "CWE",
+      "description": "Integer representation of a Common Weaknesses Enumerations (CWE). For example 399 (of https://cwe.mitre.org/data/definitions/399.html)"
+    },
+    "severity": {
+      "type": "string",
+      "title": "Severity",
+      "description": "Textual representation of the severity of the vulnerability adopted by the analysis method. If the analysis method uses values other than what is provided, the user is expected to translate appropriately.",
+      "enum": [
+        "critical",
+        "high",
+        "medium",
+        "low",
+        "info",
+        "none",
+        "unknown"
+      ]
+    },
+    "scoreMethod": {
+      "type": "string",
+      "title": "Method",
+      "description": "Specifies the severity or risk scoring methodology or standard used.\n\n* CVSSv2 - [Common Vulnerability Scoring System v2](https://www.first.org/cvss/v2/)\n* CVSSv3 - [Common Vulnerability Scoring System v3](https://www.first.org/cvss/v3-0/)\n* CVSSv31 - [Common Vulnerability Scoring System v3.1](https://www.first.org/cvss/v3-1/)\n* CVSSv4 - [Common Vulnerability Scoring System v4](https://www.first.org/cvss/v4-0/)\n* OWASP - [OWASP Risk Rating Methodology](https://owasp.org/www-community/OWASP_Risk_Rating_Methodology)\n* SSVC - [Stakeholder Specific Vulnerability Categorization](https://github.com/CERTCC/SSVC) (all versions)",
+      "enum": [
+        "CVSSv2",
+        "CVSSv3",
+        "CVSSv31",
+        "CVSSv4",
+        "OWASP",
+        "SSVC",
+        "other"
+      ]
+    },
+    "impactAnalysisState": {
+      "type": "string",
+      "title": "Impact Analysis State",
+      "description": "Declares the current state of an occurrence of a vulnerability, after automated or manual analysis. \n\n* __resolved__ = the vulnerability has been remediated. \n* __resolved\\_with\\_pedigree__ = the vulnerability has been remediated and evidence of the changes are provided in the affected components pedigree containing verifiable commit history and/or diff(s). \n* __exploitable__ = the vulnerability may be directly or indirectly exploitable. \n* __in\\_triage__ = the vulnerability is being investigated. \n* __false\\_positive__ = the vulnerability is not specific to the component or service and was falsely identified or associated. \n* __not\\_affected__ = the component or service is not affected by the vulnerability. Justification should be specified for all not_affected cases.",
+      "enum": [
+        "resolved",
+        "resolved_with_pedigree",
+        "exploitable",
+        "in_triage",
+        "false_positive",
+        "not_affected"
+      ]
+    },
+    "impactAnalysisJustification": {
+      "type": "string",
+      "title": "Impact Analysis Justification",
+      "description": "The rationale of why the impact analysis state was asserted. \n\n* __code\\_not\\_present__ = the code has been removed or tree-shaked. \n* __code\\_not\\_reachable__ = the vulnerable code is not invoked at runtime. \n* __requires\\_configuration__ = exploitability requires a configurable option to be set/unset. \n* __requires\\_dependency__ = exploitability requires a dependency that is not present. \n* __requires\\_environment__ = exploitability requires a certain environment which is not present. \n* __protected\\_by\\_compiler__ = exploitability requires a compiler flag to be set/unset. \n* __protected\\_at\\_runtime__ = exploits are prevented at runtime. \n* __protected\\_at\\_perimeter__ = attacks are blocked at physical, logical, or network perimeter. \n* __protected\\_by\\_mitigating\\_control__ = preventative measures have been implemented that reduce the likelihood and/or impact of the vulnerability.",
+      "enum": [
+        "code_not_present",
+        "code_not_reachable",
+        "requires_configuration",
+        "requires_dependency",
+        "requires_environment",
+        "protected_by_compiler",
+        "protected_at_runtime",
+        "protected_at_perimeter",
+        "protected_by_mitigating_control"
+      ]
+    },
+    "rating": {
+      "type": "object",
+      "title": "Rating",
+      "description": "Defines the severity or risk ratings of a vulnerability.",
+      "additionalProperties": false,
+      "properties": {
+        "source": {
+          "$ref": "#/definitions/vulnerabilitySource",
+          "description": "The source that calculated the severity or risk rating of the vulnerability."
+        },
+        "score": {
+          "type": "number",
+          "title": "Score",
+          "description": "The numerical score of the rating."
+        },
+        "severity": {
+          "$ref": "#/definitions/severity",
+          "description": "Textual representation of the severity that corresponds to the numerical score of the rating."
+        },
+        "method": {
+          "$ref": "#/definitions/scoreMethod"
+        },
+        "vector": {
+          "type": "string",
+          "title": "Vector",
+          "description": "Textual representation of the metric values used to score the vulnerability"
+        },
+        "justification": {
+          "type": "string",
+          "title": "Justification",
+          "description": "An optional reason for rating the vulnerability as it was"
+        }
+      }
+    },
+    "vulnerabilitySource": {
+      "type": "object",
+      "title": "Source",
+      "description": "The source of vulnerability information. This is often the organization that published the vulnerability.",
+      "additionalProperties": false,
+      "properties": {
+        "url": {
+          "type": "string",
+          "title": "URL",
+          "description": "The url of the vulnerability documentation as provided by the source.",
+          "examples": [
+            "https://nvd.nist.gov/vuln/detail/CVE-2021-39182"
+          ]
+        },
+        "name": {
+          "type": "string",
+          "title": "Name",
+          "description": "The name of the source.",
+          "examples": [
+            "NVD",
+            "National Vulnerability Database",
+            "OSS Index",
+            "VulnDB",
+            "GitHub Advisories"
+          ]
+        }
+      }
+    },
+    "vulnerability": {
+      "type": "object",
+      "title": "Vulnerability",
+      "description": "Defines a weakness in a component or service that could be exploited or triggered by a threat source.",
+      "additionalProperties": false,
+      "properties": {
+        "bom-ref": {
+          "$ref": "#/definitions/refType",
+          "title": "BOM Reference",
+          "description": "An optional identifier which can be used to reference the vulnerability elsewhere in the BOM. Every bom-ref MUST be unique within the BOM."
+        },
+        "id": {
+          "type": "string",
+          "title": "ID",
+          "description": "The identifier that uniquely identifies the vulnerability.",
+          "examples": [
+            "CVE-2021-39182",
+            "GHSA-35m5-8cvj-8783",
+            "SNYK-PYTHON-ENROCRYPT-1912876"
+          ]
+        },
+        "source": {
+          "$ref": "#/definitions/vulnerabilitySource",
+          "description": "The source that published the vulnerability."
+        },
+        "references": {
+          "type": "array",
+          "title": "References",
+          "description": "Zero or more pointers to vulnerabilities that are the equivalent of the vulnerability specified. Often times, the same vulnerability may exist in multiple sources of vulnerability intelligence, but have different identifiers. References provide a way to correlate vulnerabilities across multiple sources of vulnerability intelligence.",
+          "items": {
+            "type": "object",
+            "required": [
+              "id",
+              "source"
+            ],
+            "additionalProperties": false,
+            "properties": {
+              "id": {
+                "type": "string",
+                "title": "ID",
+                "description": "An identifier that uniquely identifies the vulnerability.",
+                "examples": [
+                  "CVE-2021-39182",
+                  "GHSA-35m5-8cvj-8783",
+                  "SNYK-PYTHON-ENROCRYPT-1912876"
+                ]
+              },
+              "source": {
+                "$ref": "#/definitions/vulnerabilitySource",
+                "description": "The source that published the vulnerability."
+              }
+            }
+          }
+        },
+        "ratings": {
+          "type": "array",
+          "title": "Ratings",
+          "description": "List of vulnerability ratings",
+          "items": {
+            "$ref": "#/definitions/rating"
+          }
+        },
+        "cwes": {
+          "type": "array",
+          "title": "CWEs",
+          "description": "List of Common Weaknesses Enumerations (CWEs) codes that describes this vulnerability. For example 399 (of https://cwe.mitre.org/data/definitions/399.html)",
+          "examples": [399],
+          "items": {
+            "$ref": "#/definitions/cwe"
+          }
+        },
+        "description": {
+          "type": "string",
+          "title": "Description",
+          "description": "A description of the vulnerability as provided by the source."
+        },
+        "detail": {
+          "type": "string",
+          "title": "Details",
+          "description": "If available, an in-depth description of the vulnerability as provided by the source organization. Details often include information useful in understanding root cause."
+        },
+        "recommendation": {
+          "type": "string",
+          "title": "Recommendation",
+          "description": "Recommendations of how the vulnerability can be remediated or mitigated."
+        },
+        "workaround": {
+          "type": "string",
+          "title": "Workarounds",
+          "description": "A bypass, usually temporary, of the vulnerability that reduces its likelihood and/or impact. Workarounds often involve changes to configuration or deployments."
+        },
+        "proofOfConcept": {
+          "type": "object",
+          "title": "Proof of Concept",
+          "description": "Evidence used to reproduce the vulnerability.",
+          "properties": {
+            "reproductionSteps": {
+              "type": "string",
+              "title": "Steps to Reproduce",
+              "description": "Precise steps to reproduce the vulnerability."
+            },
+            "environment": {
+              "type": "string",
+              "title": "Environment",
+              "description": "A description of the environment in which reproduction was possible."
+            },
+            "supportingMaterial": {
+              "type": "array",
+              "title": "Supporting Material",
+              "description": "Supporting material that helps in reproducing or understanding how reproduction is possible. This may include screenshots, payloads, and PoC exploit code.",
+              "items": { "$ref": "#/definitions/attachment" }
+            }
+          }
+        },
+        "advisories": {
+          "type": "array",
+          "title": "Advisories",
+          "description": "Published advisories of the vulnerability if provided.",
+          "items": {
+            "$ref": "#/definitions/advisory"
+          }
+        },
+        "created": {
+          "type": "string",
+          "format": "date-time",
+          "title": "Created",
+          "description": "The date and time (timestamp) when the vulnerability record was created in the vulnerability database."
+        },
+        "published": {
+          "type": "string",
+          "format": "date-time",
+          "title": "Published",
+          "description": "The date and time (timestamp) when the vulnerability record was first published."
+        },
+        "updated": {
+          "type": "string",
+          "format": "date-time",
+          "title": "Updated",
+          "description": "The date and time (timestamp) when the vulnerability record was last updated."
+        },
+        "rejected": {
+          "type": "string",
+          "format": "date-time",
+          "title": "Rejected",
+          "description": "The date and time (timestamp) when the vulnerability record was rejected (if applicable)."
+        },
+        "credits": {
+          "type": "object",
+          "title": "Credits",
+          "description": "Individuals or organizations credited with the discovery of the vulnerability.",
+          "additionalProperties": false,
+          "properties": {
+            "organizations": {
+              "type": "array",
+              "title": "Organizations",
+              "description": "The organizations credited with vulnerability discovery.",
+              "items": {
+                "$ref": "#/definitions/organizationalEntity"
+              }
+            },
+            "individuals": {
+              "type": "array",
+              "title": "Individuals",
+              "description": "The individuals, not associated with organizations, that are credited with vulnerability discovery.",
+              "items": {
+                "$ref": "#/definitions/organizationalContact"
+              }
+            }
+          }
+        },
+        "tools": {
+          "oneOf": [
+            {
+              "type": "object",
+              "title": "Tools",
+              "description": "The tool(s) used to identify, confirm, or score the vulnerability.",
+              "additionalProperties": false,
+              "properties": {
+                "components": {
+                  "type": "array",
+                  "items": {"$ref": "#/definitions/component"},
+                  "uniqueItems": true,
+                  "title": "Components",
+                  "description": "A list of software and hardware components used as tools"
+                },
+                "services": {
+                  "type": "array",
+                  "items": {"$ref": "#/definitions/service"},
+                  "uniqueItems": true,
+                  "title": "Services",
+                  "description": "A list of services used as tools. This may include microservices, function-as-a-service, and other types of network or intra-process services."
+                }
+              }
+            },
+            {
+              "type": "array",
+              "title": "Tools (legacy)",
+              "description": "[Deprecated] The tool(s) used to identify, confirm, or score the vulnerability.",
+              "items": {"$ref": "#/definitions/tool"}
+            }
+          ]
+        },
+        "analysis": {
+          "type": "object",
+          "title": "Impact Analysis",
+          "description": "An assessment of the impact and exploitability of the vulnerability.",
+          "additionalProperties": false,
+          "properties": {
+            "state": {
+              "$ref": "#/definitions/impactAnalysisState"
+            },
+            "justification": {
+              "$ref": "#/definitions/impactAnalysisJustification"
+            },
+            "response": {
+              "type": "array",
+              "title": "Response",
+              "description": "A response to the vulnerability by the manufacturer, supplier, or project responsible for the affected component or service. More than one response is allowed. Responses are strongly encouraged for vulnerabilities where the analysis state is exploitable.",
+              "items": {
+                "type": "string",
+                "enum": [
+                  "can_not_fix",
+                  "will_not_fix",
+                  "update",
+                  "rollback",
+                  "workaround_available"
+                ]
+              }
+            },
+            "detail": {
+              "type": "string",
+              "title": "Detail",
+              "description": "Detailed description of the impact including methods used during assessment. If a vulnerability is not exploitable, this field should include specific details on why the component or service is not impacted by this vulnerability."
+            },
+            "firstIssued": {
+              "type": "string",
+              "format": "date-time",
+              "title": "First Issued",
+              "description": "The date and time (timestamp) when the analysis was first issued."
+            },
+            "lastUpdated": {
+              "type": "string",
+              "format": "date-time",
+              "title": "Last Updated",
+              "description": "The date and time (timestamp) when the analysis was last updated."
+            }
+          }
+        },
+        "affects": {
+          "type": "array",
+          "uniqueItems": true,
+          "items": {
+            "type": "object",
+            "required": [
+              "ref"
+            ],
+            "additionalProperties": false,
+            "properties": {
+              "ref": {
+                "anyOf": [
+                  {
+                    "title": "Ref",
+                    "$ref": "#/definitions/refLinkType"
+                  },
+                  {
+                    "title": "BOM-Link Element",
+                    "$ref": "#/definitions/bomLinkElementType"
+                  }
+                ],
+                "title": "Reference",
+                "description": "References a component or service by the objects bom-ref"
+              },
+              "versions": {
+                "type": "array",
+                "title": "Versions",
+                "description": "Zero or more individual versions or range of versions.",
+                "items": {
+                  "type": "object",
+                  "oneOf": [
+                    {
+                      "required": ["version"]
+                    },
+                    {
+                      "required": ["range"]
+                    }
+                  ],
+                  "additionalProperties": false,
+                  "properties": {
+                    "version": {
+                      "description": "A single version of a component or service.",
+                      "$ref": "#/definitions/version"
+                    },
+                    "range": {
+                      "description": "A version range specified in Package URL Version Range syntax (vers) which is defined at https://github.com/package-url/purl-spec/VERSION-RANGE-SPEC.rst",
+                      "$ref": "#/definitions/range"
+                    },
+                    "status": {
+                      "description": "The vulnerability status for the version or range of versions.",
+                      "$ref": "#/definitions/affectedStatus",
+                      "default": "affected"
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "title": "Affects",
+          "description": "The components or services that are affected by the vulnerability."
+        },
+        "properties": {
+          "type": "array",
+          "title": "Properties",
+          "description": "Provides the ability to document properties in a name-value store. This provides flexibility to include data not officially supported in the standard without having to use additional namespaces or create extensions. Unlike key-value stores, properties support duplicate names, each potentially having different values. Property names of interest to the general public are encouraged to be registered in the [CycloneDX Property Taxonomy](https://github.com/CycloneDX/cyclonedx-property-taxonomy). Formal registration is OPTIONAL.",
+          "items": {
+            "$ref": "#/definitions/property"
+          }
+        }
+      }
+    },
+    "affectedStatus": {
+      "description": "The vulnerability status of a given version or range of versions of a product. The statuses 'affected' and 'unaffected' indicate that the version is affected or unaffected by the vulnerability. The status 'unknown' indicates that it is unknown or unspecified whether the given version is affected. There can be many reasons for an 'unknown' status, including that an investigation has not been undertaken or that a vendor has not disclosed the status.",
+      "type": "string",
+      "enum": [
+        "affected",
+        "unaffected",
+        "unknown"
+      ]
+    },
+    "version": {
+      "description": "A single version of a component or service.",
+      "type": "string",
+      "minLength": 1,
+      "maxLength": 1024
+    },
+    "range": {
+      "description": "A version range specified in Package URL Version Range syntax (vers) which is defined at https://github.com/package-url/purl-spec/VERSION-RANGE-SPEC.rst",
+      "type": "string",
+      "minLength": 1,
+      "maxLength": 1024
+    },
+    "annotations": {
+      "type": "object",
+      "title": "Annotations",
+      "description": "A comment, note, explanation, or similar textual content which provides additional context to the object(s) being annotated.",
+      "required": [
+        "subjects",
+        "annotator",
+        "timestamp",
+        "text"
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "bom-ref": {
+          "$ref": "#/definitions/refType",
+          "title": "BOM Reference",
+          "description": "An optional identifier which can be used to reference the annotation elsewhere in the BOM. Every bom-ref MUST be unique within the BOM."
+        },
+        "subjects": {
+          "type": "array",
+          "uniqueItems": true,
+          "items": {
+            "anyOf": [
+              {
+                "title": "Ref",
+                "$ref": "#/definitions/refLinkType"
+              },
+              {
+                "title": "BOM-Link Element",
+                "$ref": "#/definitions/bomLinkElementType"
+              }
+            ]
+          },
+          "title": "BOM References",
+          "description": "The object in the BOM identified by its bom-ref. This is often a component or service, but may be any object type supporting bom-refs."
+        },
+        "annotator": {
+          "type": "object",
+          "title": "Annotator",
+          "description": "The organization, person, component, or service which created the textual content of the annotation.",
+          "oneOf": [
+            {
+              "required": [
+                "organization"
+              ]
+            },
+            {
+              "required": [
+                "individual"
+              ]
+            },
+            {
+              "required": [
+                "component"
+              ]
+            },
+            {
+              "required": [
+                "service"
+              ]
+            }
+          ],
+          "additionalProperties": false,
+          "properties": {
+            "organization": {
+              "description": "The organization that created the annotation",
+              "$ref": "#/definitions/organizationalEntity"
+            },
+            "individual": {
+              "description": "The person that created the annotation",
+              "$ref": "#/definitions/organizationalContact"
+            },
+            "component": {
+              "description": "The tool or component that created the annotation",
+              "$ref": "#/definitions/component"
+            },
+            "service": {
+              "description": "The service that created the annotation",
+              "$ref": "#/definitions/service"
+            }
+          }
+        },
+        "timestamp": {
+          "type": "string",
+          "format": "date-time",
+          "title": "Timestamp",
+          "description": "The date and time (timestamp) when the annotation was created."
+        },
+        "text": {
+          "type": "string",
+          "title": "Text",
+          "description": "The textual content of the annotation."
+        },
+        "signature": {
+          "$ref": "#/definitions/signature",
+          "title": "Signature",
+          "description": "Enveloped signature in [JSON Signature Format (JSF)](https://cyberphone.github.io/doc/security/jsf.html)."
+        }
+      }
+    },
+    "modelCard": {
+      "$comment": "Model card support in CycloneDX is derived from TensorFlow Model Card Toolkit released under the Apache 2.0 license and available from https://github.com/tensorflow/model-card-toolkit/blob/main/model_card_toolkit/schema/v0.0.2/model_card.schema.json. In addition, CycloneDX model card support includes portions of VerifyML, also released under the Apache 2.0 license and available from https://github.com/cylynx/verifyml/blob/main/verifyml/model_card_toolkit/schema/v0.0.4/model_card.schema.json.",
+      "type": "object",
+      "title": "Model Card",
+      "description": "A model card describes the intended uses of a machine learning model and potential limitations, including biases and ethical considerations. Model cards typically contain the training parameters, which datasets were used to train the model, performance metrics, and other relevant data useful for ML transparency. This object SHOULD be specified for any component of type `machine-learning-model` and MUST NOT be specified for other component types.",
+      "additionalProperties": false,
+      "properties": {
+        "bom-ref": {
+          "$ref": "#/definitions/refType",
+          "title": "BOM Reference",
+          "description": "An optional identifier which can be used to reference the model card elsewhere in the BOM. Every bom-ref MUST be unique within the BOM."
+        },
+        "modelParameters": {
+          "type": "object",
+          "title": "Model Parameters",
+          "description": "Hyper-parameters for construction of the model.",
+          "additionalProperties": false,
+          "properties": {
+            "approach": {
+              "type": "object",
+              "title": "Approach",
+              "description": "The overall approach to learning used by the model for problem solving.",
+              "additionalProperties": false,
+              "properties": {
+                "type": {
+                  "type": "string",
+                  "title": "Learning Type",
+                  "description": "Learning types describing the learning problem or hybrid learning problem.",
+                  "enum": [
+                    "supervised",
+                    "unsupervised",
+                    "reinforcement-learning",
+                    "semi-supervised",
+                    "self-supervised"
+                  ]
+                }
+              }
+            },
+            "task": {
+              "type": "string",
+              "title": "Task",
+              "description": "Directly influences the input and/or output. Examples include classification, regression, clustering, etc."
+            },
+            "architectureFamily": {
+              "type": "string",
+              "title": "Architecture Family",
+              "description": "The model architecture family such as transformer network, convolutional neural network, residual neural network, LSTM neural network, etc."
+            },
+            "modelArchitecture": {
+              "type": "string",
+              "title": "Model Architecture",
+              "description": "The specific architecture of the model such as GPT-1, ResNet-50, YOLOv3, etc."
+            },
+            "datasets": {
+              "type": "array",
+              "title": "Datasets",
+              "description": "The datasets used to train and evaluate the model.",
+              "items" : {
+                "oneOf" : [
+                  {
+                    "title": "Inline Component Data",
+                    "$ref": "#/definitions/componentData"
+                  },
+                  {
+                    "type": "object",
+                    "title": "Data Component Reference",
+                    "additionalProperties": false,
+                    "properties": {
+                      "ref": {
+                        "anyOf": [
+                          {
+                            "title": "Ref",
+                            "$ref": "#/definitions/refLinkType"
+                          },
+                          {
+                            "title": "BOM-Link Element",
+                            "$ref": "#/definitions/bomLinkElementType"
+                          }
+                        ],
+                        "title": "Reference",
+                        "description": "References a data component by the components bom-ref attribute"
+                      }
+                    }
+                  }
+                ]
+              }
+            },
+            "inputs": {
+              "type": "array",
+              "title": "Inputs",
+              "description": "The input format(s) of the model",
+              "items": { "$ref": "#/definitions/inputOutputMLParameters" }
+            },
+            "outputs": {
+              "type": "array",
+              "title": "Outputs",
+              "description": "The output format(s) from the model",
+              "items": { "$ref": "#/definitions/inputOutputMLParameters" }
+            }
+          }
+        },
+        "quantitativeAnalysis": {
+          "type": "object",
+          "title": "Quantitative Analysis",
+          "description": "A quantitative analysis of the model",
+          "additionalProperties": false,
+          "properties": {
+            "performanceMetrics": {
+              "type": "array",
+              "title": "Performance Metrics",
+              "description": "The model performance metrics being reported. Examples may include accuracy, F1 score, precision, top-3 error rates, MSC, etc.",
+              "items": { "$ref": "#/definitions/performanceMetric" }
+            },
+            "graphics": { "$ref": "#/definitions/graphicsCollection" }
+          }
+        },
+        "considerations": {
+          "type": "object",
+          "title": "Considerations",
+          "description": "What considerations should be taken into account regarding the model's construction, training, and application?",
+          "additionalProperties": false,
+          "properties": {
+            "users": {
+              "type": "array",
+              "title": "Users",
+              "description": "Who are the intended users of the model?",
+              "items": {
+                "type": "string"
+              }
+            },
+            "useCases": {
+              "type": "array",
+              "title": "Use Cases",
+              "description": "What are the intended use cases of the model?",
+              "items": {
+                "type": "string"
+              }
+            },
+            "technicalLimitations": {
+              "type": "array",
+              "title": "Technical Limitations",
+              "description": "What are the known technical limitations of the model? E.g. What kind(s) of data should the model be expected not to perform well on? What are the factors that might degrade model performance?",
+              "items": {
+                "type": "string"
+              }
+            },
+            "performanceTradeoffs": {
+              "type": "array",
+              "title": "Performance Tradeoffs",
+              "description": "What are the known tradeoffs in accuracy/performance of the model?",
+              "items": {
+                "type": "string"
+              }
+            },
+            "ethicalConsiderations": {
+              "type": "array",
+              "title": "Ethical Considerations",
+              "description": "What are the ethical (or environmental) risks involved in the application of this model?",
+              "items": { "$ref": "#/definitions/risk" }
+            },
+            "fairnessAssessments": {
+              "type": "array",
+              "title": "Fairness Assessments",
+              "description": "How does the model affect groups at risk of being systematically disadvantaged? What are the harms and benefits to the various affected groups?",
+              "items": {
+                "$ref": "#/definitions/fairnessAssessment"
+              }
+            }
+          }
+        },
+        "properties": {
+          "type": "array",
+          "title": "Properties",
+          "description": "Provides the ability to document properties in a name-value store. This provides flexibility to include data not officially supported in the standard without having to use additional namespaces or create extensions. Unlike key-value stores, properties support duplicate names, each potentially having different values. Property names of interest to the general public are encouraged to be registered in the [CycloneDX Property Taxonomy](https://github.com/CycloneDX/cyclonedx-property-taxonomy). Formal registration is OPTIONAL.",
+          "items": {"$ref": "#/definitions/property"}
+        }
+      }
+    },
+    "inputOutputMLParameters": {
+      "type": "object",
+      "title": "Input and Output Parameters",
+      "additionalProperties": false,
+      "properties": {
+        "format": {
+          "description": "The data format for input/output to the model. Example formats include string, image, time-series",
+          "type": "string"
+        }
+      }
+    },
+    "componentData": {
+      "type": "object",
+      "additionalProperties": false,
+      "required": [
+        "type"
+      ],
+      "properties": {
+        "bom-ref": {
+          "$ref": "#/definitions/refType",
+          "title": "BOM Reference",
+          "description": "An optional identifier which can be used to reference the dataset elsewhere in the BOM. Every bom-ref MUST be unique within the BOM."
+        },
+        "type": {
+          "type": "string",
+          "title": "Type of Data",
+          "description": "The general theme or subject matter of the data being specified.\n\n* __source-code__ = Any type of code, code snippet, or data-as-code.\n* __configuration__ = Parameters or settings that may be used by other components.\n* __dataset__ = A collection of data.\n* __definition__ = Data that can be used to create new instances of what the definition defines.\n* __other__ = Any other type of data that does not fit into existing definitions.",
+          "enum": [
+            "source-code",
+            "configuration",
+            "dataset",
+            "definition",
+            "other"
+          ]
+        },
+        "name": {
+          "description": "The name of the dataset.",
+          "type": "string"
+        },
+        "contents": {
+          "type": "object",
+          "title": "Data Contents",
+          "description": "The contents or references to the contents of the data being described.",
+          "additionalProperties": false,
+          "properties": {
+            "attachment": {
+              "title": "Data Attachment",
+              "description": "An optional way to include textual or encoded data.",
+              "$ref": "#/definitions/attachment"
+            },
+            "url": {
+              "type": "string",
+              "title": "Data URL",
+              "description": "The URL to where the data can be retrieved.",
+              "format": "iri-reference"
+            },
+            "properties": {
+              "type": "array",
+              "title": "Configuration Properties",
+              "description": "Provides the ability to document name-value parameters used for configuration.",
+              "items": {
+                "$ref": "#/definitions/property"
+              }
+            }
+          }
+        },
+        "classification": {
+          "$ref": "#/definitions/dataClassification"
+        },
+        "sensitiveData": {
+          "type": "array",
+          "description": "A description of any sensitive data in a dataset.",
+          "items": {
+            "type": "string"
+          }
+        },
+        "graphics": { "$ref": "#/definitions/graphicsCollection" },
+        "description": {
+          "description": "A description of the dataset. Can describe size of dataset, whether it's used for source code, training, testing, or validation, etc.",
+          "type": "string"
+        },
+        "governance": {
+          "type": "object",
+          "title": "Data Governance",
+          "$ref": "#/definitions/dataGovernance"
+        }
+      }
+    },
+    "dataGovernance": {
+      "type": "object",
+      "title": "Data Governance",
+      "additionalProperties": false,
+      "properties": {
+        "custodians": {
+          "type": "array",
+          "title": "Data Custodians",
+          "description": "Data custodians are responsible for the safe custody, transport, and storage of data.",
+          "items": { "$ref": "#/definitions/dataGovernanceResponsibleParty" }
+        },
+        "stewards": {
+          "type": "array",
+          "title": "Data Stewards",
+          "description": "Data stewards are responsible for data content, context, and associated business rules.",
+          "items": { "$ref": "#/definitions/dataGovernanceResponsibleParty" }
+        },
+        "owners": {
+          "type": "array",
+          "title": "Data Owners",
+          "description": "Data owners are concerned with risk and appropriate access to data.",
+          "items": { "$ref": "#/definitions/dataGovernanceResponsibleParty" }
+        }
+      }
+    },
+    "dataGovernanceResponsibleParty": {
+      "type": "object",
+      "additionalProperties": false,
+      "properties": {
+        "organization": {
+          "title": "Organization",
+          "$ref": "#/definitions/organizationalEntity"
+        },
+        "contact": {
+          "title": "Individual",
+          "$ref": "#/definitions/organizationalContact"
+        }
+      },
+      "oneOf":[
+        {
+          "required": ["organization"]
+        },
+        {
+          "required": ["contact"]
+        }
+      ]
+    },
+    "graphicsCollection": {
+      "type": "object",
+      "title": "Graphics Collection",
+      "description": "A collection of graphics that represent various measurements.",
+      "additionalProperties": false,
+      "properties": {
+        "description": {
+          "description": "A description of this collection of graphics.",
+          "type": "string"
+        },
+        "collection": {
+          "description": "A collection of graphics.",
+          "type": "array",
+          "items": { "$ref": "#/definitions/graphic" }
+        }
+      }
+    },
+    "graphic": {
+      "type": "object",
+      "additionalProperties": false,
+      "properties": {
+        "name": {
+          "description": "The name of the graphic.",
+          "type": "string"
+        },
+        "image": {
+          "title": "Graphic Image",
+          "description": "The graphic (vector or raster). Base64 encoding MUST be specified for binary images.",
+          "$ref": "#/definitions/attachment"
+        }
+      }
+    },
+    "performanceMetric": {
+      "type": "object",
+      "additionalProperties": false,
+      "properties": {
+        "type": {
+          "description": "The type of performance metric.",
+          "type": "string"
+        },
+        "value": {
+          "description": "The value of the performance metric.",
+          "type": "string"
+        },
+        "slice": {
+          "description": "The name of the slice this metric was computed on. By default, assume this metric is not sliced.",
+          "type": "string"
+        },
+        "confidenceInterval": {
+          "description": "The confidence interval of the metric.",
+          "type": "object",
+          "additionalProperties": false,
+          "properties": {
+            "lowerBound": {
+              "description": "The lower bound of the confidence interval.",
+              "type": "string"
+            },
+            "upperBound": {
+              "description": "The upper bound of the confidence interval.",
+              "type": "string"
+            }
+          }
+        }
+      }
+    },
+    "risk": {
+      "type": "object",
+      "additionalProperties": false,
+      "properties": {
+        "name": {
+          "description": "The name of the risk.",
+          "type": "string"
+        },
+        "mitigationStrategy": {
+          "description": "Strategy used to address this risk.",
+          "type": "string"
+        }
+      }
+    },
+    "fairnessAssessment": {
+      "type": "object",
+      "title": "Fairness Assessment",
+      "description": "Information about the benefits and harms of the model to an identified at risk group.",
+      "additionalProperties": false,
+      "properties": {
+        "groupAtRisk": {
+          "type": "string",
+          "description": "The groups or individuals at risk of being systematically disadvantaged by the model."
+        },
+        "benefits": {
+          "type": "string",
+          "description": "Expected benefits to the identified groups."
+        },
+        "harms": {
+          "type": "string",
+          "description": "Expected harms to the identified groups."
+        },
+        "mitigationStrategy": {
+          "type": "string",
+          "description": "With respect to the benefits and harms outlined, please describe any mitigation strategy implemented."
+        }
+      }
+    },
+    "dataClassification": {
+      "type": "string",
+      "title": "Data Classification",
+      "description": "Data classification tags data according to its type, sensitivity, and value if altered, stolen, or destroyed."
+    },
+    "formula": {
+      "title": "Formula",
+      "description": "Describes workflows and resources that captures rules and other aspects of how the associated BOM component or service was formed.",
+      "type": "object",
+      "additionalProperties": false,
+      "properties": {
+        "bom-ref": {
+          "title": "BOM Reference",
+          "description": "An optional identifier which can be used to reference the formula elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.",
+          "$ref": "#/definitions/refType"
+        },
+        "components": {
+          "title": "Components",
+          "description": "Transient components that are used in tasks that constitute one or more of this formula's workflows",
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/component"
+          },
+          "uniqueItems": true
+        },
+        "services": {
+          "title": "Services",
+          "description": "Transient services that are used in tasks that constitute one or more of this formula's workflows",
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/service"
+          },
+          "uniqueItems": true
+        },
+        "workflows": {
+          "title": "Workflows",
+          "description": "List of workflows that can be declared to accomplish specific orchestrated goals and independently triggered.",
+          "$comment": "Different workflows can be designed to work together to perform end-to-end CI/CD builds and deployments.",
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/workflow"
+          },
+          "uniqueItems": true
+        },
+        "properties": {
+          "type": "array",
+          "title": "Properties",
+          "items": {
+            "$ref": "#/definitions/property"
+          }
+        }
+      }
+    },
+    "workflow": {
+      "title": "Workflow",
+      "description": "A specialized orchestration task.",
+      "$comment": "Workflow are as task themselves and can trigger other workflow tasks.  These relationships can be modeled in the taskDependencies graph.",
+      "type": "object",
+      "required": [
+        "bom-ref",
+        "uid",
+        "taskTypes"
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "bom-ref": {
+          "title": "BOM Reference",
+          "description": "An optional identifier which can be used to reference the workflow elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.",
+          "$ref": "#/definitions/refType"
+        },
+        "uid": {
+          "title": "Unique Identifier (UID)",
+          "description": "The unique identifier for the resource instance within its deployment context.",
+          "type": "string"
+        },
+        "name": {
+          "title": "Name",
+          "description": "The name of the resource instance.",
+          "type": "string"
+        },
+        "description": {
+          "title": "Description",
+          "description": "A description of the resource instance.",
+          "type": "string"
+        },
+        "resourceReferences": {
+          "title": "Resource references",
+          "description": "References to component or service resources that are used to realize the resource instance.",
+          "type": "array",
+          "uniqueItems": true,
+          "items": {
+            "$ref": "#/definitions/resourceReferenceChoice"
+          }
+        },
+        "tasks": {
+          "title": "Tasks",
+          "description": "The tasks that comprise the workflow.",
+          "$comment": "Note that tasks can appear more than once as different instances (by name or UID).",
+          "type": "array",
+          "uniqueItems": true,
+          "items": {
+            "$ref": "#/definitions/task"
+          }
+        },
+        "taskDependencies": {
+          "title": "Task dependency graph",
+          "description": "The graph of dependencies between tasks within the workflow.",
+          "type": "array",
+          "uniqueItems": true,
+          "items": {
+            "$ref": "#/definitions/dependency"
+          }
+        },
+        "taskTypes": {
+          "title": "Task types",
+          "description": "Indicates the types of activities performed by the set of workflow tasks.",
+          "$comment": "Currently, these types reflect common CI/CD actions.",
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/taskType"
+          }
+        },
+        "trigger": {
+          "title": "Trigger",
+          "description": "The trigger that initiated the task.",
+          "$ref": "#/definitions/trigger"
+        },
+        "steps": {
+          "title": "Steps",
+          "description": "The sequence of steps for the task.",
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/step"
+          },
+          "uniqueItems": true
+        },
+        "inputs": {
+          "title": "Inputs",
+          "description": "Represents resources and data brought into a task at runtime by executor or task commands",
+          "examples": ["a `configuration` file which was declared as a local `component` or `externalReference`"],
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/inputType"
+          },
+          "uniqueItems": true
+        },
+        "outputs": {
+          "title": "Outputs",
+          "description": "Represents resources and data output from a task at runtime by executor or task commands",
+          "examples": ["a log file or metrics data produced by the task"],
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/outputType"
+          },
+          "uniqueItems": true
+        },
+        "timeStart": {
+          "title": "Time start",
+          "description": "The date and time (timestamp) when the task started.",
+          "type": "string",
+          "format": "date-time"
+        },
+        "timeEnd": {
+          "title": "Time end",
+          "description": "The date and time (timestamp) when the task ended.",
+          "type": "string",
+          "format": "date-time"
+        },
+        "workspaces": {
+          "title": "Workspaces",
+          "description": "A set of named filesystem or data resource shareable by workflow tasks.",
+          "type": "array",
+          "uniqueItems": true,
+          "items": {
+            "$ref": "#/definitions/workspace"
+          }
+        },
+        "runtimeTopology": {
+          "title": "Runtime topology",
+          "description": "A graph of the component runtime topology for workflow's instance.",
+          "$comment": "A description of the runtime component and service topology.  This can describe a partial or complete topology used to host and execute the task (e.g., hardware, operating systems, configurations, etc.),",
+          "type": "array",
+          "uniqueItems": true,
+          "items": {
+            "$ref": "#/definitions/dependency"
+          }
+        },
+        "properties": {
+          "type": "array",
+          "title": "Properties",
+          "items": {
+            "$ref": "#/definitions/property"
+          }
+        }
+      }
+    },
+    "task": {
+      "title": "Task",
+      "description": "Describes the inputs, sequence of steps and resources used to accomplish a task and its output.",
+      "$comment": "Tasks are building blocks for constructing assemble CI/CD workflows or pipelines.",
+      "type": "object",
+      "required": [
+        "bom-ref",
+        "uid",
+        "taskTypes"
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "bom-ref": {
+          "title": "BOM Reference",
+          "description": "An optional identifier which can be used to reference the task elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.",
+          "$ref": "#/definitions/refType"
+        },
+        "uid": {
+          "title": "Unique Identifier (UID)",
+          "description": "The unique identifier for the resource instance within its deployment context.",
+          "type": "string"
+        },
+        "name": {
+          "title": "Name",
+          "description": "The name of the resource instance.",
+          "type": "string"
+        },
+        "description": {
+          "title": "Description",
+          "description": "A description of the resource instance.",
+          "type": "string"
+        },
+        "resourceReferences": {
+          "title": "Resource references",
+          "description": "References to component or service resources that are used to realize the resource instance.",
+          "type": "array",
+          "uniqueItems": true,
+          "items": {
+            "$ref": "#/definitions/resourceReferenceChoice"
+          }
+        },
+        "taskTypes": {
+          "title": "Task types",
+          "description": "Indicates the types of activities performed by the set of workflow tasks.",
+          "$comment": "Currently, these types reflect common CI/CD actions.",
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/taskType"
+          }
+        },
+        "trigger": {
+          "title": "Trigger",
+          "description": "The trigger that initiated the task.",
+          "$ref": "#/definitions/trigger"
+        },
+        "steps": {
+          "title": "Steps",
+          "description": "The sequence of steps for the task.",
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/step"
+          },
+          "uniqueItems": true
+        },
+        "inputs": {
+          "title": "Inputs",
+          "description": "Represents resources and data brought into a task at runtime by executor or task commands",
+          "examples": ["a `configuration` file which was declared as a local `component` or `externalReference`"],
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/inputType"
+          },
+          "uniqueItems": true
+        },
+        "outputs": {
+          "title": "Outputs",
+          "description": "Represents resources and data output from a task at runtime by executor or task commands",
+          "examples": ["a log file or metrics data produced by the task"],
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/outputType"
+          },
+          "uniqueItems": true
+        },
+        "timeStart": {
+          "title": "Time start",
+          "description": "The date and time (timestamp) when the task started.",
+          "type": "string",
+          "format": "date-time"
+        },
+        "timeEnd": {
+          "title": "Time end",
+          "description": "The date and time (timestamp) when the task ended.",
+          "type": "string",
+          "format": "date-time"
+        },
+        "workspaces": {
+          "title": "Workspaces",
+          "description": "A set of named filesystem or data resource shareable by workflow tasks.",
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/workspace"
+          },
+          "uniqueItems": true
+        },
+        "runtimeTopology": {
+          "title": "Runtime topology",
+          "description": "A graph of the component runtime topology for task's instance.",
+          "$comment": "A description of the runtime component and service topology.  This can describe a partial or complete topology used to host and execute the task (e.g., hardware, operating systems, configurations, etc.),",
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/dependency"
+          },
+          "uniqueItems": true
+        },
+        "properties": {
+          "type": "array",
+          "title": "Properties",
+          "items": {
+            "$ref": "#/definitions/property"
+          }
+        }
+      }
+    },
+    "step": {
+      "type": "object",
+      "description": "Executes specific commands or tools in order to accomplish its owning task as part of a sequence.",
+      "additionalProperties": false,
+      "properties": {
+        "name": {
+          "title": "Name",
+          "description": "A name for the step.",
+          "type": "string"
+        },
+        "description": {
+          "title": "Description",
+          "description": "A description of the step.",
+          "type": "string"
+        },
+        "commands": {
+          "title": "Commands",
+          "description": "Ordered list of commands or directives for the step",
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/command"
+          }
+        },
+        "properties": {
+          "type": "array",
+          "title": "Properties",
+          "items": {
+            "$ref": "#/definitions/property"
+          }
+        }
+      }
+    },
+    "command": {
+      "type": "object",
+      "additionalProperties": false,
+      "properties": {
+        "executed": {
+          "title": "Executed",
+          "description": "A text representation of the executed command.",
+          "type": "string"
+        },
+        "properties": {
+          "type": "array",
+          "title": "Properties",
+          "items": {
+            "$ref": "#/definitions/property"
+          }
+        }
+      }
+    },
+    "workspace": {
+      "title": "Workspace",
+      "description": "A named filesystem or data resource shareable by workflow tasks.",
+      "type": "object",
+      "required": [
+        "bom-ref",
+        "uid"
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "bom-ref": {
+          "title": "BOM Reference",
+          "description": "An optional identifier which can be used to reference the workspace elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.",
+          "$ref": "#/definitions/refType"
+        },
+        "uid": {
+          "title": "Unique Identifier (UID)",
+          "description": "The unique identifier for the resource instance within its deployment context.",
+          "type": "string"
+        },
+        "name": {
+          "title": "Name",
+          "description": "The name of the resource instance.",
+          "type": "string"
+        },
+        "aliases": {
+          "title": "Aliases",
+          "description": "The names for the workspace as referenced by other workflow tasks. Effectively, a name mapping so other tasks can use their own local name in their steps.",
+          "type": "array",
+          "items": {"type": "string"}
+        },
+        "description": {
+          "title": "Description",
+          "description": "A description of the resource instance.",
+          "type": "string"
+        },
+        "resourceReferences": {
+          "title": "Resource references",
+          "description": "References to component or service resources that are used to realize the resource instance.",
+          "type": "array",
+          "uniqueItems": true,
+          "items": {
+            "$ref": "#/definitions/resourceReferenceChoice"
+          }
+        },
+        "accessMode": {
+          "title": "Access mode",
+          "description": "Describes the read-write access control for the workspace relative to the owning resource instance.",
+          "type": "string",
+          "enum": [
+            "read-only",
+            "read-write",
+            "read-write-once",
+            "write-once",
+            "write-only"
+          ]
+        },
+        "mountPath": {
+          "title": "Mount path",
+          "description": "A path to a location on disk where the workspace will be available to the associated task's steps.",
+          "type": "string"
+        },
+        "managedDataType": {
+          "title": "Managed data type",
+          "description": "The name of a domain-specific data type the workspace represents.",
+          "$comment": "This property is for CI/CD frameworks that are able to provide access to structured, managed data at a more granular level than a filesystem.",
+          "examples": ["ConfigMap","Secret"],
+          "type": "string"
+        },
+        "volumeRequest": {
+          "title": "Volume request",
+          "description": "Identifies the reference to the request for a specific volume type and parameters.",
+          "examples": ["a kubernetes Persistent Volume Claim (PVC) name"],
+          "type": "string"
+        },
+        "volume": {
+          "title": "Volume",
+          "description": "Information about the actual volume instance allocated to the workspace.",
+          "$comment": "The actual volume allocated may be different than the request.",
+          "examples": ["see https://kubernetes.io/docs/concepts/storage/persistent-volumes/"],
+          "$ref": "#/definitions/volume"
+        },
+        "properties": {
+          "type": "array",
+          "title": "Properties",
+          "items": {
+            "$ref": "#/definitions/property"
+          }
+        }
+      }
+    },
+    "volume": {
+      "title": "Volume",
+      "description": "An identifiable, logical unit of data storage tied to a physical device.",
+      "type": "object",
+      "additionalProperties": false,
+      "properties": {
+        "uid": {
+          "title": "Unique Identifier (UID)",
+          "description": "The unique identifier for the volume instance within its deployment context.",
+          "type": "string"
+        },
+        "name": {
+          "title": "Name",
+          "description": "The name of the volume instance",
+          "type": "string"
+        },
+        "mode": {
+          "title": "Mode",
+          "description": "The mode for the volume instance.",
+          "type": "string",
+          "enum": [
+            "filesystem", "block"
+          ],
+          "default": "filesystem"
+        },
+        "path": {
+          "title": "Path",
+          "description": "The underlying path created from the actual volume.",
+          "type": "string"
+        },
+        "sizeAllocated": {
+          "title": "Size allocated",
+          "description": "The allocated size of the volume accessible to the associated workspace. This should include the scalar size as well as IEC standard unit in either decimal or binary form.",
+          "examples": ["10GB", "2Ti", "1Pi"],
+          "type": "string"
+        },
+        "persistent": {
+          "title": "Persistent",
+          "description": "Indicates if the volume persists beyond the life of the resource it is associated with.",
+          "type": "boolean"
+        },
+        "remote": {
+          "title": "Remote",
+          "description": "Indicates if the volume is remotely (i.e., network) attached.",
+          "type": "boolean"
+        },
+        "properties": {
+          "type": "array",
+          "title": "Properties",
+          "items": {
+            "$ref": "#/definitions/property"
+          }
+        }
+      }
+    },
+    "trigger": {
+      "title": "Trigger",
+      "description": "Represents a resource that can conditionally activate (or fire) tasks based upon associated events and their data.",
+      "type": "object",
+      "additionalProperties": false,
+      "required": [
+        "type",
+        "bom-ref",
+        "uid"
+      ],
+      "properties": {
+        "bom-ref": {
+          "title": "BOM Reference",
+          "description": "An optional identifier which can be used to reference the trigger elsewhere in the BOM. Every bom-ref MUST be unique within the BOM.",
+          "$ref": "#/definitions/refType"
+        },
+        "uid": {
+          "title": "Unique Identifier (UID)",
+          "description": "The unique identifier for the resource instance within its deployment context.",
+          "type": "string"
+        },
+        "name": {
+          "title": "Name",
+          "description": "The name of the resource instance.",
+          "type": "string"
+        },
+        "description": {
+          "title": "Description",
+          "description": "A description of the resource instance.",
+          "type": "string"
+        },
+        "resourceReferences": {
+          "title": "Resource references",
+          "description": "References to component or service resources that are used to realize the resource instance.",
+          "type": "array",
+          "uniqueItems": true,
+          "items": {
+            "$ref": "#/definitions/resourceReferenceChoice"
+          }
+        },
+        "type": {
+          "title": "Type",
+          "description": "The source type of event which caused the trigger to fire.",
+          "type": "string",
+          "enum": [
+            "manual",
+            "api",
+            "webhook",
+            "scheduled"
+          ]
+        },
+        "event": {
+          "title": "Event",
+          "description": "The event data that caused the associated trigger to activate.",
+          "$ref": "#/definitions/event"
+        },
+        "conditions": {
+          "type": "array",
+          "uniqueItems": true,
+          "items": {
+            "$ref": "#/definitions/condition"
+          }
+        },
+        "timeActivated": {
+          "title": "Time activated",
+          "description": "The date and time (timestamp) when the trigger was activated.",
+          "type": "string",
+          "format": "date-time"
+        },
+        "inputs": {
+          "title": "Inputs",
+          "description": "Represents resources and data brought into a task at runtime by executor or task commands",
+          "examples": ["a `configuration` file which was declared as a local `component` or `externalReference`"],
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/inputType"
+          },
+          "uniqueItems": true
+        },
+        "outputs": {
+          "title": "Outputs",
+          "description": "Represents resources and data output from a task at runtime by executor or task commands",
+          "examples": ["a log file or metrics data produced by the task"],
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/outputType"
+          },
+          "uniqueItems": true
+        },
+        "properties": {
+          "type": "array",
+          "title": "Properties",
+          "items": {
+            "$ref": "#/definitions/property"
+          }
+        }
+      }
+    },
+    "event": {
+      "title": "Event",
+      "description": "Represents something that happened that may trigger a response.",
+      "type": "object",
+      "additionalProperties": false,
+      "properties": {
+        "uid": {
+          "title": "Unique Identifier (UID)",
+          "description": "The unique identifier of the event.",
+          "type": "string"
+        },
+        "description": {
+          "title": "Description",
+          "description": "A description of the event.",
+          "type": "string"
+        },
+        "timeReceived": {
+          "title": "Time Received",
+          "description": "The date and time (timestamp) when the event was received.",
+          "type": "string",
+          "format": "date-time"
+        },
+        "data": {
+          "title": "Data",
+          "description": "Encoding of the raw event data.",
+          "$ref": "#/definitions/attachment"
+        },
+        "source": {
+          "title": "Source",
+          "description": "References the component or service that was the source of the event",
+          "$ref": "#/definitions/resourceReferenceChoice"
+        },
+        "target": {
+          "title": "Target",
+          "description": "References the component or service that was the target of the event",
+          "$ref": "#/definitions/resourceReferenceChoice"
+        },
+        "properties": {
+          "type": "array",
+          "title": "Properties",
+          "items": {
+            "$ref": "#/definitions/property"
+          }
+        }
+      }
+    },
+    "inputType": {
+      "title": "Input type",
+      "description": "Type that represents various input data types and formats.",
+      "type": "object",
+      "oneOf": [
+        {
+          "required": [
+            "resource"
+          ]
+        },
+        {
+          "required": [
+            "parameters"
+          ]
+        },
+        {
+          "required": [
+            "environmentVars"
+          ]
+        },
+        {
+          "required": [
+            "data"
+          ]
+        }
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "source": {
+          "title": "Source",
+          "description": "A references to the component or service that provided the input to the task (e.g., reference to a service with data flow value of `inbound`)",
+          "examples": [
+            "source code repository",
+            "database"
+          ],
+          "$ref": "#/definitions/resourceReferenceChoice"
+        },
+        "target": {
+          "title": "Target",
+          "description": "A reference to the component or service that received or stored the input if not the task itself (e.g., a local, named storage workspace)",
+          "examples": [
+            "workspace",
+            "directory"
+          ],
+          "$ref": "#/definitions/resourceReferenceChoice"
+        },
+        "resource": {
+          "title": "Resource",
+          "description": "A reference to an independent resource provided as an input to a task by the workflow runtime.",
+          "examples": [
+            "reference to a configuration file in a repository (i.e., a bom-ref)",
+            "reference to a scanning service used in a task (i.e., a bom-ref)"
+          ],
+          "$ref": "#/definitions/resourceReferenceChoice"
+        },
+        "parameters": {
+          "title": "Parameters",
+          "description": "Inputs that have the form of parameters with names and values.",
+          "type": "array",
+          "uniqueItems": true,
+          "items": {
+            "$ref": "#/definitions/parameter"
+          }
+        },
+        "environmentVars": {
+          "title": "Environment variables",
+          "description": "Inputs that have the form of parameters with names and values.",
+          "type": "array",
+          "uniqueItems": true,
+          "items": {
+            "oneOf": [
+              {
+                "$ref": "#/definitions/property"
+              },
+              {
+                "type": "string"
+              }
+            ]
+          }
+        },
+        "data": {
+          "title": "Data",
+          "description": "Inputs that have the form of data.",
+          "$ref": "#/definitions/attachment"
+        },
+        "properties": {
+          "type": "array",
+          "title": "Properties",
+          "items": {
+            "$ref": "#/definitions/property"
+          }
+        }
+      }
+    },
+    "outputType": {
+      "type": "object",
+      "oneOf": [
+        {
+          "required": [
+            "resource"
+          ]
+        },
+        {
+          "required": [
+            "environmentVars"
+          ]
+        },
+        {
+          "required": [
+            "data"
+          ]
+        }
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "type": {
+          "title": "Type",
+          "description": "Describes the type of data output.",
+          "type": "string",
+          "enum": [
+            "artifact",
+            "attestation",
+            "log",
+            "evidence",
+            "metrics",
+            "other"
+          ]
+        },
+        "source": {
+          "title": "Source",
+          "description": "Component or service that generated or provided the output from the task (e.g., a build tool)",
+          "$ref": "#/definitions/resourceReferenceChoice"
+        },
+        "target": {
+          "title": "Target",
+          "description": "Component or service that received the output from the task (e.g., reference to an artifactory service with data flow value of `outbound`)",
+          "examples": ["a log file described as an `externalReference` within its target domain."],
+          "$ref": "#/definitions/resourceReferenceChoice"
+        },
+        "resource": {
+          "title": "Resource",
+          "description": "A reference to an independent resource generated as output by the task.",
+          "examples": [
+            "configuration file",
+            "source code",
+            "scanning service"
+          ],
+          "$ref": "#/definitions/resourceReferenceChoice"
+        },
+        "data": {
+          "title": "Data",
+          "description": "Outputs that have the form of data.",
+          "$ref": "#/definitions/attachment"
+        },
+        "environmentVars": {
+          "title": "Environment variables",
+          "description": "Outputs that have the form of environment variables.",
+          "type": "array",
+          "items": {
+            "oneOf": [
+              {
+                "$ref": "#/definitions/property"
+              },
+              {
+                "type": "string"
+              }
+            ]
+          },
+          "uniqueItems": true
+        },
+        "properties": {
+          "type": "array",
+          "title": "Properties",
+          "items": {
+            "$ref": "#/definitions/property"
+          }
+        }
+      }
+    },
+    "resourceReferenceChoice": {
+      "title": "Resource reference choice",
+      "description": "A reference to a locally defined resource (e.g., a bom-ref) or an externally accessible resource.",
+      "$comment": "Enables reference to a resource that participates in a workflow; using either internal (bom-ref) or external (externalReference) types.",
+      "type": "object",
+      "additionalProperties": false,
+      "properties": {
+        "ref": {
+          "title": "BOM Reference",
+          "description": "References an object by its bom-ref attribute",
+          "anyOf": [
+            {
+              "title": "Ref",
+              "$ref": "#/definitions/refLinkType"
+            },
+            {
+              "title": "BOM-Link Element",
+              "$ref": "#/definitions/bomLinkElementType"
+            }
+          ]
+        },
+        "externalReference": {
+          "title": "External reference",
+          "description": "Reference to an externally accessible resource.",
+          "$ref": "#/definitions/externalReference"
+        }
+      },
+      "oneOf": [
+        {
+          "required": [
+            "ref"
+          ]
+        },
+        {
+          "required": [
+            "externalReference"
+          ]
+        }
+      ]
+    },
+    "condition": {
+      "title": "Condition",
+      "description": "A condition that was used to determine a trigger should be activated.",
+      "type": "object",
+      "additionalProperties": false,
+      "properties": {
+        "description": {
+          "title": "Description",
+          "description": "Describes the set of conditions which cause the trigger to activate.",
+          "type": "string"
+        },
+        "expression": {
+          "title": "Expression",
+          "description": "The logical expression that was evaluated that determined the trigger should be fired.",
+          "type": "string"
+        },
+        "properties": {
+          "type": "array",
+          "title": "Properties",
+          "items": {
+            "$ref": "#/definitions/property"
+          }
+        }
+      }
+    },
+    "taskType": {
+      "type": "string",
+      "enum": [
+        "copy",
+        "clone",
+        "lint",
+        "scan",
+        "merge",
+        "build",
+        "test",
+        "deliver",
+        "deploy",
+        "release",
+        "clean",
+        "other"
+      ]
+    },
+    "parameter": {
+      "title": "Parameter",
+      "description": "A representation of a functional parameter.",
+      "type": "object",
+      "additionalProperties": false,
+      "properties": {
+        "name": {
+          "title": "Name",
+          "description": "The name of the parameter.",
+          "type": "string"
+        },
+        "value": {
+          "title": "Value",
+          "description": "The value of the parameter.",
+          "type": "string"
+        },
+        "dataType": {
+          "title": "Data type",
+          "description": "The data type of the parameter.",
+          "type": "string"
+        }
+      }
+    },
+    "signature": {
+      "$ref": "jsf-0.82.schema.json#/definitions/signature",
+      "title": "Signature",
+      "description": "Enveloped signature in [JSON Signature Format (JSF)](https://cyberphone.github.io/doc/security/jsf.html)."
+    }
+  }
+}
diff --git a/deps/npm/test/schemas/cyclonedx/jsf-0.82.schema.json b/deps/npm/test/schemas/cyclonedx/jsf-0.82.schema.json
new file mode 100644
index 00000000000000..f46bfb1e52731a
--- /dev/null
+++ b/deps/npm/test/schemas/cyclonedx/jsf-0.82.schema.json
@@ -0,0 +1,240 @@
+{
+  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$id": "http://cyclonedx.org/schema/jsf-0.82.schema.json",
+  "type": "object",
+  "title": "JSON Signature Format (JSF) standard",
+  "$comment" : "JSON Signature Format schema is published under the terms of the Apache License 2.0. JSF was developed by Anders Rundgren (anders.rundgren.net@gmail.com) as a part of the OpenKeyStore project. This schema supports the entirely of the JSF standard excluding 'extensions'.",
+  "definitions": {
+    "signature": {
+      "type": "object",
+      "title": "Signature",
+      "oneOf": [
+        {
+          "additionalProperties": false,
+          "properties": {
+            "signers": {
+              "type": "array",
+              "title": "Signature",
+              "description": "Unique top level property for Multiple Signatures. (multisignature)",
+              "items": {"$ref": "#/definitions/signer"}
+            }
+          }
+        },
+        {
+          "additionalProperties": false,
+          "properties": {
+            "chain": {
+              "type": "array",
+              "title": "Signature",
+              "description": "Unique top level property for Signature Chains. (signaturechain)",
+              "items": {"$ref": "#/definitions/signer"}
+            }
+          }
+        },
+        {
+          "title": "Signature",
+          "description": "Unique top level property for simple signatures. (signaturecore)",
+          "$ref": "#/definitions/signer"
+        }
+      ]
+    },
+    "signer": {
+      "type": "object",
+      "title": "Signature",
+      "required": [
+        "algorithm",
+        "value"
+      ],
+      "additionalProperties": false,
+      "properties": {
+        "algorithm": {
+          "oneOf": [
+            {
+              "type": "string",
+              "title": "Algorithm",
+              "description": "Signature algorithm. The currently recognized JWA [RFC7518] and RFC8037 [RFC8037] asymmetric key algorithms. Note: Unlike RFC8037 [RFC8037] JSF requires explicit Ed* algorithm names instead of \"EdDSA\".",
+              "enum": [
+                "RS256",
+                "RS384",
+                "RS512",
+                "PS256",
+                "PS384",
+                "PS512",
+                "ES256",
+                "ES384",
+                "ES512",
+                "Ed25519",
+                "Ed448",
+                "HS256",
+                "HS384",
+                "HS512"
+              ]
+            },
+            {
+              "type": "string",
+              "title": "Algorithm",
+              "description": "Signature algorithm. Note: If proprietary signature algorithms are added, they must be expressed as URIs.",
+              "format": "uri"
+            }
+          ]
+        },
+        "keyId": {
+          "type": "string",
+          "title": "Key ID",
+          "description": "Optional. Application specific string identifying the signature key."
+        },
+        "publicKey": {
+          "title": "Public key",
+          "description": "Optional. Public key object.",
+          "$ref": "#/definitions/publicKey"
+        },
+        "certificatePath": {
+          "type": "array",
+          "title": "Certificate path",
+          "description": "Optional. Sorted array of X.509 [RFC5280] certificates, where the first element must contain the signature certificate. The certificate path must be contiguous but is not required to be complete.",
+          "items": {
+            "type": "string"
+          }
+        },
+        "excludes": {
+          "type": "array",
+          "title": "Excludes",
+          "description": "Optional. Array holding the names of one or more application level properties that must be excluded from the signature process. Note that the \"excludes\" property itself, must also be excluded from the signature process. Since both the \"excludes\" property and the associated data it points to are unsigned, a conforming JSF implementation must provide options for specifying which properties to accept.",
+          "items": {
+            "type": "string"
+          }
+        },
+        "value": {
+          "type": "string",
+          "title": "Signature",
+          "description": "The signature data. Note that the binary representation must follow the JWA [RFC7518] specifications."
+        }
+      }
+    },
+    "keyType": {
+      "type": "string",
+      "title": "Key type",
+      "description": "Key type indicator.",
+      "enum": [
+        "EC",
+        "OKP",
+        "RSA"
+      ]
+    },
+    "publicKey": {
+      "title": "Public key",
+      "description": "Optional. Public key object.",
+      "type": "object",
+      "required": [
+        "kty"
+      ],
+      "additionalProperties": true,
+      "properties": {
+        "kty": {
+          "$ref": "#/definitions/keyType"
+        }
+      },
+      "allOf": [
+        {
+          "if": {
+            "properties": { "kty": { "const": "EC" } }
+          },
+          "then": {
+            "required": [
+              "kty",
+              "crv",
+              "x",
+              "y"
+            ],
+            "additionalProperties": false,
+            "properties": {
+              "kty": {
+                "$ref": "#/definitions/keyType"
+              },
+              "crv": {
+                "type": "string",
+                "title": "Curve name",
+                "description": "EC curve name.",
+                "enum": [
+                  "P-256",
+                  "P-384",
+                  "P-521"
+                ]
+              },
+              "x": {
+                "type": "string",
+                "title": "Coordinate",
+                "description": "EC curve point X. The length of this field must be the full size of a coordinate for the curve specified in the \"crv\" parameter. For example, if the value of \"crv\" is \"P-521\", the decoded argument must be 66 bytes."
+              },
+              "y": {
+                "type": "string",
+                "title": "Coordinate",
+                "description": "EC curve point Y. The length of this field must be the full size of a coordinate for the curve specified in the \"crv\" parameter. For example, if the value of \"crv\" is \"P-256\", the decoded argument must be 32 bytes."
+              }
+            }
+          }
+        },
+        {
+          "if": {
+            "properties": { "kty": { "const": "OKP" } }
+          },
+          "then": {
+            "required": [
+              "kty",
+              "crv",
+              "x"
+            ],
+            "additionalProperties": false,
+            "properties": {
+              "kty": {
+                "$ref": "#/definitions/keyType"
+              },
+              "crv": {
+                "type": "string",
+                "title": "Curve name",
+                "description": "EdDSA curve name.",
+                "enum": [
+                  "Ed25519",
+                  "Ed448"
+                ]
+              },
+              "x": {
+                "type": "string",
+                "title": "Coordinate",
+                "description": "EdDSA curve point X. The length of this field must be the full size of a coordinate for the curve specified in the \"crv\" parameter. For example, if the value of \"crv\" is \"Ed25519\", the decoded argument must be 32 bytes."
+              }
+            }
+          }
+        },
+        {
+          "if": {
+            "properties": { "kty": { "const": "RSA" } }
+          },
+          "then": {
+            "required": [
+              "kty",
+              "n",
+              "e"
+            ],
+            "additionalProperties": false,
+            "properties": {
+              "kty": {
+                "$ref": "#/definitions/keyType"
+              },
+              "n": {
+                "type": "string",
+                "title": "Modulus",
+                "description": "RSA modulus."
+              },
+              "e": {
+                "type": "string",
+                "title": "Exponent",
+                "description": "RSA exponent."
+              }
+            }
+          }
+        }
+      ]
+    }
+  }
+}
diff --git a/deps/npm/test/schemas/cyclonedx/spdx.schema.json b/deps/npm/test/schemas/cyclonedx/spdx.schema.json
new file mode 100644
index 00000000000000..f04d013c74c48d
--- /dev/null
+++ b/deps/npm/test/schemas/cyclonedx/spdx.schema.json
@@ -0,0 +1,621 @@
+{
+  "$schema": "http://json-schema.org/draft-07/schema#",
+  "$id": "http://cyclonedx.org/schema/spdx.schema.json",
+  "$comment": "v1.0-3.21",
+  "type": "string",
+  "enum": [
+    "0BSD",
+    "AAL",
+    "Abstyles",
+    "AdaCore-doc",
+    "Adobe-2006",
+    "Adobe-Glyph",
+    "ADSL",
+    "AFL-1.1",
+    "AFL-1.2",
+    "AFL-2.0",
+    "AFL-2.1",
+    "AFL-3.0",
+    "Afmparse",
+    "AGPL-1.0",
+    "AGPL-1.0-only",
+    "AGPL-1.0-or-later",
+    "AGPL-3.0",
+    "AGPL-3.0-only",
+    "AGPL-3.0-or-later",
+    "Aladdin",
+    "AMDPLPA",
+    "AML",
+    "AMPAS",
+    "ANTLR-PD",
+    "ANTLR-PD-fallback",
+    "Apache-1.0",
+    "Apache-1.1",
+    "Apache-2.0",
+    "APAFML",
+    "APL-1.0",
+    "App-s2p",
+    "APSL-1.0",
+    "APSL-1.1",
+    "APSL-1.2",
+    "APSL-2.0",
+    "Arphic-1999",
+    "Artistic-1.0",
+    "Artistic-1.0-cl8",
+    "Artistic-1.0-Perl",
+    "Artistic-2.0",
+    "ASWF-Digital-Assets-1.0",
+    "ASWF-Digital-Assets-1.1",
+    "Baekmuk",
+    "Bahyph",
+    "Barr",
+    "Beerware",
+    "Bitstream-Charter",
+    "Bitstream-Vera",
+    "BitTorrent-1.0",
+    "BitTorrent-1.1",
+    "blessing",
+    "BlueOak-1.0.0",
+    "Boehm-GC",
+    "Borceux",
+    "Brian-Gladman-3-Clause",
+    "BSD-1-Clause",
+    "BSD-2-Clause",
+    "BSD-2-Clause-FreeBSD",
+    "BSD-2-Clause-NetBSD",
+    "BSD-2-Clause-Patent",
+    "BSD-2-Clause-Views",
+    "BSD-3-Clause",
+    "BSD-3-Clause-Attribution",
+    "BSD-3-Clause-Clear",
+    "BSD-3-Clause-LBNL",
+    "BSD-3-Clause-Modification",
+    "BSD-3-Clause-No-Military-License",
+    "BSD-3-Clause-No-Nuclear-License",
+    "BSD-3-Clause-No-Nuclear-License-2014",
+    "BSD-3-Clause-No-Nuclear-Warranty",
+    "BSD-3-Clause-Open-MPI",
+    "BSD-4-Clause",
+    "BSD-4-Clause-Shortened",
+    "BSD-4-Clause-UC",
+    "BSD-4.3RENO",
+    "BSD-4.3TAHOE",
+    "BSD-Advertising-Acknowledgement",
+    "BSD-Attribution-HPND-disclaimer",
+    "BSD-Protection",
+    "BSD-Source-Code",
+    "BSL-1.0",
+    "BUSL-1.1",
+    "bzip2-1.0.5",
+    "bzip2-1.0.6",
+    "C-UDA-1.0",
+    "CAL-1.0",
+    "CAL-1.0-Combined-Work-Exception",
+    "Caldera",
+    "CATOSL-1.1",
+    "CC-BY-1.0",
+    "CC-BY-2.0",
+    "CC-BY-2.5",
+    "CC-BY-2.5-AU",
+    "CC-BY-3.0",
+    "CC-BY-3.0-AT",
+    "CC-BY-3.0-DE",
+    "CC-BY-3.0-IGO",
+    "CC-BY-3.0-NL",
+    "CC-BY-3.0-US",
+    "CC-BY-4.0",
+    "CC-BY-NC-1.0",
+    "CC-BY-NC-2.0",
+    "CC-BY-NC-2.5",
+    "CC-BY-NC-3.0",
+    "CC-BY-NC-3.0-DE",
+    "CC-BY-NC-4.0",
+    "CC-BY-NC-ND-1.0",
+    "CC-BY-NC-ND-2.0",
+    "CC-BY-NC-ND-2.5",
+    "CC-BY-NC-ND-3.0",
+    "CC-BY-NC-ND-3.0-DE",
+    "CC-BY-NC-ND-3.0-IGO",
+    "CC-BY-NC-ND-4.0",
+    "CC-BY-NC-SA-1.0",
+    "CC-BY-NC-SA-2.0",
+    "CC-BY-NC-SA-2.0-DE",
+    "CC-BY-NC-SA-2.0-FR",
+    "CC-BY-NC-SA-2.0-UK",
+    "CC-BY-NC-SA-2.5",
+    "CC-BY-NC-SA-3.0",
+    "CC-BY-NC-SA-3.0-DE",
+    "CC-BY-NC-SA-3.0-IGO",
+    "CC-BY-NC-SA-4.0",
+    "CC-BY-ND-1.0",
+    "CC-BY-ND-2.0",
+    "CC-BY-ND-2.5",
+    "CC-BY-ND-3.0",
+    "CC-BY-ND-3.0-DE",
+    "CC-BY-ND-4.0",
+    "CC-BY-SA-1.0",
+    "CC-BY-SA-2.0",
+    "CC-BY-SA-2.0-UK",
+    "CC-BY-SA-2.1-JP",
+    "CC-BY-SA-2.5",
+    "CC-BY-SA-3.0",
+    "CC-BY-SA-3.0-AT",
+    "CC-BY-SA-3.0-DE",
+    "CC-BY-SA-3.0-IGO",
+    "CC-BY-SA-4.0",
+    "CC-PDDC",
+    "CC0-1.0",
+    "CDDL-1.0",
+    "CDDL-1.1",
+    "CDL-1.0",
+    "CDLA-Permissive-1.0",
+    "CDLA-Permissive-2.0",
+    "CDLA-Sharing-1.0",
+    "CECILL-1.0",
+    "CECILL-1.1",
+    "CECILL-2.0",
+    "CECILL-2.1",
+    "CECILL-B",
+    "CECILL-C",
+    "CERN-OHL-1.1",
+    "CERN-OHL-1.2",
+    "CERN-OHL-P-2.0",
+    "CERN-OHL-S-2.0",
+    "CERN-OHL-W-2.0",
+    "CFITSIO",
+    "checkmk",
+    "ClArtistic",
+    "Clips",
+    "CMU-Mach",
+    "CNRI-Jython",
+    "CNRI-Python",
+    "CNRI-Python-GPL-Compatible",
+    "COIL-1.0",
+    "Community-Spec-1.0",
+    "Condor-1.1",
+    "copyleft-next-0.3.0",
+    "copyleft-next-0.3.1",
+    "Cornell-Lossless-JPEG",
+    "CPAL-1.0",
+    "CPL-1.0",
+    "CPOL-1.02",
+    "Crossword",
+    "CrystalStacker",
+    "CUA-OPL-1.0",
+    "Cube",
+    "curl",
+    "D-FSL-1.0",
+    "diffmark",
+    "DL-DE-BY-2.0",
+    "DOC",
+    "Dotseqn",
+    "DRL-1.0",
+    "DSDP",
+    "dtoa",
+    "dvipdfm",
+    "ECL-1.0",
+    "ECL-2.0",
+    "eCos-2.0",
+    "EFL-1.0",
+    "EFL-2.0",
+    "eGenix",
+    "Elastic-2.0",
+    "Entessa",
+    "EPICS",
+    "EPL-1.0",
+    "EPL-2.0",
+    "ErlPL-1.1",
+    "etalab-2.0",
+    "EUDatagrid",
+    "EUPL-1.0",
+    "EUPL-1.1",
+    "EUPL-1.2",
+    "Eurosym",
+    "Fair",
+    "FDK-AAC",
+    "Frameworx-1.0",
+    "FreeBSD-DOC",
+    "FreeImage",
+    "FSFAP",
+    "FSFUL",
+    "FSFULLR",
+    "FSFULLRWD",
+    "FTL",
+    "GD",
+    "GFDL-1.1",
+    "GFDL-1.1-invariants-only",
+    "GFDL-1.1-invariants-or-later",
+    "GFDL-1.1-no-invariants-only",
+    "GFDL-1.1-no-invariants-or-later",
+    "GFDL-1.1-only",
+    "GFDL-1.1-or-later",
+    "GFDL-1.2",
+    "GFDL-1.2-invariants-only",
+    "GFDL-1.2-invariants-or-later",
+    "GFDL-1.2-no-invariants-only",
+    "GFDL-1.2-no-invariants-or-later",
+    "GFDL-1.2-only",
+    "GFDL-1.2-or-later",
+    "GFDL-1.3",
+    "GFDL-1.3-invariants-only",
+    "GFDL-1.3-invariants-or-later",
+    "GFDL-1.3-no-invariants-only",
+    "GFDL-1.3-no-invariants-or-later",
+    "GFDL-1.3-only",
+    "GFDL-1.3-or-later",
+    "Giftware",
+    "GL2PS",
+    "Glide",
+    "Glulxe",
+    "GLWTPL",
+    "gnuplot",
+    "GPL-1.0",
+    "GPL-1.0+",
+    "GPL-1.0-only",
+    "GPL-1.0-or-later",
+    "GPL-2.0",
+    "GPL-2.0+",
+    "GPL-2.0-only",
+    "GPL-2.0-or-later",
+    "GPL-2.0-with-autoconf-exception",
+    "GPL-2.0-with-bison-exception",
+    "GPL-2.0-with-classpath-exception",
+    "GPL-2.0-with-font-exception",
+    "GPL-2.0-with-GCC-exception",
+    "GPL-3.0",
+    "GPL-3.0+",
+    "GPL-3.0-only",
+    "GPL-3.0-or-later",
+    "GPL-3.0-with-autoconf-exception",
+    "GPL-3.0-with-GCC-exception",
+    "Graphics-Gems",
+    "gSOAP-1.3b",
+    "HaskellReport",
+    "Hippocratic-2.1",
+    "HP-1986",
+    "HPND",
+    "HPND-export-US",
+    "HPND-Markus-Kuhn",
+    "HPND-sell-variant",
+    "HPND-sell-variant-MIT-disclaimer",
+    "HTMLTIDY",
+    "IBM-pibs",
+    "ICU",
+    "IEC-Code-Components-EULA",
+    "IJG",
+    "IJG-short",
+    "ImageMagick",
+    "iMatix",
+    "Imlib2",
+    "Info-ZIP",
+    "Inner-Net-2.0",
+    "Intel",
+    "Intel-ACPI",
+    "Interbase-1.0",
+    "IPA",
+    "IPL-1.0",
+    "ISC",
+    "Jam",
+    "JasPer-2.0",
+    "JPL-image",
+    "JPNIC",
+    "JSON",
+    "Kazlib",
+    "Knuth-CTAN",
+    "LAL-1.2",
+    "LAL-1.3",
+    "Latex2e",
+    "Latex2e-translated-notice",
+    "Leptonica",
+    "LGPL-2.0",
+    "LGPL-2.0+",
+    "LGPL-2.0-only",
+    "LGPL-2.0-or-later",
+    "LGPL-2.1",
+    "LGPL-2.1+",
+    "LGPL-2.1-only",
+    "LGPL-2.1-or-later",
+    "LGPL-3.0",
+    "LGPL-3.0+",
+    "LGPL-3.0-only",
+    "LGPL-3.0-or-later",
+    "LGPLLR",
+    "Libpng",
+    "libpng-2.0",
+    "libselinux-1.0",
+    "libtiff",
+    "libutil-David-Nugent",
+    "LiLiQ-P-1.1",
+    "LiLiQ-R-1.1",
+    "LiLiQ-Rplus-1.1",
+    "Linux-man-pages-1-para",
+    "Linux-man-pages-copyleft",
+    "Linux-man-pages-copyleft-2-para",
+    "Linux-man-pages-copyleft-var",
+    "Linux-OpenIB",
+    "LOOP",
+    "LPL-1.0",
+    "LPL-1.02",
+    "LPPL-1.0",
+    "LPPL-1.1",
+    "LPPL-1.2",
+    "LPPL-1.3a",
+    "LPPL-1.3c",
+    "LZMA-SDK-9.11-to-9.20",
+    "LZMA-SDK-9.22",
+    "MakeIndex",
+    "Martin-Birgmeier",
+    "metamail",
+    "Minpack",
+    "MirOS",
+    "MIT",
+    "MIT-0",
+    "MIT-advertising",
+    "MIT-CMU",
+    "MIT-enna",
+    "MIT-feh",
+    "MIT-Festival",
+    "MIT-Modern-Variant",
+    "MIT-open-group",
+    "MIT-Wu",
+    "MITNFA",
+    "Motosoto",
+    "mpi-permissive",
+    "mpich2",
+    "MPL-1.0",
+    "MPL-1.1",
+    "MPL-2.0",
+    "MPL-2.0-no-copyleft-exception",
+    "mplus",
+    "MS-LPL",
+    "MS-PL",
+    "MS-RL",
+    "MTLL",
+    "MulanPSL-1.0",
+    "MulanPSL-2.0",
+    "Multics",
+    "Mup",
+    "NAIST-2003",
+    "NASA-1.3",
+    "Naumen",
+    "NBPL-1.0",
+    "NCGL-UK-2.0",
+    "NCSA",
+    "Net-SNMP",
+    "NetCDF",
+    "Newsletr",
+    "NGPL",
+    "NICTA-1.0",
+    "NIST-PD",
+    "NIST-PD-fallback",
+    "NIST-Software",
+    "NLOD-1.0",
+    "NLOD-2.0",
+    "NLPL",
+    "Nokia",
+    "NOSL",
+    "Noweb",
+    "NPL-1.0",
+    "NPL-1.1",
+    "NPOSL-3.0",
+    "NRL",
+    "NTP",
+    "NTP-0",
+    "Nunit",
+    "O-UDA-1.0",
+    "OCCT-PL",
+    "OCLC-2.0",
+    "ODbL-1.0",
+    "ODC-By-1.0",
+    "OFFIS",
+    "OFL-1.0",
+    "OFL-1.0-no-RFN",
+    "OFL-1.0-RFN",
+    "OFL-1.1",
+    "OFL-1.1-no-RFN",
+    "OFL-1.1-RFN",
+    "OGC-1.0",
+    "OGDL-Taiwan-1.0",
+    "OGL-Canada-2.0",
+    "OGL-UK-1.0",
+    "OGL-UK-2.0",
+    "OGL-UK-3.0",
+    "OGTSL",
+    "OLDAP-1.1",
+    "OLDAP-1.2",
+    "OLDAP-1.3",
+    "OLDAP-1.4",
+    "OLDAP-2.0",
+    "OLDAP-2.0.1",
+    "OLDAP-2.1",
+    "OLDAP-2.2",
+    "OLDAP-2.2.1",
+    "OLDAP-2.2.2",
+    "OLDAP-2.3",
+    "OLDAP-2.4",
+    "OLDAP-2.5",
+    "OLDAP-2.6",
+    "OLDAP-2.7",
+    "OLDAP-2.8",
+    "OLFL-1.3",
+    "OML",
+    "OpenPBS-2.3",
+    "OpenSSL",
+    "OPL-1.0",
+    "OPL-UK-3.0",
+    "OPUBL-1.0",
+    "OSET-PL-2.1",
+    "OSL-1.0",
+    "OSL-1.1",
+    "OSL-2.0",
+    "OSL-2.1",
+    "OSL-3.0",
+    "Parity-6.0.0",
+    "Parity-7.0.0",
+    "PDDL-1.0",
+    "PHP-3.0",
+    "PHP-3.01",
+    "Plexus",
+    "PolyForm-Noncommercial-1.0.0",
+    "PolyForm-Small-Business-1.0.0",
+    "PostgreSQL",
+    "PSF-2.0",
+    "psfrag",
+    "psutils",
+    "Python-2.0",
+    "Python-2.0.1",
+    "Qhull",
+    "QPL-1.0",
+    "QPL-1.0-INRIA-2004",
+    "Rdisc",
+    "RHeCos-1.1",
+    "RPL-1.1",
+    "RPL-1.5",
+    "RPSL-1.0",
+    "RSA-MD",
+    "RSCPL",
+    "Ruby",
+    "SAX-PD",
+    "Saxpath",
+    "SCEA",
+    "SchemeReport",
+    "Sendmail",
+    "Sendmail-8.23",
+    "SGI-B-1.0",
+    "SGI-B-1.1",
+    "SGI-B-2.0",
+    "SGP4",
+    "SHL-0.5",
+    "SHL-0.51",
+    "SimPL-2.0",
+    "SISSL",
+    "SISSL-1.2",
+    "Sleepycat",
+    "SMLNJ",
+    "SMPPL",
+    "SNIA",
+    "snprintf",
+    "Spencer-86",
+    "Spencer-94",
+    "Spencer-99",
+    "SPL-1.0",
+    "SSH-OpenSSH",
+    "SSH-short",
+    "SSPL-1.0",
+    "StandardML-NJ",
+    "SugarCRM-1.1.3",
+    "SunPro",
+    "SWL",
+    "Symlinks",
+    "TAPR-OHL-1.0",
+    "TCL",
+    "TCP-wrappers",
+    "TermReadKey",
+    "TMate",
+    "TORQUE-1.1",
+    "TOSL",
+    "TPDL",
+    "TPL-1.0",
+    "TTWL",
+    "TU-Berlin-1.0",
+    "TU-Berlin-2.0",
+    "UCAR",
+    "UCL-1.0",
+    "Unicode-DFS-2015",
+    "Unicode-DFS-2016",
+    "Unicode-TOU",
+    "UnixCrypt",
+    "Unlicense",
+    "UPL-1.0",
+    "Vim",
+    "VOSTROM",
+    "VSL-1.0",
+    "W3C",
+    "W3C-19980720",
+    "W3C-20150513",
+    "w3m",
+    "Watcom-1.0",
+    "Widget-Workshop",
+    "Wsuipa",
+    "WTFPL",
+    "wxWindows",
+    "X11",
+    "X11-distribute-modifications-variant",
+    "Xdebug-1.03",
+    "Xerox",
+    "Xfig",
+    "XFree86-1.1",
+    "xinetd",
+    "xlock",
+    "Xnet",
+    "xpp",
+    "XSkat",
+    "YPL-1.0",
+    "YPL-1.1",
+    "Zed",
+    "Zend-2.0",
+    "Zimbra-1.3",
+    "Zimbra-1.4",
+    "Zlib",
+    "zlib-acknowledgement",
+    "ZPL-1.1",
+    "ZPL-2.0",
+    "ZPL-2.1",
+    "389-exception",
+    "Asterisk-exception",
+    "Autoconf-exception-2.0",
+    "Autoconf-exception-3.0",
+    "Autoconf-exception-generic",
+    "Autoconf-exception-macro",
+    "Bison-exception-2.2",
+    "Bootloader-exception",
+    "Classpath-exception-2.0",
+    "CLISP-exception-2.0",
+    "cryptsetup-OpenSSL-exception",
+    "DigiRule-FOSS-exception",
+    "eCos-exception-2.0",
+    "Fawkes-Runtime-exception",
+    "FLTK-exception",
+    "Font-exception-2.0",
+    "freertos-exception-2.0",
+    "GCC-exception-2.0",
+    "GCC-exception-3.1",
+    "GNAT-exception",
+    "gnu-javamail-exception",
+    "GPL-3.0-interface-exception",
+    "GPL-3.0-linking-exception",
+    "GPL-3.0-linking-source-exception",
+    "GPL-CC-1.0",
+    "GStreamer-exception-2005",
+    "GStreamer-exception-2008",
+    "i2p-gpl-java-exception",
+    "KiCad-libraries-exception",
+    "LGPL-3.0-linking-exception",
+    "libpri-OpenH323-exception",
+    "Libtool-exception",
+    "Linux-syscall-note",
+    "LLGPL",
+    "LLVM-exception",
+    "LZMA-exception",
+    "mif-exception",
+    "Nokia-Qt-exception-1.1",
+    "OCaml-LGPL-linking-exception",
+    "OCCT-exception-1.0",
+    "OpenJDK-assembly-exception-1.0",
+    "openvpn-openssl-exception",
+    "PS-or-PDF-font-exception-20170817",
+    "QPL-1.0-INRIA-2004-exception",
+    "Qt-GPL-exception-1.0",
+    "Qt-LGPL-exception-1.1",
+    "Qwt-exception-1.0",
+    "SHL-2.0",
+    "SHL-2.1",
+    "SWI-exception",
+    "Swift-exception",
+    "u-boot-exception-2.0",
+    "Universal-FOSS-exception-1.0",
+    "vsftpd-openssl-exception",
+    "WxWindows-exception-3.1",
+    "x11vnc-openssl-exception"
+  ]
+}
diff --git a/deps/npm/test/schemas/spdx/spdx-2.3.schema.json b/deps/npm/test/schemas/spdx/spdx-2.3.schema.json
new file mode 100644
index 00000000000000..ee61e6686e885f
--- /dev/null
+++ b/deps/npm/test/schemas/spdx/spdx-2.3.schema.json
@@ -0,0 +1,740 @@
+{
+  "$schema" : "http://json-schema.org/draft-07/schema#",
+  "$id" : "http://spdx.org/rdf/terms/2.3",
+  "title" : "SPDX 2.3",
+  "type" : "object",
+  "properties" : {
+    "SPDXID" : {
+      "type" : "string",
+      "description" : "Uniquely identify any element in an SPDX document which may be referenced by other elements."
+    },
+    "annotations" : {
+      "description" : "Provide additional information about an SpdxElement.",
+      "type" : "array",
+      "items" : {
+        "type" : "object",
+        "properties" : {
+          "annotationDate" : {
+            "description" : "Identify when the comment was made. This is to be specified according to the combined date and time in the UTC format, as specified in the ISO 8601 standard.",
+            "type" : "string"
+          },
+          "annotationType" : {
+            "description" : "Type of the annotation.",
+            "type" : "string",
+            "enum" : [ "OTHER", "REVIEW" ]
+          },
+          "annotator" : {
+            "description" : "This field identifies the person, organization, or tool that has commented on a file, package, snippet, or the entire document.",
+            "type" : "string"
+          },
+          "comment" : {
+            "type" : "string"
+          }
+        },
+        "required" : [ "annotationDate", "annotationType", "annotator", "comment" ],
+        "additionalProperties" : false,
+        "description" : "An Annotation is a comment on an SpdxItem by an agent."
+      }
+    },
+    "comment" : {
+      "type" : "string"
+    },
+    "creationInfo" : {
+      "type" : "object",
+      "properties" : {
+        "comment" : {
+          "type" : "string"
+        },
+        "created" : {
+          "description" : "Identify when the SPDX document was originally created. The date is to be specified according to combined date and time in UTC format as specified in ISO 8601 standard.",
+          "type" : "string"
+        },
+        "creators" : {
+          "description" : "Identify who (or what, in the case of a tool) created the SPDX document. If the SPDX document was created by an individual, indicate the person's name. If the SPDX document was created on behalf of a company or organization, indicate the entity name. If the SPDX document was created using a software tool, indicate the name and version for that tool. If multiple participants or tools were involved, use multiple instances of this field. Person name or organization name may be designated as “anonymous” if appropriate.",
+          "minItems" : 1,
+          "type" : "array",
+          "items" : {
+            "description" : "Identify who (or what, in the case of a tool) created the SPDX document. If the SPDX document was created by an individual, indicate the person's name. If the SPDX document was created on behalf of a company or organization, indicate the entity name. If the SPDX document was created using a software tool, indicate the name and version for that tool. If multiple participants or tools were involved, use multiple instances of this field. Person name or organization name may be designated as “anonymous” if appropriate.",
+            "type" : "string"
+          }
+        },
+        "licenseListVersion" : {
+          "description" : "An optional field for creators of the SPDX file to provide the version of the SPDX License List used when the SPDX file was created.",
+          "type" : "string"
+        }
+      },
+      "required" : [ "created", "creators" ],
+      "additionalProperties" : false,
+      "description" : "One instance is required for each SPDX file produced. It provides the necessary information for forward and backward compatibility for processing tools."
+    },
+    "dataLicense" : {
+      "description" : "License expression for dataLicense. See SPDX Annex D for the license expression syntax.  Compliance with the SPDX specification includes populating the SPDX fields therein with data related to such fields (\"SPDX-Metadata\"). The SPDX specification contains numerous fields where an SPDX document creator may provide relevant explanatory text in SPDX-Metadata. Without opining on the lawfulness of \"database rights\" (in jurisdictions where applicable), such explanatory text is copyrightable subject matter in most Berne Convention countries. By using the SPDX specification, or any portion hereof, you hereby agree that any copyright rights (as determined by your jurisdiction) in any SPDX-Metadata, including without limitation explanatory text, shall be subject to the terms of the Creative Commons CC0 1.0 Universal license. For SPDX-Metadata not containing any copyright rights, you hereby agree and acknowledge that the SPDX-Metadata is provided to you \"as-is\" and without any representations or warranties of any kind concerning the SPDX-Metadata, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non-infringement, or the absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law.",
+      "type" : "string"
+    },
+    "externalDocumentRefs" : {
+      "description" : "Identify any external SPDX documents referenced within this SPDX document.",
+      "type" : "array",
+      "items" : {
+        "type" : "object",
+        "properties" : {
+          "checksum" : {
+            "type" : "object",
+            "properties" : {
+              "algorithm" : {
+                "description" : "Identifies the algorithm used to produce the subject Checksum. Currently, SHA-1 is the only supported algorithm. It is anticipated that other algorithms will be supported at a later time.",
+                "type" : "string",
+                "enum" : [ "SHA1", "BLAKE3", "SHA3-384", "SHA256", "SHA384", "BLAKE2b-512", "BLAKE2b-256", "SHA3-512", "MD2", "ADLER32", "MD4", "SHA3-256", "BLAKE2b-384", "SHA512", "MD6", "MD5", "SHA224" ]
+              },
+              "checksumValue" : {
+                "description" : "The checksumValue property provides a lower case hexidecimal encoded digest value produced using a specific algorithm.",
+                "type" : "string"
+              }
+            },
+            "required" : [ "algorithm", "checksumValue" ],
+            "additionalProperties" : false,
+            "description" : "A Checksum is value that allows the contents of a file to be authenticated. Even small changes to the content of the file will change its checksum. This class allows the results of a variety of checksum and cryptographic message digest algorithms to be represented."
+          },
+          "externalDocumentId" : {
+            "description" : "externalDocumentId is a string containing letters, numbers, ., - and/or + which uniquely identifies an external document within this document.",
+            "type" : "string"
+          },
+          "spdxDocument" : {
+            "description" : "SPDX ID for SpdxDocument.  A property containing an SPDX document.",
+            "type" : "string"
+          }
+        },
+        "required" : [ "checksum", "externalDocumentId", "spdxDocument" ],
+        "additionalProperties" : false,
+        "description" : "Information about an external SPDX document reference including the checksum. This allows for verification of the external references."
+      }
+    },
+    "hasExtractedLicensingInfos" : {
+      "description" : "Indicates that a particular ExtractedLicensingInfo was defined in the subject SpdxDocument.",
+      "type" : "array",
+      "items" : {
+        "type" : "object",
+        "properties" : {
+          "comment" : {
+            "type" : "string"
+          },
+          "crossRefs" : {
+            "description" : "Cross Reference Detail for a license SeeAlso URL",
+            "type" : "array",
+            "items" : {
+              "type" : "object",
+              "properties" : {
+                "isLive" : {
+                  "description" : "Indicate a URL is still a live accessible location on the public internet",
+                  "type" : "boolean"
+                },
+                "isValid" : {
+                  "description" : "True if the URL is a valid well formed URL",
+                  "type" : "boolean"
+                },
+                "isWayBackLink" : {
+                  "description" : "True if the License SeeAlso URL points to a Wayback archive",
+                  "type" : "boolean"
+                },
+                "match" : {
+                  "description" : "Status of a License List SeeAlso URL reference if it refers to a website that matches the license text.",
+                  "type" : "string"
+                },
+                "order" : {
+                  "description" : "The ordinal order of this element within a list",
+                  "type" : "integer"
+                },
+                "timestamp" : {
+                  "description" : "Timestamp",
+                  "type" : "string"
+                },
+                "url" : {
+                  "description" : "URL Reference",
+                  "type" : "string"
+                }
+              },
+              "required" : [ "url" ],
+              "additionalProperties" : false,
+              "description" : "Cross reference details for the a URL reference"
+            }
+          },
+          "extractedText" : {
+            "description" : "Provide a copy of the actual text of the license reference extracted from the package, file or snippet that is associated with the License Identifier to aid in future analysis.",
+            "type" : "string"
+          },
+          "licenseId" : {
+            "description" : "A human readable short form license identifier for a license. The license ID is either on the standard license list or the form \"LicenseRef-[idString]\" where [idString] is a unique string containing letters, numbers, \".\" or \"-\".  When used within a license expression, the license ID can optionally include a reference to an external document in the form \"DocumentRef-[docrefIdString]:LicenseRef-[idString]\" where docRefIdString is an ID for an external document reference.",
+            "type" : "string"
+          },
+          "name" : {
+            "description" : "Identify name of this SpdxElement.",
+            "type" : "string"
+          },
+          "seeAlsos" : {
+            "type" : "array",
+            "items" : {
+              "type" : "string"
+            }
+          }
+        },
+        "required" : [ "extractedText", "licenseId" ],
+        "additionalProperties" : false,
+        "description" : "An ExtractedLicensingInfo represents a license or licensing notice that was found in a package, file or snippet. Any license text that is recognized as a license may be represented as a License rather than an ExtractedLicensingInfo."
+      }
+    },
+    "name" : {
+      "description" : "Identify name of this SpdxElement.",
+      "type" : "string"
+    },
+    "revieweds" : {
+      "description" : "Reviewed",
+      "type" : "array",
+      "items" : {
+        "type" : "object",
+        "properties" : {
+          "comment" : {
+            "type" : "string"
+          },
+          "reviewDate" : {
+            "description" : "The date and time at which the SpdxDocument was reviewed. This value must be in UTC and have 'Z' as its timezone indicator.",
+            "type" : "string"
+          },
+          "reviewer" : {
+            "description" : "The name and, optionally, contact information of the person who performed the review. Values of this property must conform to the agent and tool syntax.  The reviewer property is deprecated in favor of Annotation with an annotationType review.",
+            "type" : "string"
+          }
+        },
+        "required" : [ "reviewDate" ],
+        "additionalProperties" : false,
+        "description" : "This class has been deprecated in favor of an Annotation with an Annotation type of review."
+      }
+    },
+    "spdxVersion" : {
+      "description" : "Provide a reference number that can be used to understand how to parse and interpret the rest of the file. It will enable both future changes to the specification and to support backward compatibility. The version number consists of a major and minor version indicator. The major field will be incremented when incompatible changes between versions are made (one or more sections are created, modified or deleted). The minor field will be incremented when backwards compatible changes are made.",
+      "type" : "string"
+    },
+    "documentNamespace" : {
+      "type" : "string",
+      "description" : "The URI provides an unambiguous mechanism for other SPDX documents to reference SPDX elements within this SPDX document."
+    },
+    "documentDescribes" : {
+      "description" : "Packages, files and/or Snippets described by this SPDX document",
+      "type" : "array",
+      "items" : {
+        "type" : "string",
+        "description" : "SPDX ID for each Package, File, or Snippet."
+      }
+    },
+    "packages" : {
+      "description" : "Packages referenced in the SPDX document",
+      "type" : "array",
+      "items" : {
+        "type" : "object",
+        "properties" : {
+          "SPDXID" : {
+            "type" : "string",
+            "description" : "Uniquely identify any element in an SPDX document which may be referenced by other elements."
+          },
+          "annotations" : {
+            "description" : "Provide additional information about an SpdxElement.",
+            "type" : "array",
+            "items" : {
+              "type" : "object",
+              "properties" : {
+                "annotationDate" : {
+                  "description" : "Identify when the comment was made. This is to be specified according to the combined date and time in the UTC format, as specified in the ISO 8601 standard.",
+                  "type" : "string"
+                },
+                "annotationType" : {
+                  "description" : "Type of the annotation.",
+                  "type" : "string",
+                  "enum" : [ "OTHER", "REVIEW" ]
+                },
+                "annotator" : {
+                  "description" : "This field identifies the person, organization, or tool that has commented on a file, package, snippet, or the entire document.",
+                  "type" : "string"
+                },
+                "comment" : {
+                  "type" : "string"
+                }
+              },
+              "required" : [ "annotationDate", "annotationType", "annotator", "comment" ],
+              "additionalProperties" : false,
+              "description" : "An Annotation is a comment on an SpdxItem by an agent."
+            }
+          },
+          "attributionTexts" : {
+            "description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConculded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
+            "type" : "array",
+            "items" : {
+              "description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConculded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
+              "type" : "string"
+            }
+          },
+          "builtDate" : {
+            "description" : "This field provides a place for recording the actual date the package was built.",
+            "type" : "string"
+          },
+          "checksums" : {
+            "description" : "The checksum property provides a mechanism that can be used to verify that the contents of a File or Package have not changed.",
+            "type" : "array",
+            "items" : {
+              "type" : "object",
+              "properties" : {
+                "algorithm" : {
+                  "description" : "Identifies the algorithm used to produce the subject Checksum. Currently, SHA-1 is the only supported algorithm. It is anticipated that other algorithms will be supported at a later time.",
+                  "type" : "string",
+                  "enum" : [ "SHA1", "BLAKE3", "SHA3-384", "SHA256", "SHA384", "BLAKE2b-512", "BLAKE2b-256", "SHA3-512", "MD2", "ADLER32", "MD4", "SHA3-256", "BLAKE2b-384", "SHA512", "MD6", "MD5", "SHA224" ]
+                },
+                "checksumValue" : {
+                  "description" : "The checksumValue property provides a lower case hexidecimal encoded digest value produced using a specific algorithm.",
+                  "type" : "string"
+                }
+              },
+              "required" : [ "algorithm", "checksumValue" ],
+              "additionalProperties" : false,
+              "description" : "A Checksum is value that allows the contents of a file to be authenticated. Even small changes to the content of the file will change its checksum. This class allows the results of a variety of checksum and cryptographic message digest algorithms to be represented."
+            }
+          },
+          "comment" : {
+            "type" : "string"
+          },
+          "copyrightText" : {
+            "description" : "The text of copyright declarations recited in the package, file or snippet.\n\nIf the copyrightText field is not present, it implies an equivalent meaning to NOASSERTION.",
+            "type" : "string"
+          },
+          "description" : {
+            "description" : "Provides a detailed description of the package.",
+            "type" : "string"
+          },
+          "downloadLocation" : {
+            "description" : "The URI at which this package is available for download. Private (i.e., not publicly reachable) URIs are acceptable as values of this property. The values http://spdx.org/rdf/terms#none and http://spdx.org/rdf/terms#noassertion may be used to specify that the package is not downloadable or that no attempt was made to determine its download location, respectively.",
+            "type" : "string"
+          },
+          "externalRefs" : {
+            "description" : "An External Reference allows a Package to reference an external source of additional information, metadata, enumerations, asset identifiers, or downloadable content believed to be relevant to the Package.",
+            "type" : "array",
+            "items" : {
+              "type" : "object",
+              "properties" : {
+                "comment" : {
+                  "type" : "string"
+                },
+                "referenceCategory" : {
+                  "description" : "Category for the external reference",
+                  "type" : "string",
+                  "enum" : [ "OTHER", "PERSISTENT-ID", "SECURITY", "PACKAGE-MANAGER" ]
+                },
+                "referenceLocator" : {
+                  "description" : "The unique string with no spaces necessary to access the package-specific information, metadata, or content within the target location. The format of the locator is subject to constraints defined by the .",
+                  "type" : "string"
+                },
+                "referenceType" : {
+                  "description" : "Type of the external reference. These are definined in an appendix in the SPDX specification.",
+                  "type" : "string"
+                }
+              },
+              "required" : [ "referenceCategory", "referenceLocator", "referenceType" ],
+              "additionalProperties" : false,
+              "description" : "An External Reference allows a Package to reference an external source of additional information, metadata, enumerations, asset identifiers, or downloadable content believed to be relevant to the Package."
+            }
+          },
+          "filesAnalyzed" : {
+            "description" : "Indicates whether the file content of this package has been available for or subjected to analysis when creating the SPDX document. If false indicates packages that represent metadata or URI references to a project, product, artifact, distribution or a component. If set to false, the package must not contain any files.",
+            "type" : "boolean"
+          },
+          "hasFiles" : {
+            "description" : "Indicates that a particular file belongs to a package.",
+            "type" : "array",
+            "items" : {
+              "description" : "SPDX ID for File.  Indicates that a particular file belongs to a package.",
+              "type" : "string"
+            }
+          },
+          "homepage" : {
+            "type" : "string"
+          },
+          "licenseComments" : {
+            "description" : "The licenseComments property allows the preparer of the SPDX document to describe why the licensing in spdx:licenseConcluded was chosen.",
+            "type" : "string"
+          },
+          "licenseConcluded" : {
+            "description" : "License expression for licenseConcluded. See SPDX Annex D for the license expression syntax.  The licensing that the preparer of this SPDX document has concluded, based on the evidence, actually applies to the SPDX Item.\n\nIf the licenseConcluded field is not present for an SPDX Item, it implies an equivalent meaning to NOASSERTION.",
+            "type" : "string"
+          },
+          "licenseDeclared" : {
+            "description" : "License expression for licenseDeclared. See SPDX Annex D for the license expression syntax.  The licensing that the creators of the software in the package, or the packager, have declared. Declarations by the original software creator should be preferred, if they exist.",
+            "type" : "string"
+          },
+          "licenseInfoFromFiles" : {
+            "description" : "The licensing information that was discovered directly within the package. There will be an instance of this property for each distinct value of alllicenseInfoInFile properties of all files contained in the package.\n\nIf the licenseInfoFromFiles field is not present for a package and filesAnalyzed property for that same pacakge is true or omitted, it implies an equivalent meaning to NOASSERTION.",
+            "type" : "array",
+            "items" : {
+              "description" : "License expression for licenseInfoFromFiles. See SPDX Annex D for the license expression syntax.  The licensing information that was discovered directly within the package. There will be an instance of this property for each distinct value of alllicenseInfoInFile properties of all files contained in the package.\n\nIf the licenseInfoFromFiles field is not present for a package and filesAnalyzed property for that same pacakge is true or omitted, it implies an equivalent meaning to NOASSERTION.",
+              "type" : "string"
+            }
+          },
+          "name" : {
+            "description" : "Identify name of this SpdxElement.",
+            "type" : "string"
+          },
+          "originator" : {
+            "description" : "The name and, optionally, contact information of the person or organization that originally created the package. Values of this property must conform to the agent and tool syntax.",
+            "type" : "string"
+          },
+          "packageFileName" : {
+            "description" : "The base name of the package file name. For example, zlib-1.2.5.tar.gz.",
+            "type" : "string"
+          },
+          "packageVerificationCode" : {
+            "type" : "object",
+            "properties" : {
+              "packageVerificationCodeExcludedFiles" : {
+                "description" : "A file that was excluded when calculating the package verification code. This is usually a file containing SPDX data regarding the package. If a package contains more than one SPDX file all SPDX files must be excluded from the package verification code. If this is not done it would be impossible to correctly calculate the verification codes in both files.",
+                "type" : "array",
+                "items" : {
+                  "description" : "A file that was excluded when calculating the package verification code. This is usually a file containing SPDX data regarding the package. If a package contains more than one SPDX file all SPDX files must be excluded from the package verification code. If this is not done it would be impossible to correctly calculate the verification codes in both files.",
+                  "type" : "string"
+                }
+              },
+              "packageVerificationCodeValue" : {
+                "description" : "The actual package verification code as a hex encoded value.",
+                "type" : "string"
+              }
+            },
+            "required" : [ "packageVerificationCodeValue" ],
+            "additionalProperties" : false,
+            "description" : "A manifest based verification code (the algorithm is defined in section 4.7 of the full specification) of the SPDX Item. This allows consumers of this data and/or database to determine if an SPDX item they have in hand is identical to the SPDX item from which the data was produced. This algorithm works even if the SPDX document is included in the SPDX item."
+          },
+          "primaryPackagePurpose" : {
+            "description" : "This field provides information about the primary purpose of the identified package. Package Purpose is intrinsic to how the package is being used rather than the content of the package.",
+            "type" : "string",
+            "enum" : [ "OTHER", "INSTALL", "ARCHIVE", "FIRMWARE", "APPLICATION", "FRAMEWORK", "LIBRARY", "CONTAINER", "SOURCE", "DEVICE", "OPERATING_SYSTEM", "FILE" ]
+          },
+          "releaseDate" : {
+            "description" : "This field provides a place for recording the date the package was released.",
+            "type" : "string"
+          },
+          "sourceInfo" : {
+            "description" : "Allows the producer(s) of the SPDX document to describe how the package was acquired and/or changed from the original source.",
+            "type" : "string"
+          },
+          "summary" : {
+            "description" : "Provides a short description of the package.",
+            "type" : "string"
+          },
+          "supplier" : {
+            "description" : "The name and, optionally, contact information of the person or organization who was the immediate supplier of this package to the recipient. The supplier may be different than originator when the software has been repackaged. Values of this property must conform to the agent and tool syntax.",
+            "type" : "string"
+          },
+          "validUntilDate" : {
+            "description" : "This field provides a place for recording the end of the support period for a package from the supplier.",
+            "type" : "string"
+          },
+          "versionInfo" : {
+            "description" : "Provides an indication of the version of the package that is described by this SpdxDocument.",
+            "type" : "string"
+          }
+        },
+        "required" : [ "SPDXID", "downloadLocation", "name" ],
+        "additionalProperties" : false
+      }
+    },
+    "files" : {
+      "description" : "Files referenced in the SPDX document",
+      "type" : "array",
+      "items" : {
+        "type" : "object",
+        "properties" : {
+          "SPDXID" : {
+            "type" : "string",
+            "description" : "Uniquely identify any element in an SPDX document which may be referenced by other elements."
+          },
+          "annotations" : {
+            "description" : "Provide additional information about an SpdxElement.",
+            "type" : "array",
+            "items" : {
+              "type" : "object",
+              "properties" : {
+                "annotationDate" : {
+                  "description" : "Identify when the comment was made. This is to be specified according to the combined date and time in the UTC format, as specified in the ISO 8601 standard.",
+                  "type" : "string"
+                },
+                "annotationType" : {
+                  "description" : "Type of the annotation.",
+                  "type" : "string",
+                  "enum" : [ "OTHER", "REVIEW" ]
+                },
+                "annotator" : {
+                  "description" : "This field identifies the person, organization, or tool that has commented on a file, package, snippet, or the entire document.",
+                  "type" : "string"
+                },
+                "comment" : {
+                  "type" : "string"
+                }
+              },
+              "required" : [ "annotationDate", "annotationType", "annotator", "comment" ],
+              "additionalProperties" : false,
+              "description" : "An Annotation is a comment on an SpdxItem by an agent."
+            }
+          },
+          "artifactOfs" : {
+            "description" : "Indicates the project in which the SpdxElement originated. Tools must preserve doap:homepage and doap:name properties and the URI (if one is known) of doap:Project resources that are values of this property. All other properties of doap:Projects are not directly supported by SPDX and may be dropped when translating to or from some SPDX formats.",
+            "type" : "array",
+            "items" : {
+              "type" : "object"
+            }
+          },
+          "attributionTexts" : {
+            "description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConculded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
+            "type" : "array",
+            "items" : {
+              "description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConculded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
+              "type" : "string"
+            }
+          },
+          "checksums" : {
+            "description" : "The checksum property provides a mechanism that can be used to verify that the contents of a File or Package have not changed.",
+            "minItems" : 1,
+            "type" : "array",
+            "items" : {
+              "type" : "object",
+              "properties" : {
+                "algorithm" : {
+                  "description" : "Identifies the algorithm used to produce the subject Checksum. Currently, SHA-1 is the only supported algorithm. It is anticipated that other algorithms will be supported at a later time.",
+                  "type" : "string",
+                  "enum" : [ "SHA1", "BLAKE3", "SHA3-384", "SHA256", "SHA384", "BLAKE2b-512", "BLAKE2b-256", "SHA3-512", "MD2", "ADLER32", "MD4", "SHA3-256", "BLAKE2b-384", "SHA512", "MD6", "MD5", "SHA224" ]
+                },
+                "checksumValue" : {
+                  "description" : "The checksumValue property provides a lower case hexidecimal encoded digest value produced using a specific algorithm.",
+                  "type" : "string"
+                }
+              },
+              "required" : [ "algorithm", "checksumValue" ],
+              "additionalProperties" : false,
+              "description" : "A Checksum is value that allows the contents of a file to be authenticated. Even small changes to the content of the file will change its checksum. This class allows the results of a variety of checksum and cryptographic message digest algorithms to be represented."
+            }
+          },
+          "comment" : {
+            "type" : "string"
+          },
+          "copyrightText" : {
+            "description" : "The text of copyright declarations recited in the package, file or snippet.\n\nIf the copyrightText field is not present, it implies an equivalent meaning to NOASSERTION.",
+            "type" : "string"
+          },
+          "fileContributors" : {
+            "description" : "This field provides a place for the SPDX file creator to record file contributors. Contributors could include names of copyright holders and/or authors who may not be copyright holders yet contributed to the file content.",
+            "type" : "array",
+            "items" : {
+              "description" : "This field provides a place for the SPDX file creator to record file contributors. Contributors could include names of copyright holders and/or authors who may not be copyright holders yet contributed to the file content.",
+              "type" : "string"
+            }
+          },
+          "fileDependencies" : {
+            "description" : "This field is deprecated since SPDX 2.0 in favor of using Section 7 which provides more granularity about relationships.",
+            "type" : "array",
+            "items" : {
+              "description" : "SPDX ID for File.  This field is deprecated since SPDX 2.0 in favor of using Section 7 which provides more granularity about relationships.",
+              "type" : "string"
+            }
+          },
+          "fileName" : {
+            "description" : "The name of the file relative to the root of the package.",
+            "type" : "string"
+          },
+          "fileTypes" : {
+            "description" : "The type of the file.",
+            "type" : "array",
+            "items" : {
+              "description" : "The type of the file.",
+              "type" : "string",
+              "enum" : [ "OTHER", "DOCUMENTATION", "IMAGE", "VIDEO", "ARCHIVE", "SPDX", "APPLICATION", "SOURCE", "BINARY", "TEXT", "AUDIO" ]
+            }
+          },
+          "licenseComments" : {
+            "description" : "The licenseComments property allows the preparer of the SPDX document to describe why the licensing in spdx:licenseConcluded was chosen.",
+            "type" : "string"
+          },
+          "licenseConcluded" : {
+            "description" : "License expression for licenseConcluded. See SPDX Annex D for the license expression syntax.  The licensing that the preparer of this SPDX document has concluded, based on the evidence, actually applies to the SPDX Item.\n\nIf the licenseConcluded field is not present for an SPDX Item, it implies an equivalent meaning to NOASSERTION.",
+            "type" : "string"
+          },
+          "licenseInfoInFiles" : {
+            "description" : "Licensing information that was discovered directly in the subject file. This is also considered a declared license for the file.\n\nIf the licenseInfoInFile field is not present for a file, it implies an equivalent meaning to NOASSERTION.",
+            "type" : "array",
+            "items" : {
+              "description" : "License expression for licenseInfoInFile. See SPDX Annex D for the license expression syntax.  Licensing information that was discovered directly in the subject file. This is also considered a declared license for the file.\n\nIf the licenseInfoInFile field is not present for a file, it implies an equivalent meaning to NOASSERTION.",
+              "type" : "string"
+            }
+          },
+          "noticeText" : {
+            "description" : "This field provides a place for the SPDX file creator to record potential legal notices found in the file. This may or may not include copyright statements.",
+            "type" : "string"
+          }
+        },
+        "required" : [ "SPDXID", "checksums", "fileName" ],
+        "additionalProperties" : false
+      }
+    },
+    "snippets" : {
+      "description" : "Snippets referenced in the SPDX document",
+      "type" : "array",
+      "items" : {
+        "type" : "object",
+        "properties" : {
+          "SPDXID" : {
+            "type" : "string",
+            "description" : "Uniquely identify any element in an SPDX document which may be referenced by other elements."
+          },
+          "annotations" : {
+            "description" : "Provide additional information about an SpdxElement.",
+            "type" : "array",
+            "items" : {
+              "type" : "object",
+              "properties" : {
+                "annotationDate" : {
+                  "description" : "Identify when the comment was made. This is to be specified according to the combined date and time in the UTC format, as specified in the ISO 8601 standard.",
+                  "type" : "string"
+                },
+                "annotationType" : {
+                  "description" : "Type of the annotation.",
+                  "type" : "string",
+                  "enum" : [ "OTHER", "REVIEW" ]
+                },
+                "annotator" : {
+                  "description" : "This field identifies the person, organization, or tool that has commented on a file, package, snippet, or the entire document.",
+                  "type" : "string"
+                },
+                "comment" : {
+                  "type" : "string"
+                }
+              },
+              "required" : [ "annotationDate", "annotationType", "annotator", "comment" ],
+              "additionalProperties" : false,
+              "description" : "An Annotation is a comment on an SpdxItem by an agent."
+            }
+          },
+          "attributionTexts" : {
+            "description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConculded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
+            "type" : "array",
+            "items" : {
+              "description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConculded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
+              "type" : "string"
+            }
+          },
+          "comment" : {
+            "type" : "string"
+          },
+          "copyrightText" : {
+            "description" : "The text of copyright declarations recited in the package, file or snippet.\n\nIf the copyrightText field is not present, it implies an equivalent meaning to NOASSERTION.",
+            "type" : "string"
+          },
+          "licenseComments" : {
+            "description" : "The licenseComments property allows the preparer of the SPDX document to describe why the licensing in spdx:licenseConcluded was chosen.",
+            "type" : "string"
+          },
+          "licenseConcluded" : {
+            "description" : "License expression for licenseConcluded. See SPDX Annex D for the license expression syntax.  The licensing that the preparer of this SPDX document has concluded, based on the evidence, actually applies to the SPDX Item.\n\nIf the licenseConcluded field is not present for an SPDX Item, it implies an equivalent meaning to NOASSERTION.",
+            "type" : "string"
+          },
+          "licenseInfoInSnippets" : {
+            "description" : "Licensing information that was discovered directly in the subject snippet. This is also considered a declared license for the snippet.\n\nIf the licenseInfoInSnippet field is not present for a snippet, it implies an equivalent meaning to NOASSERTION.",
+            "type" : "array",
+            "items" : {
+              "description" : "License expression for licenseInfoInSnippet. See SPDX Annex D for the license expression syntax.  Licensing information that was discovered directly in the subject snippet. This is also considered a declared license for the snippet.\n\nIf the licenseInfoInSnippet field is not present for a snippet, it implies an equivalent meaning to NOASSERTION.",
+              "type" : "string"
+            }
+          },
+          "name" : {
+            "description" : "Identify name of this SpdxElement.",
+            "type" : "string"
+          },
+          "ranges" : {
+            "description" : "This field defines the byte range in the original host file (in X.2) that the snippet information applies to",
+            "minItems" : 1,
+            "type" : "array",
+            "items" : {
+              "type" : "object",
+              "properties" : {
+                "endPointer" : {
+                  "type" : "object",
+                  "properties" : {
+                    "reference" : {
+                      "description" : "SPDX ID for File",
+                      "type" : "string"
+                    },
+                    "offset" : {
+                      "type" : "integer",
+                      "description" : "Byte offset in the file"
+                    },
+                    "lineNumber" : {
+                      "type" : "integer",
+                      "description" : "line number offset in the file"
+                    }
+                  },
+                  "required" : [ "reference" ],
+                  "additionalProperties" : false
+                },
+                "startPointer" : {
+                  "type" : "object",
+                  "properties" : {
+                    "reference" : {
+                      "description" : "SPDX ID for File",
+                      "type" : "string"
+                    },
+                    "offset" : {
+                      "type" : "integer",
+                      "description" : "Byte offset in the file"
+                    },
+                    "lineNumber" : {
+                      "type" : "integer",
+                      "description" : "line number offset in the file"
+                    }
+                  },
+                  "required" : [ "reference" ],
+                  "additionalProperties" : false
+                }
+              },
+              "required" : [ "endPointer", "startPointer" ],
+              "additionalProperties" : false
+            }
+          },
+          "snippetFromFile" : {
+            "description" : "SPDX ID for File.  File containing the SPDX element (e.g. the file contaning a snippet).",
+            "type" : "string"
+          }
+        },
+        "required" : [ "SPDXID", "name", "ranges", "snippetFromFile" ],
+        "additionalProperties" : false
+      }
+    },
+    "relationships" : {
+      "description" : "Relationships referenced in the SPDX document",
+      "type" : "array",
+      "items" : {
+        "type" : "object",
+        "properties" : {
+          "spdxElementId" : {
+            "type" : "string",
+            "description" : "Id to which the SPDX element is related"
+          },
+          "comment" : {
+            "type" : "string"
+          },
+          "relatedSpdxElement" : {
+            "description" : "SPDX ID for SpdxElement.  A related SpdxElement.",
+            "type" : "string"
+          },
+          "relationshipType" : {
+            "description" : "Describes the type of relationship between two SPDX elements.",
+            "type" : "string",
+            "enum" : [ "VARIANT_OF", "COPY_OF", "PATCH_FOR", "TEST_DEPENDENCY_OF", "CONTAINED_BY", "DATA_FILE_OF", "OPTIONAL_COMPONENT_OF", "ANCESTOR_OF", "GENERATES", "CONTAINS", "OPTIONAL_DEPENDENCY_OF", "FILE_ADDED", "REQUIREMENT_DESCRIPTION_FOR", "DEV_DEPENDENCY_OF", "DEPENDENCY_OF", "BUILD_DEPENDENCY_OF", "DESCRIBES", "PREREQUISITE_FOR", "HAS_PREREQUISITE", "PROVIDED_DEPENDENCY_OF", "DYNAMIC_LINK", "DESCRIBED_BY", "METAFILE_OF", "DEPENDENCY_MANIFEST_OF", "PATCH_APPLIED", "RUNTIME_DEPENDENCY_OF", "TEST_OF", "TEST_TOOL_OF", "DEPENDS_ON", "SPECIFICATION_FOR", "FILE_MODIFIED", "DISTRIBUTION_ARTIFACT", "AMENDS", "DOCUMENTATION_OF", "GENERATED_FROM", "STATIC_LINK", "OTHER", "BUILD_TOOL_OF", "TEST_CASE_OF", "PACKAGE_OF", "DESCENDANT_OF", "FILE_DELETED", "EXPANDED_FROM_ARCHIVE", "DEV_TOOL_OF", "EXAMPLE_OF" ]
+          }
+        },
+        "required" : [ "spdxElementId", "relatedSpdxElement", "relationshipType" ],
+        "additionalProperties" : false
+      }
+    }
+  },
+  "required" : [ "SPDXID", "creationInfo", "dataLicense", "name", "spdxVersion" ],
+  "additionalProperties" : false
+}
\ No newline at end of file
diff --git a/deps/openssl/config/archs/BSD-x86/asm/configdata.pm b/deps/openssl/config/archs/BSD-x86/asm/configdata.pm
index 667d9eb6c472cd..2eec8ceaa21cb7 100644
--- a/deps/openssl/config/archs/BSD-x86/asm/configdata.pm
+++ b/deps/openssl/config/archs/BSD-x86/asm/configdata.pm
@@ -156,7 +156,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -203,7 +203,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -255,11 +255,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "BSD-x86",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/BSD-x86/asm/crypto/buildinf.h b/deps/openssl/config/archs/BSD-x86/asm/crypto/buildinf.h
index c83c080bcb3ade..b5d8c7c8adce23 100644
--- a/deps/openssl/config/archs/BSD-x86/asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/BSD-x86/asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: BSD-x86"
-#define DATE "built on: Sun Aug  6 00:25:19 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:48:37 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/BSD-x86/asm/include/openssl/opensslv.h b/deps/openssl/config/archs/BSD-x86/asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/BSD-x86/asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/BSD-x86/asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/BSD-x86/asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/BSD-x86/asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/BSD-x86/asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/BSD-x86/asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/BSD-x86/asm_avx2/configdata.pm b/deps/openssl/config/archs/BSD-x86/asm_avx2/configdata.pm
index d21a502b43b514..b9fef9eebf98a6 100644
--- a/deps/openssl/config/archs/BSD-x86/asm_avx2/configdata.pm
+++ b/deps/openssl/config/archs/BSD-x86/asm_avx2/configdata.pm
@@ -156,7 +156,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -203,7 +203,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -255,11 +255,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "BSD-x86",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/BSD-x86/asm_avx2/crypto/buildinf.h b/deps/openssl/config/archs/BSD-x86/asm_avx2/crypto/buildinf.h
index b3e839decc98ce..4b373bd0dc21f4 100644
--- a/deps/openssl/config/archs/BSD-x86/asm_avx2/crypto/buildinf.h
+++ b/deps/openssl/config/archs/BSD-x86/asm_avx2/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: BSD-x86"
-#define DATE "built on: Sun Aug  6 00:25:40 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:48:56 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/BSD-x86/asm_avx2/include/openssl/opensslv.h b/deps/openssl/config/archs/BSD-x86/asm_avx2/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/BSD-x86/asm_avx2/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/BSD-x86/asm_avx2/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/BSD-x86/asm_avx2/include/openssl/pkcs7.h b/deps/openssl/config/archs/BSD-x86/asm_avx2/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/BSD-x86/asm_avx2/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/BSD-x86/asm_avx2/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/BSD-x86/no-asm/configdata.pm b/deps/openssl/config/archs/BSD-x86/no-asm/configdata.pm
index df06e22c5669e8..65137fe6dcc5b3 100644
--- a/deps/openssl/config/archs/BSD-x86/no-asm/configdata.pm
+++ b/deps/openssl/config/archs/BSD-x86/no-asm/configdata.pm
@@ -154,7 +154,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -202,7 +202,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-asm no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -255,11 +255,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "BSD-x86",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/BSD-x86/no-asm/crypto/buildinf.h b/deps/openssl/config/archs/BSD-x86/no-asm/crypto/buildinf.h
index 0b2dc3af6c4db6..edf452c92abb33 100644
--- a/deps/openssl/config/archs/BSD-x86/no-asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/BSD-x86/no-asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: BSD-x86"
-#define DATE "built on: Sun Aug  6 00:26:00 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:49:16 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/BSD-x86/no-asm/include/openssl/opensslv.h b/deps/openssl/config/archs/BSD-x86/no-asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/BSD-x86/no-asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/BSD-x86/no-asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/BSD-x86/no-asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/BSD-x86/no-asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/BSD-x86/no-asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/BSD-x86/no-asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/BSD-x86_64/asm/configdata.pm b/deps/openssl/config/archs/BSD-x86_64/asm/configdata.pm
index f3476682006a8a..82a08c7ee72579 100644
--- a/deps/openssl/config/archs/BSD-x86_64/asm/configdata.pm
+++ b/deps/openssl/config/archs/BSD-x86_64/asm/configdata.pm
@@ -156,7 +156,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -203,7 +203,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -255,11 +255,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "BSD-x86_64",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/BSD-x86_64/asm/crypto/buildinf.h b/deps/openssl/config/archs/BSD-x86_64/asm/crypto/buildinf.h
index 8220828c4d379e..9b2212f3ae4bd1 100644
--- a/deps/openssl/config/archs/BSD-x86_64/asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/BSD-x86_64/asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: BSD-x86_64"
-#define DATE "built on: Sun Aug  6 00:26:19 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:49:35 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/BSD-x86_64/asm/include/openssl/opensslv.h b/deps/openssl/config/archs/BSD-x86_64/asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/BSD-x86_64/asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/BSD-x86_64/asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/BSD-x86_64/asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/BSD-x86_64/asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/BSD-x86_64/asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/BSD-x86_64/asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/BSD-x86_64/asm_avx2/configdata.pm b/deps/openssl/config/archs/BSD-x86_64/asm_avx2/configdata.pm
index 07333980e3d535..397887f1e385f7 100644
--- a/deps/openssl/config/archs/BSD-x86_64/asm_avx2/configdata.pm
+++ b/deps/openssl/config/archs/BSD-x86_64/asm_avx2/configdata.pm
@@ -156,7 +156,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -203,7 +203,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -255,11 +255,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "BSD-x86_64",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/BSD-x86_64/asm_avx2/crypto/buildinf.h b/deps/openssl/config/archs/BSD-x86_64/asm_avx2/crypto/buildinf.h
index 0141bc595c4669..1148cc2a577c0c 100644
--- a/deps/openssl/config/archs/BSD-x86_64/asm_avx2/crypto/buildinf.h
+++ b/deps/openssl/config/archs/BSD-x86_64/asm_avx2/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: BSD-x86_64"
-#define DATE "built on: Sun Aug  6 00:26:43 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:49:58 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/BSD-x86_64/asm_avx2/include/openssl/opensslv.h b/deps/openssl/config/archs/BSD-x86_64/asm_avx2/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/BSD-x86_64/asm_avx2/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/BSD-x86_64/asm_avx2/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/BSD-x86_64/asm_avx2/include/openssl/pkcs7.h b/deps/openssl/config/archs/BSD-x86_64/asm_avx2/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/BSD-x86_64/asm_avx2/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/BSD-x86_64/asm_avx2/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/BSD-x86_64/no-asm/configdata.pm b/deps/openssl/config/archs/BSD-x86_64/no-asm/configdata.pm
index daa479b8c190aa..3a36a6286ecc1e 100644
--- a/deps/openssl/config/archs/BSD-x86_64/no-asm/configdata.pm
+++ b/deps/openssl/config/archs/BSD-x86_64/no-asm/configdata.pm
@@ -154,7 +154,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -202,7 +202,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-asm no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -255,11 +255,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "BSD-x86_64",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/BSD-x86_64/no-asm/crypto/buildinf.h b/deps/openssl/config/archs/BSD-x86_64/no-asm/crypto/buildinf.h
index f1fbc792476400..d9add13d2a3d32 100644
--- a/deps/openssl/config/archs/BSD-x86_64/no-asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/BSD-x86_64/no-asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: BSD-x86_64"
-#define DATE "built on: Sun Aug  6 00:27:07 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:50:22 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/BSD-x86_64/no-asm/include/openssl/opensslv.h b/deps/openssl/config/archs/BSD-x86_64/no-asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/BSD-x86_64/no-asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/BSD-x86_64/no-asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/BSD-x86_64/no-asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/BSD-x86_64/no-asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/BSD-x86_64/no-asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/BSD-x86_64/no-asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/VC-WIN32/asm/configdata.pm b/deps/openssl/config/archs/VC-WIN32/asm/configdata.pm
index ca62a99b20e7e9..8bf601f3902773 100644
--- a/deps/openssl/config/archs/VC-WIN32/asm/configdata.pm
+++ b/deps/openssl/config/archs/VC-WIN32/asm/configdata.pm
@@ -165,7 +165,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -216,7 +216,7 @@ our %config = (
     ],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -268,11 +268,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "VC-WIN32",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "lib",
@@ -287,7 +287,7 @@ our %target = (
     "LDFLAGS" => "/nologo /debug",
     "MT" => "mt",
     "MTFLAGS" => "-nologo",
-    "RANLIB" => "CODE(0x55c06cf5ea80)",
+    "RANLIB" => "CODE(0x558d4506ace0)",
     "RC" => "rc",
     "_conf_fname_int" => [
         "Configurations/00-base-templates.conf",
diff --git a/deps/openssl/config/archs/VC-WIN32/asm/crypto/buildinf.h b/deps/openssl/config/archs/VC-WIN32/asm/crypto/buildinf.h
index b4978c23fed544..8a88b5d57d37eb 100644
--- a/deps/openssl/config/archs/VC-WIN32/asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/VC-WIN32/asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: "
-#define DATE "built on: Sun Aug  6 00:43:26 2023 UTC"
+#define DATE "built on: Thu Oct 26 15:04:24 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/VC-WIN32/asm/include/openssl/opensslv.h b/deps/openssl/config/archs/VC-WIN32/asm/include/openssl/opensslv.h
index 38b44f1054ad3d..a410f0eddf361c 100644
--- a/deps/openssl/config/archs/VC-WIN32/asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/VC-WIN32/asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/VC-WIN32/asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/VC-WIN32/asm/include/openssl/pkcs7.h
index 3978fd087bca3b..0a95a93e59e262 100644
--- a/deps/openssl/config/archs/VC-WIN32/asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/VC-WIN32/asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/VC-WIN32/asm_avx2/configdata.pm b/deps/openssl/config/archs/VC-WIN32/asm_avx2/configdata.pm
index 62ccddd60f494f..b0c0b52ee69d56 100644
--- a/deps/openssl/config/archs/VC-WIN32/asm_avx2/configdata.pm
+++ b/deps/openssl/config/archs/VC-WIN32/asm_avx2/configdata.pm
@@ -165,7 +165,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -216,7 +216,7 @@ our %config = (
     ],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -268,11 +268,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "VC-WIN32",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "lib",
@@ -287,7 +287,7 @@ our %target = (
     "LDFLAGS" => "/nologo /debug",
     "MT" => "mt",
     "MTFLAGS" => "-nologo",
-    "RANLIB" => "CODE(0x55b8a711a640)",
+    "RANLIB" => "CODE(0x55f14f6dce20)",
     "RC" => "rc",
     "_conf_fname_int" => [
         "Configurations/00-base-templates.conf",
diff --git a/deps/openssl/config/archs/VC-WIN32/asm_avx2/crypto/buildinf.h b/deps/openssl/config/archs/VC-WIN32/asm_avx2/crypto/buildinf.h
index 00774a2a9b5c85..82019d38ddffd7 100644
--- a/deps/openssl/config/archs/VC-WIN32/asm_avx2/crypto/buildinf.h
+++ b/deps/openssl/config/archs/VC-WIN32/asm_avx2/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: "
-#define DATE "built on: Sun Aug  6 00:43:47 2023 UTC"
+#define DATE "built on: Thu Oct 26 15:04:43 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/VC-WIN32/asm_avx2/include/openssl/opensslv.h b/deps/openssl/config/archs/VC-WIN32/asm_avx2/include/openssl/opensslv.h
index 38b44f1054ad3d..a410f0eddf361c 100644
--- a/deps/openssl/config/archs/VC-WIN32/asm_avx2/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/VC-WIN32/asm_avx2/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/VC-WIN32/asm_avx2/include/openssl/pkcs7.h b/deps/openssl/config/archs/VC-WIN32/asm_avx2/include/openssl/pkcs7.h
index 3978fd087bca3b..0a95a93e59e262 100644
--- a/deps/openssl/config/archs/VC-WIN32/asm_avx2/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/VC-WIN32/asm_avx2/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/VC-WIN32/no-asm/configdata.pm b/deps/openssl/config/archs/VC-WIN32/no-asm/configdata.pm
index 9a5d93c30fa1ab..40491bd28bd763 100644
--- a/deps/openssl/config/archs/VC-WIN32/no-asm/configdata.pm
+++ b/deps/openssl/config/archs/VC-WIN32/no-asm/configdata.pm
@@ -163,7 +163,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -215,7 +215,7 @@ our %config = (
     ],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-asm no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -268,11 +268,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "VC-WIN32",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "lib",
@@ -287,7 +287,7 @@ our %target = (
     "LDFLAGS" => "/nologo /debug",
     "MT" => "mt",
     "MTFLAGS" => "-nologo",
-    "RANLIB" => "CODE(0x55ac94d0db28)",
+    "RANLIB" => "CODE(0x55dfb3e6a5e8)",
     "RC" => "rc",
     "_conf_fname_int" => [
         "Configurations/00-base-templates.conf",
diff --git a/deps/openssl/config/archs/VC-WIN32/no-asm/crypto/buildinf.h b/deps/openssl/config/archs/VC-WIN32/no-asm/crypto/buildinf.h
index b19b8b48b13928..3894b1e4a023f9 100644
--- a/deps/openssl/config/archs/VC-WIN32/no-asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/VC-WIN32/no-asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: "
-#define DATE "built on: Sun Aug  6 00:44:09 2023 UTC"
+#define DATE "built on: Thu Oct 26 15:05:01 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/VC-WIN32/no-asm/include/openssl/opensslv.h b/deps/openssl/config/archs/VC-WIN32/no-asm/include/openssl/opensslv.h
index 38b44f1054ad3d..a410f0eddf361c 100644
--- a/deps/openssl/config/archs/VC-WIN32/no-asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/VC-WIN32/no-asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/VC-WIN32/no-asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/VC-WIN32/no-asm/include/openssl/pkcs7.h
index 3978fd087bca3b..0a95a93e59e262 100644
--- a/deps/openssl/config/archs/VC-WIN32/no-asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/VC-WIN32/no-asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/VC-WIN64-ARM/no-asm/configdata.pm b/deps/openssl/config/archs/VC-WIN64-ARM/no-asm/configdata.pm
index 4c747db9cfb5c7..e450e0c1904e51 100644
--- a/deps/openssl/config/archs/VC-WIN64-ARM/no-asm/configdata.pm
+++ b/deps/openssl/config/archs/VC-WIN64-ARM/no-asm/configdata.pm
@@ -163,7 +163,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -213,7 +213,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-asm no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -266,11 +266,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "VC-WIN64-ARM",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "lib",
@@ -283,7 +283,7 @@ our %target = (
     "LDFLAGS" => "/nologo /debug",
     "MT" => "mt",
     "MTFLAGS" => "-nologo",
-    "RANLIB" => "CODE(0x56025ddf3078)",
+    "RANLIB" => "CODE(0x55619ad3d968)",
     "RC" => "rc",
     "_conf_fname_int" => [
         "Configurations/00-base-templates.conf",
diff --git a/deps/openssl/config/archs/VC-WIN64-ARM/no-asm/crypto/buildinf.h b/deps/openssl/config/archs/VC-WIN64-ARM/no-asm/crypto/buildinf.h
index f32efe5d98eca3..2611edb7bd6bf2 100644
--- a/deps/openssl/config/archs/VC-WIN64-ARM/no-asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/VC-WIN64-ARM/no-asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: VC-WIN64-ARM"
-#define DATE "built on: Sun Aug  6 00:44:29 2023 UTC"
+#define DATE "built on: Thu Oct 26 15:05:18 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/VC-WIN64-ARM/no-asm/include/openssl/opensslv.h b/deps/openssl/config/archs/VC-WIN64-ARM/no-asm/include/openssl/opensslv.h
index 38b44f1054ad3d..a410f0eddf361c 100644
--- a/deps/openssl/config/archs/VC-WIN64-ARM/no-asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/VC-WIN64-ARM/no-asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/VC-WIN64-ARM/no-asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/VC-WIN64-ARM/no-asm/include/openssl/pkcs7.h
index 3978fd087bca3b..0a95a93e59e262 100644
--- a/deps/openssl/config/archs/VC-WIN64-ARM/no-asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/VC-WIN64-ARM/no-asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/VC-WIN64A/asm/configdata.pm b/deps/openssl/config/archs/VC-WIN64A/asm/configdata.pm
index 80443a734d38e4..ca90ef75c27121 100644
--- a/deps/openssl/config/archs/VC-WIN64A/asm/configdata.pm
+++ b/deps/openssl/config/archs/VC-WIN64A/asm/configdata.pm
@@ -168,7 +168,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -219,7 +219,7 @@ our %config = (
     ],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -271,11 +271,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "VC-WIN64A",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "lib",
@@ -290,7 +290,7 @@ our %target = (
     "LDFLAGS" => "/nologo /debug",
     "MT" => "mt",
     "MTFLAGS" => "-nologo",
-    "RANLIB" => "CODE(0x56532d60fad0)",
+    "RANLIB" => "CODE(0x559ccffc4580)",
     "RC" => "rc",
     "_conf_fname_int" => [
         "Configurations/00-base-templates.conf",
@@ -356,7 +356,7 @@ our %target = (
     "mtoutflag" => "-outputresource:",
     "multilib" => "-x64",
     "perl_platform" => "Windows::MSVC",
-    "perlasm_scheme" => "auto",
+    "perlasm_scheme" => "nasm",
     "rcoutflag" => "/fo",
     "shared_cflag" => "",
     "shared_defflag" => "",
diff --git a/deps/openssl/config/archs/VC-WIN64A/asm/crypto/buildinf.h b/deps/openssl/config/archs/VC-WIN64A/asm/crypto/buildinf.h
index 06a91884502b77..8daa2d52f03a84 100644
--- a/deps/openssl/config/archs/VC-WIN64A/asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/VC-WIN64A/asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: "
-#define DATE "built on: Sun Aug  6 00:42:10 2023 UTC"
+#define DATE "built on: Thu Oct 26 15:03:22 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/VC-WIN64A/asm/crypto/poly1305/poly1305-x86_64.asm b/deps/openssl/config/archs/VC-WIN64A/asm/crypto/poly1305/poly1305-x86_64.asm
index 26f683384d1806..fb3823608c949b 100644
--- a/deps/openssl/config/archs/VC-WIN64A/asm/crypto/poly1305/poly1305-x86_64.asm
+++ b/deps/openssl/config/archs/VC-WIN64A/asm/crypto/poly1305/poly1305-x86_64.asm
@@ -46,11 +46,6 @@ $L$SEH_begin_poly1305_init:
 	lea	rax,[poly1305_blocks_avx2]
 	bt	r9,37
 	cmovc	r10,rax
-	mov	rax,2149646336
-	shr	r9,32
-	and	r9,rax
-	cmp	r9,rax
-	je	NEAR $L$init_base2_44
 	mov	rax,0x0ffffffc0fffffff
 	mov	rcx,0x0ffffffc0ffffffc
 	and	rax,QWORD[rsi]
@@ -2605,1029 +2600,6 @@ $L$do_avx512_epilogue:
 	DB	0F3h,0C3h		;repret
 
 $L$SEH_end_poly1305_blocks_avx512:
-
-ALIGN	32
-poly1305_init_base2_44:
-	mov	QWORD[8+rsp],rdi	;WIN64 prologue
-	mov	QWORD[16+rsp],rsi
-	mov	rax,rsp
-$L$SEH_begin_poly1305_init_base2_44:
-	mov	rdi,rcx
-	mov	rsi,rdx
-	mov	rdx,r8
-
-
-
-	xor	rax,rax
-	mov	QWORD[rdi],rax
-	mov	QWORD[8+rdi],rax
-	mov	QWORD[16+rdi],rax
-
-$L$init_base2_44:
-	lea	r10,[poly1305_blocks_vpmadd52]
-	lea	r11,[poly1305_emit_base2_44]
-
-	mov	rax,0x0ffffffc0fffffff
-	mov	rcx,0x0ffffffc0ffffffc
-	and	rax,QWORD[rsi]
-	mov	r8,0x00000fffffffffff
-	and	rcx,QWORD[8+rsi]
-	mov	r9,0x00000fffffffffff
-	and	r8,rax
-	shrd	rax,rcx,44
-	mov	QWORD[40+rdi],r8
-	and	rax,r9
-	shr	rcx,24
-	mov	QWORD[48+rdi],rax
-	lea	rax,[rax*4+rax]
-	mov	QWORD[56+rdi],rcx
-	shl	rax,2
-	lea	rcx,[rcx*4+rcx]
-	shl	rcx,2
-	mov	QWORD[24+rdi],rax
-	mov	QWORD[32+rdi],rcx
-	mov	QWORD[64+rdi],-1
-	mov	QWORD[rdx],r10
-	mov	QWORD[8+rdx],r11
-	mov	eax,1
-	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
-	mov	rsi,QWORD[16+rsp]
-	DB	0F3h,0C3h		;repret
-
-$L$SEH_end_poly1305_init_base2_44:
-
-ALIGN	32
-poly1305_blocks_vpmadd52:
-	mov	QWORD[8+rsp],rdi	;WIN64 prologue
-	mov	QWORD[16+rsp],rsi
-	mov	rax,rsp
-$L$SEH_begin_poly1305_blocks_vpmadd52:
-	mov	rdi,rcx
-	mov	rsi,rdx
-	mov	rdx,r8
-	mov	rcx,r9
-
-
-
-DB	243,15,30,250
-	shr	rdx,4
-	jz	NEAR $L$no_data_vpmadd52
-
-	shl	rcx,40
-	mov	r8,QWORD[64+rdi]
-
-
-
-
-
-
-	mov	rax,3
-	mov	r10,1
-	cmp	rdx,4
-	cmovae	rax,r10
-	test	r8,r8
-	cmovns	rax,r10
-
-	and	rax,rdx
-	jz	NEAR $L$blocks_vpmadd52_4x
-
-	sub	rdx,rax
-	mov	r10d,7
-	mov	r11d,1
-	kmovw	k7,r10d
-	lea	r10,[$L$2_44_inp_permd]
-	kmovw	k1,r11d
-
-	vmovq	xmm21,rcx
-	vmovdqa64	ymm19,YMMWORD[r10]
-	vmovdqa64	ymm20,YMMWORD[32+r10]
-	vpermq	ymm21,ymm21,0xcf
-	vmovdqa64	ymm22,YMMWORD[64+r10]
-
-	vmovdqu64	ymm16{k7}{z},[rdi]
-	vmovdqu64	ymm3{k7}{z},[40+rdi]
-	vmovdqu64	ymm4{k7}{z},[32+rdi]
-	vmovdqu64	ymm5{k7}{z},[24+rdi]
-
-	vmovdqa64	ymm23,YMMWORD[96+r10]
-	vmovdqa64	ymm24,YMMWORD[128+r10]
-
-	jmp	NEAR $L$oop_vpmadd52
-
-ALIGN	32
-$L$oop_vpmadd52:
-	vmovdqu32	xmm18,XMMWORD[rsi]
-	lea	rsi,[16+rsi]
-
-	vpermd	ymm18,ymm19,ymm18
-	vpsrlvq	ymm18,ymm18,ymm20
-	vpandq	ymm18,ymm18,ymm22
-	vporq	ymm18,ymm18,ymm21
-
-	vpaddq	ymm16,ymm16,ymm18
-
-	vpermq	ymm0{k7}{z},ymm16,0
-	vpermq	ymm1{k7}{z},ymm16,85
-	vpermq	ymm2{k7}{z},ymm16,170
-
-	vpxord	ymm16,ymm16,ymm16
-	vpxord	ymm17,ymm17,ymm17
-
-	vpmadd52luq	ymm16,ymm0,ymm3
-	vpmadd52huq	ymm17,ymm0,ymm3
-
-	vpmadd52luq	ymm16,ymm1,ymm4
-	vpmadd52huq	ymm17,ymm1,ymm4
-
-	vpmadd52luq	ymm16,ymm2,ymm5
-	vpmadd52huq	ymm17,ymm2,ymm5
-
-	vpsrlvq	ymm18,ymm16,ymm23
-	vpsllvq	ymm17,ymm17,ymm24
-	vpandq	ymm16,ymm16,ymm22
-
-	vpaddq	ymm17,ymm17,ymm18
-
-	vpermq	ymm17,ymm17,147
-
-	vpaddq	ymm16,ymm16,ymm17
-
-	vpsrlvq	ymm18,ymm16,ymm23
-	vpandq	ymm16,ymm16,ymm22
-
-	vpermq	ymm18,ymm18,147
-
-	vpaddq	ymm16,ymm16,ymm18
-
-	vpermq	ymm18{k1}{z},ymm16,147
-
-	vpaddq	ymm16,ymm16,ymm18
-	vpsllq	ymm18,ymm18,2
-
-	vpaddq	ymm16,ymm16,ymm18
-
-	dec	rax
-	jnz	NEAR $L$oop_vpmadd52
-
-	vmovdqu64	YMMWORD[rdi]{k7},ymm16
-
-	test	rdx,rdx
-	jnz	NEAR $L$blocks_vpmadd52_4x
-
-$L$no_data_vpmadd52:
-	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
-	mov	rsi,QWORD[16+rsp]
-	DB	0F3h,0C3h		;repret
-
-$L$SEH_end_poly1305_blocks_vpmadd52:
-
-ALIGN	32
-poly1305_blocks_vpmadd52_4x:
-	mov	QWORD[8+rsp],rdi	;WIN64 prologue
-	mov	QWORD[16+rsp],rsi
-	mov	rax,rsp
-$L$SEH_begin_poly1305_blocks_vpmadd52_4x:
-	mov	rdi,rcx
-	mov	rsi,rdx
-	mov	rdx,r8
-	mov	rcx,r9
-
-
-
-	shr	rdx,4
-	jz	NEAR $L$no_data_vpmadd52_4x
-
-	shl	rcx,40
-	mov	r8,QWORD[64+rdi]
-
-$L$blocks_vpmadd52_4x:
-	vpbroadcastq	ymm31,rcx
-
-	vmovdqa64	ymm28,YMMWORD[$L$x_mask44]
-	mov	eax,5
-	vmovdqa64	ymm29,YMMWORD[$L$x_mask42]
-	kmovw	k1,eax
-
-	test	r8,r8
-	js	NEAR $L$init_vpmadd52
-
-	vmovq	xmm0,QWORD[rdi]
-	vmovq	xmm1,QWORD[8+rdi]
-	vmovq	xmm2,QWORD[16+rdi]
-
-	test	rdx,3
-	jnz	NEAR $L$blocks_vpmadd52_2x_do
-
-$L$blocks_vpmadd52_4x_do:
-	vpbroadcastq	ymm3,QWORD[64+rdi]
-	vpbroadcastq	ymm4,QWORD[96+rdi]
-	vpbroadcastq	ymm5,QWORD[128+rdi]
-	vpbroadcastq	ymm16,QWORD[160+rdi]
-
-$L$blocks_vpmadd52_4x_key_loaded:
-	vpsllq	ymm17,ymm5,2
-	vpaddq	ymm17,ymm17,ymm5
-	vpsllq	ymm17,ymm17,2
-
-	test	rdx,7
-	jz	NEAR $L$blocks_vpmadd52_8x
-
-	vmovdqu64	ymm26,YMMWORD[rsi]
-	vmovdqu64	ymm27,YMMWORD[32+rsi]
-	lea	rsi,[64+rsi]
-
-	vpunpcklqdq	ymm25,ymm26,ymm27
-	vpunpckhqdq	ymm27,ymm26,ymm27
-
-
-
-	vpsrlq	ymm26,ymm27,24
-	vporq	ymm26,ymm26,ymm31
-	vpaddq	ymm2,ymm2,ymm26
-	vpandq	ymm24,ymm25,ymm28
-	vpsrlq	ymm25,ymm25,44
-	vpsllq	ymm27,ymm27,20
-	vporq	ymm25,ymm25,ymm27
-	vpandq	ymm25,ymm25,ymm28
-
-	sub	rdx,4
-	jz	NEAR $L$tail_vpmadd52_4x
-	jmp	NEAR $L$oop_vpmadd52_4x
-	ud2
-
-ALIGN	32
-$L$init_vpmadd52:
-	vmovq	xmm16,QWORD[24+rdi]
-	vmovq	xmm2,QWORD[56+rdi]
-	vmovq	xmm17,QWORD[32+rdi]
-	vmovq	xmm3,QWORD[40+rdi]
-	vmovq	xmm4,QWORD[48+rdi]
-
-	vmovdqa	ymm0,ymm3
-	vmovdqa	ymm1,ymm4
-	vmovdqa	ymm5,ymm2
-
-	mov	eax,2
-
-$L$mul_init_vpmadd52:
-	vpxorq	ymm18,ymm18,ymm18
-	vpmadd52luq	ymm18,ymm16,ymm2
-	vpxorq	ymm19,ymm19,ymm19
-	vpmadd52huq	ymm19,ymm16,ymm2
-	vpxorq	ymm20,ymm20,ymm20
-	vpmadd52luq	ymm20,ymm17,ymm2
-	vpxorq	ymm21,ymm21,ymm21
-	vpmadd52huq	ymm21,ymm17,ymm2
-	vpxorq	ymm22,ymm22,ymm22
-	vpmadd52luq	ymm22,ymm3,ymm2
-	vpxorq	ymm23,ymm23,ymm23
-	vpmadd52huq	ymm23,ymm3,ymm2
-
-	vpmadd52luq	ymm18,ymm3,ymm0
-	vpmadd52huq	ymm19,ymm3,ymm0
-	vpmadd52luq	ymm20,ymm4,ymm0
-	vpmadd52huq	ymm21,ymm4,ymm0
-	vpmadd52luq	ymm22,ymm5,ymm0
-	vpmadd52huq	ymm23,ymm5,ymm0
-
-	vpmadd52luq	ymm18,ymm17,ymm1
-	vpmadd52huq	ymm19,ymm17,ymm1
-	vpmadd52luq	ymm20,ymm3,ymm1
-	vpmadd52huq	ymm21,ymm3,ymm1
-	vpmadd52luq	ymm22,ymm4,ymm1
-	vpmadd52huq	ymm23,ymm4,ymm1
-
-
-
-	vpsrlq	ymm30,ymm18,44
-	vpsllq	ymm19,ymm19,8
-	vpandq	ymm0,ymm18,ymm28
-	vpaddq	ymm19,ymm19,ymm30
-
-	vpaddq	ymm20,ymm20,ymm19
-
-	vpsrlq	ymm30,ymm20,44
-	vpsllq	ymm21,ymm21,8
-	vpandq	ymm1,ymm20,ymm28
-	vpaddq	ymm21,ymm21,ymm30
-
-	vpaddq	ymm22,ymm22,ymm21
-
-	vpsrlq	ymm30,ymm22,42
-	vpsllq	ymm23,ymm23,10
-	vpandq	ymm2,ymm22,ymm29
-	vpaddq	ymm23,ymm23,ymm30
-
-	vpaddq	ymm0,ymm0,ymm23
-	vpsllq	ymm23,ymm23,2
-
-	vpaddq	ymm0,ymm0,ymm23
-
-	vpsrlq	ymm30,ymm0,44
-	vpandq	ymm0,ymm0,ymm28
-
-	vpaddq	ymm1,ymm1,ymm30
-
-	dec	eax
-	jz	NEAR $L$done_init_vpmadd52
-
-	vpunpcklqdq	ymm4,ymm1,ymm4
-	vpbroadcastq	xmm1,xmm1
-	vpunpcklqdq	ymm5,ymm2,ymm5
-	vpbroadcastq	xmm2,xmm2
-	vpunpcklqdq	ymm3,ymm0,ymm3
-	vpbroadcastq	xmm0,xmm0
-
-	vpsllq	ymm16,ymm4,2
-	vpsllq	ymm17,ymm5,2
-	vpaddq	ymm16,ymm16,ymm4
-	vpaddq	ymm17,ymm17,ymm5
-	vpsllq	ymm16,ymm16,2
-	vpsllq	ymm17,ymm17,2
-
-	jmp	NEAR $L$mul_init_vpmadd52
-	ud2
-
-ALIGN	32
-$L$done_init_vpmadd52:
-	vinserti128	ymm4,ymm1,xmm4,1
-	vinserti128	ymm5,ymm2,xmm5,1
-	vinserti128	ymm3,ymm0,xmm3,1
-
-	vpermq	ymm4,ymm4,216
-	vpermq	ymm5,ymm5,216
-	vpermq	ymm3,ymm3,216
-
-	vpsllq	ymm16,ymm4,2
-	vpaddq	ymm16,ymm16,ymm4
-	vpsllq	ymm16,ymm16,2
-
-	vmovq	xmm0,QWORD[rdi]
-	vmovq	xmm1,QWORD[8+rdi]
-	vmovq	xmm2,QWORD[16+rdi]
-
-	test	rdx,3
-	jnz	NEAR $L$done_init_vpmadd52_2x
-
-	vmovdqu64	YMMWORD[64+rdi],ymm3
-	vpbroadcastq	ymm3,xmm3
-	vmovdqu64	YMMWORD[96+rdi],ymm4
-	vpbroadcastq	ymm4,xmm4
-	vmovdqu64	YMMWORD[128+rdi],ymm5
-	vpbroadcastq	ymm5,xmm5
-	vmovdqu64	YMMWORD[160+rdi],ymm16
-	vpbroadcastq	ymm16,xmm16
-
-	jmp	NEAR $L$blocks_vpmadd52_4x_key_loaded
-	ud2
-
-ALIGN	32
-$L$done_init_vpmadd52_2x:
-	vmovdqu64	YMMWORD[64+rdi],ymm3
-	vpsrldq	ymm3,ymm3,8
-	vmovdqu64	YMMWORD[96+rdi],ymm4
-	vpsrldq	ymm4,ymm4,8
-	vmovdqu64	YMMWORD[128+rdi],ymm5
-	vpsrldq	ymm5,ymm5,8
-	vmovdqu64	YMMWORD[160+rdi],ymm16
-	vpsrldq	ymm16,ymm16,8
-	jmp	NEAR $L$blocks_vpmadd52_2x_key_loaded
-	ud2
-
-ALIGN	32
-$L$blocks_vpmadd52_2x_do:
-	vmovdqu64	ymm5{k1}{z},[((128+8))+rdi]
-	vmovdqu64	ymm16{k1}{z},[((160+8))+rdi]
-	vmovdqu64	ymm3{k1}{z},[((64+8))+rdi]
-	vmovdqu64	ymm4{k1}{z},[((96+8))+rdi]
-
-$L$blocks_vpmadd52_2x_key_loaded:
-	vmovdqu64	ymm26,YMMWORD[rsi]
-	vpxorq	ymm27,ymm27,ymm27
-	lea	rsi,[32+rsi]
-
-	vpunpcklqdq	ymm25,ymm26,ymm27
-	vpunpckhqdq	ymm27,ymm26,ymm27
-
-
-
-	vpsrlq	ymm26,ymm27,24
-	vporq	ymm26,ymm26,ymm31
-	vpaddq	ymm2,ymm2,ymm26
-	vpandq	ymm24,ymm25,ymm28
-	vpsrlq	ymm25,ymm25,44
-	vpsllq	ymm27,ymm27,20
-	vporq	ymm25,ymm25,ymm27
-	vpandq	ymm25,ymm25,ymm28
-
-	jmp	NEAR $L$tail_vpmadd52_2x
-	ud2
-
-ALIGN	32
-$L$oop_vpmadd52_4x:
-
-	vpaddq	ymm0,ymm0,ymm24
-	vpaddq	ymm1,ymm1,ymm25
-
-	vpxorq	ymm18,ymm18,ymm18
-	vpmadd52luq	ymm18,ymm16,ymm2
-	vpxorq	ymm19,ymm19,ymm19
-	vpmadd52huq	ymm19,ymm16,ymm2
-	vpxorq	ymm20,ymm20,ymm20
-	vpmadd52luq	ymm20,ymm17,ymm2
-	vpxorq	ymm21,ymm21,ymm21
-	vpmadd52huq	ymm21,ymm17,ymm2
-	vpxorq	ymm22,ymm22,ymm22
-	vpmadd52luq	ymm22,ymm3,ymm2
-	vpxorq	ymm23,ymm23,ymm23
-	vpmadd52huq	ymm23,ymm3,ymm2
-
-	vmovdqu64	ymm26,YMMWORD[rsi]
-	vmovdqu64	ymm27,YMMWORD[32+rsi]
-	lea	rsi,[64+rsi]
-	vpmadd52luq	ymm18,ymm3,ymm0
-	vpmadd52huq	ymm19,ymm3,ymm0
-	vpmadd52luq	ymm20,ymm4,ymm0
-	vpmadd52huq	ymm21,ymm4,ymm0
-	vpmadd52luq	ymm22,ymm5,ymm0
-	vpmadd52huq	ymm23,ymm5,ymm0
-
-	vpunpcklqdq	ymm25,ymm26,ymm27
-	vpunpckhqdq	ymm27,ymm26,ymm27
-	vpmadd52luq	ymm18,ymm17,ymm1
-	vpmadd52huq	ymm19,ymm17,ymm1
-	vpmadd52luq	ymm20,ymm3,ymm1
-	vpmadd52huq	ymm21,ymm3,ymm1
-	vpmadd52luq	ymm22,ymm4,ymm1
-	vpmadd52huq	ymm23,ymm4,ymm1
-
-
-
-	vpsrlq	ymm30,ymm18,44
-	vpsllq	ymm19,ymm19,8
-	vpandq	ymm0,ymm18,ymm28
-	vpaddq	ymm19,ymm19,ymm30
-
-	vpsrlq	ymm26,ymm27,24
-	vporq	ymm26,ymm26,ymm31
-	vpaddq	ymm20,ymm20,ymm19
-
-	vpsrlq	ymm30,ymm20,44
-	vpsllq	ymm21,ymm21,8
-	vpandq	ymm1,ymm20,ymm28
-	vpaddq	ymm21,ymm21,ymm30
-
-	vpandq	ymm24,ymm25,ymm28
-	vpsrlq	ymm25,ymm25,44
-	vpsllq	ymm27,ymm27,20
-	vpaddq	ymm22,ymm22,ymm21
-
-	vpsrlq	ymm30,ymm22,42
-	vpsllq	ymm23,ymm23,10
-	vpandq	ymm2,ymm22,ymm29
-	vpaddq	ymm23,ymm23,ymm30
-
-	vpaddq	ymm2,ymm2,ymm26
-	vpaddq	ymm0,ymm0,ymm23
-	vpsllq	ymm23,ymm23,2
-
-	vpaddq	ymm0,ymm0,ymm23
-	vporq	ymm25,ymm25,ymm27
-	vpandq	ymm25,ymm25,ymm28
-
-	vpsrlq	ymm30,ymm0,44
-	vpandq	ymm0,ymm0,ymm28
-
-	vpaddq	ymm1,ymm1,ymm30
-
-	sub	rdx,4
-	jnz	NEAR $L$oop_vpmadd52_4x
-
-$L$tail_vpmadd52_4x:
-	vmovdqu64	ymm5,YMMWORD[128+rdi]
-	vmovdqu64	ymm16,YMMWORD[160+rdi]
-	vmovdqu64	ymm3,YMMWORD[64+rdi]
-	vmovdqu64	ymm4,YMMWORD[96+rdi]
-
-$L$tail_vpmadd52_2x:
-	vpsllq	ymm17,ymm5,2
-	vpaddq	ymm17,ymm17,ymm5
-	vpsllq	ymm17,ymm17,2
-
-
-	vpaddq	ymm0,ymm0,ymm24
-	vpaddq	ymm1,ymm1,ymm25
-
-	vpxorq	ymm18,ymm18,ymm18
-	vpmadd52luq	ymm18,ymm16,ymm2
-	vpxorq	ymm19,ymm19,ymm19
-	vpmadd52huq	ymm19,ymm16,ymm2
-	vpxorq	ymm20,ymm20,ymm20
-	vpmadd52luq	ymm20,ymm17,ymm2
-	vpxorq	ymm21,ymm21,ymm21
-	vpmadd52huq	ymm21,ymm17,ymm2
-	vpxorq	ymm22,ymm22,ymm22
-	vpmadd52luq	ymm22,ymm3,ymm2
-	vpxorq	ymm23,ymm23,ymm23
-	vpmadd52huq	ymm23,ymm3,ymm2
-
-	vpmadd52luq	ymm18,ymm3,ymm0
-	vpmadd52huq	ymm19,ymm3,ymm0
-	vpmadd52luq	ymm20,ymm4,ymm0
-	vpmadd52huq	ymm21,ymm4,ymm0
-	vpmadd52luq	ymm22,ymm5,ymm0
-	vpmadd52huq	ymm23,ymm5,ymm0
-
-	vpmadd52luq	ymm18,ymm17,ymm1
-	vpmadd52huq	ymm19,ymm17,ymm1
-	vpmadd52luq	ymm20,ymm3,ymm1
-	vpmadd52huq	ymm21,ymm3,ymm1
-	vpmadd52luq	ymm22,ymm4,ymm1
-	vpmadd52huq	ymm23,ymm4,ymm1
-
-
-
-
-	mov	eax,1
-	kmovw	k1,eax
-	vpsrldq	ymm24,ymm18,8
-	vpsrldq	ymm0,ymm19,8
-	vpsrldq	ymm25,ymm20,8
-	vpsrldq	ymm1,ymm21,8
-	vpaddq	ymm18,ymm18,ymm24
-	vpaddq	ymm19,ymm19,ymm0
-	vpsrldq	ymm26,ymm22,8
-	vpsrldq	ymm2,ymm23,8
-	vpaddq	ymm20,ymm20,ymm25
-	vpaddq	ymm21,ymm21,ymm1
-	vpermq	ymm24,ymm18,0x2
-	vpermq	ymm0,ymm19,0x2
-	vpaddq	ymm22,ymm22,ymm26
-	vpaddq	ymm23,ymm23,ymm2
-
-	vpermq	ymm25,ymm20,0x2
-	vpermq	ymm1,ymm21,0x2
-	vpaddq	ymm18{k1}{z},ymm18,ymm24
-	vpaddq	ymm19{k1}{z},ymm19,ymm0
-	vpermq	ymm26,ymm22,0x2
-	vpermq	ymm2,ymm23,0x2
-	vpaddq	ymm20{k1}{z},ymm20,ymm25
-	vpaddq	ymm21{k1}{z},ymm21,ymm1
-	vpaddq	ymm22{k1}{z},ymm22,ymm26
-	vpaddq	ymm23{k1}{z},ymm23,ymm2
-
-
-
-	vpsrlq	ymm30,ymm18,44
-	vpsllq	ymm19,ymm19,8
-	vpandq	ymm0,ymm18,ymm28
-	vpaddq	ymm19,ymm19,ymm30
-
-	vpaddq	ymm20,ymm20,ymm19
-
-	vpsrlq	ymm30,ymm20,44
-	vpsllq	ymm21,ymm21,8
-	vpandq	ymm1,ymm20,ymm28
-	vpaddq	ymm21,ymm21,ymm30
-
-	vpaddq	ymm22,ymm22,ymm21
-
-	vpsrlq	ymm30,ymm22,42
-	vpsllq	ymm23,ymm23,10
-	vpandq	ymm2,ymm22,ymm29
-	vpaddq	ymm23,ymm23,ymm30
-
-	vpaddq	ymm0,ymm0,ymm23
-	vpsllq	ymm23,ymm23,2
-
-	vpaddq	ymm0,ymm0,ymm23
-
-	vpsrlq	ymm30,ymm0,44
-	vpandq	ymm0,ymm0,ymm28
-
-	vpaddq	ymm1,ymm1,ymm30
-
-
-	sub	rdx,2
-	ja	NEAR $L$blocks_vpmadd52_4x_do
-
-	vmovq	QWORD[rdi],xmm0
-	vmovq	QWORD[8+rdi],xmm1
-	vmovq	QWORD[16+rdi],xmm2
-	vzeroall
-
-$L$no_data_vpmadd52_4x:
-	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
-	mov	rsi,QWORD[16+rsp]
-	DB	0F3h,0C3h		;repret
-
-$L$SEH_end_poly1305_blocks_vpmadd52_4x:
-
-ALIGN	32
-poly1305_blocks_vpmadd52_8x:
-	mov	QWORD[8+rsp],rdi	;WIN64 prologue
-	mov	QWORD[16+rsp],rsi
-	mov	rax,rsp
-$L$SEH_begin_poly1305_blocks_vpmadd52_8x:
-	mov	rdi,rcx
-	mov	rsi,rdx
-	mov	rdx,r8
-	mov	rcx,r9
-
-
-
-	shr	rdx,4
-	jz	NEAR $L$no_data_vpmadd52_8x
-
-	shl	rcx,40
-	mov	r8,QWORD[64+rdi]
-
-	vmovdqa64	ymm28,YMMWORD[$L$x_mask44]
-	vmovdqa64	ymm29,YMMWORD[$L$x_mask42]
-
-	test	r8,r8
-	js	NEAR $L$init_vpmadd52
-
-	vmovq	xmm0,QWORD[rdi]
-	vmovq	xmm1,QWORD[8+rdi]
-	vmovq	xmm2,QWORD[16+rdi]
-
-$L$blocks_vpmadd52_8x:
-
-
-
-	vmovdqu64	ymm5,YMMWORD[128+rdi]
-	vmovdqu64	ymm16,YMMWORD[160+rdi]
-	vmovdqu64	ymm3,YMMWORD[64+rdi]
-	vmovdqu64	ymm4,YMMWORD[96+rdi]
-
-	vpsllq	ymm17,ymm5,2
-	vpaddq	ymm17,ymm17,ymm5
-	vpsllq	ymm17,ymm17,2
-
-	vpbroadcastq	ymm8,xmm5
-	vpbroadcastq	ymm6,xmm3
-	vpbroadcastq	ymm7,xmm4
-
-	vpxorq	ymm18,ymm18,ymm18
-	vpmadd52luq	ymm18,ymm16,ymm8
-	vpxorq	ymm19,ymm19,ymm19
-	vpmadd52huq	ymm19,ymm16,ymm8
-	vpxorq	ymm20,ymm20,ymm20
-	vpmadd52luq	ymm20,ymm17,ymm8
-	vpxorq	ymm21,ymm21,ymm21
-	vpmadd52huq	ymm21,ymm17,ymm8
-	vpxorq	ymm22,ymm22,ymm22
-	vpmadd52luq	ymm22,ymm3,ymm8
-	vpxorq	ymm23,ymm23,ymm23
-	vpmadd52huq	ymm23,ymm3,ymm8
-
-	vpmadd52luq	ymm18,ymm3,ymm6
-	vpmadd52huq	ymm19,ymm3,ymm6
-	vpmadd52luq	ymm20,ymm4,ymm6
-	vpmadd52huq	ymm21,ymm4,ymm6
-	vpmadd52luq	ymm22,ymm5,ymm6
-	vpmadd52huq	ymm23,ymm5,ymm6
-
-	vpmadd52luq	ymm18,ymm17,ymm7
-	vpmadd52huq	ymm19,ymm17,ymm7
-	vpmadd52luq	ymm20,ymm3,ymm7
-	vpmadd52huq	ymm21,ymm3,ymm7
-	vpmadd52luq	ymm22,ymm4,ymm7
-	vpmadd52huq	ymm23,ymm4,ymm7
-
-
-
-	vpsrlq	ymm30,ymm18,44
-	vpsllq	ymm19,ymm19,8
-	vpandq	ymm6,ymm18,ymm28
-	vpaddq	ymm19,ymm19,ymm30
-
-	vpaddq	ymm20,ymm20,ymm19
-
-	vpsrlq	ymm30,ymm20,44
-	vpsllq	ymm21,ymm21,8
-	vpandq	ymm7,ymm20,ymm28
-	vpaddq	ymm21,ymm21,ymm30
-
-	vpaddq	ymm22,ymm22,ymm21
-
-	vpsrlq	ymm30,ymm22,42
-	vpsllq	ymm23,ymm23,10
-	vpandq	ymm8,ymm22,ymm29
-	vpaddq	ymm23,ymm23,ymm30
-
-	vpaddq	ymm6,ymm6,ymm23
-	vpsllq	ymm23,ymm23,2
-
-	vpaddq	ymm6,ymm6,ymm23
-
-	vpsrlq	ymm30,ymm6,44
-	vpandq	ymm6,ymm6,ymm28
-
-	vpaddq	ymm7,ymm7,ymm30
-
-
-
-
-
-	vpunpcklqdq	ymm26,ymm8,ymm5
-	vpunpckhqdq	ymm5,ymm8,ymm5
-	vpunpcklqdq	ymm24,ymm6,ymm3
-	vpunpckhqdq	ymm3,ymm6,ymm3
-	vpunpcklqdq	ymm25,ymm7,ymm4
-	vpunpckhqdq	ymm4,ymm7,ymm4
-	vshufi64x2	zmm8,zmm26,zmm5,0x44
-	vshufi64x2	zmm6,zmm24,zmm3,0x44
-	vshufi64x2	zmm7,zmm25,zmm4,0x44
-
-	vmovdqu64	zmm26,ZMMWORD[rsi]
-	vmovdqu64	zmm27,ZMMWORD[64+rsi]
-	lea	rsi,[128+rsi]
-
-	vpsllq	zmm10,zmm8,2
-	vpsllq	zmm9,zmm7,2
-	vpaddq	zmm10,zmm10,zmm8
-	vpaddq	zmm9,zmm9,zmm7
-	vpsllq	zmm10,zmm10,2
-	vpsllq	zmm9,zmm9,2
-
-	vpbroadcastq	zmm31,rcx
-	vpbroadcastq	zmm28,xmm28
-	vpbroadcastq	zmm29,xmm29
-
-	vpbroadcastq	zmm16,xmm9
-	vpbroadcastq	zmm17,xmm10
-	vpbroadcastq	zmm3,xmm6
-	vpbroadcastq	zmm4,xmm7
-	vpbroadcastq	zmm5,xmm8
-
-	vpunpcklqdq	zmm25,zmm26,zmm27
-	vpunpckhqdq	zmm27,zmm26,zmm27
-
-
-
-	vpsrlq	zmm26,zmm27,24
-	vporq	zmm26,zmm26,zmm31
-	vpaddq	zmm2,zmm2,zmm26
-	vpandq	zmm24,zmm25,zmm28
-	vpsrlq	zmm25,zmm25,44
-	vpsllq	zmm27,zmm27,20
-	vporq	zmm25,zmm25,zmm27
-	vpandq	zmm25,zmm25,zmm28
-
-	sub	rdx,8
-	jz	NEAR $L$tail_vpmadd52_8x
-	jmp	NEAR $L$oop_vpmadd52_8x
-
-ALIGN	32
-$L$oop_vpmadd52_8x:
-
-	vpaddq	zmm0,zmm0,zmm24
-	vpaddq	zmm1,zmm1,zmm25
-
-	vpxorq	zmm18,zmm18,zmm18
-	vpmadd52luq	zmm18,zmm16,zmm2
-	vpxorq	zmm19,zmm19,zmm19
-	vpmadd52huq	zmm19,zmm16,zmm2
-	vpxorq	zmm20,zmm20,zmm20
-	vpmadd52luq	zmm20,zmm17,zmm2
-	vpxorq	zmm21,zmm21,zmm21
-	vpmadd52huq	zmm21,zmm17,zmm2
-	vpxorq	zmm22,zmm22,zmm22
-	vpmadd52luq	zmm22,zmm3,zmm2
-	vpxorq	zmm23,zmm23,zmm23
-	vpmadd52huq	zmm23,zmm3,zmm2
-
-	vmovdqu64	zmm26,ZMMWORD[rsi]
-	vmovdqu64	zmm27,ZMMWORD[64+rsi]
-	lea	rsi,[128+rsi]
-	vpmadd52luq	zmm18,zmm3,zmm0
-	vpmadd52huq	zmm19,zmm3,zmm0
-	vpmadd52luq	zmm20,zmm4,zmm0
-	vpmadd52huq	zmm21,zmm4,zmm0
-	vpmadd52luq	zmm22,zmm5,zmm0
-	vpmadd52huq	zmm23,zmm5,zmm0
-
-	vpunpcklqdq	zmm25,zmm26,zmm27
-	vpunpckhqdq	zmm27,zmm26,zmm27
-	vpmadd52luq	zmm18,zmm17,zmm1
-	vpmadd52huq	zmm19,zmm17,zmm1
-	vpmadd52luq	zmm20,zmm3,zmm1
-	vpmadd52huq	zmm21,zmm3,zmm1
-	vpmadd52luq	zmm22,zmm4,zmm1
-	vpmadd52huq	zmm23,zmm4,zmm1
-
-
-
-	vpsrlq	zmm30,zmm18,44
-	vpsllq	zmm19,zmm19,8
-	vpandq	zmm0,zmm18,zmm28
-	vpaddq	zmm19,zmm19,zmm30
-
-	vpsrlq	zmm26,zmm27,24
-	vporq	zmm26,zmm26,zmm31
-	vpaddq	zmm20,zmm20,zmm19
-
-	vpsrlq	zmm30,zmm20,44
-	vpsllq	zmm21,zmm21,8
-	vpandq	zmm1,zmm20,zmm28
-	vpaddq	zmm21,zmm21,zmm30
-
-	vpandq	zmm24,zmm25,zmm28
-	vpsrlq	zmm25,zmm25,44
-	vpsllq	zmm27,zmm27,20
-	vpaddq	zmm22,zmm22,zmm21
-
-	vpsrlq	zmm30,zmm22,42
-	vpsllq	zmm23,zmm23,10
-	vpandq	zmm2,zmm22,zmm29
-	vpaddq	zmm23,zmm23,zmm30
-
-	vpaddq	zmm2,zmm2,zmm26
-	vpaddq	zmm0,zmm0,zmm23
-	vpsllq	zmm23,zmm23,2
-
-	vpaddq	zmm0,zmm0,zmm23
-	vporq	zmm25,zmm25,zmm27
-	vpandq	zmm25,zmm25,zmm28
-
-	vpsrlq	zmm30,zmm0,44
-	vpandq	zmm0,zmm0,zmm28
-
-	vpaddq	zmm1,zmm1,zmm30
-
-	sub	rdx,8
-	jnz	NEAR $L$oop_vpmadd52_8x
-
-$L$tail_vpmadd52_8x:
-
-	vpaddq	zmm0,zmm0,zmm24
-	vpaddq	zmm1,zmm1,zmm25
-
-	vpxorq	zmm18,zmm18,zmm18
-	vpmadd52luq	zmm18,zmm9,zmm2
-	vpxorq	zmm19,zmm19,zmm19
-	vpmadd52huq	zmm19,zmm9,zmm2
-	vpxorq	zmm20,zmm20,zmm20
-	vpmadd52luq	zmm20,zmm10,zmm2
-	vpxorq	zmm21,zmm21,zmm21
-	vpmadd52huq	zmm21,zmm10,zmm2
-	vpxorq	zmm22,zmm22,zmm22
-	vpmadd52luq	zmm22,zmm6,zmm2
-	vpxorq	zmm23,zmm23,zmm23
-	vpmadd52huq	zmm23,zmm6,zmm2
-
-	vpmadd52luq	zmm18,zmm6,zmm0
-	vpmadd52huq	zmm19,zmm6,zmm0
-	vpmadd52luq	zmm20,zmm7,zmm0
-	vpmadd52huq	zmm21,zmm7,zmm0
-	vpmadd52luq	zmm22,zmm8,zmm0
-	vpmadd52huq	zmm23,zmm8,zmm0
-
-	vpmadd52luq	zmm18,zmm10,zmm1
-	vpmadd52huq	zmm19,zmm10,zmm1
-	vpmadd52luq	zmm20,zmm6,zmm1
-	vpmadd52huq	zmm21,zmm6,zmm1
-	vpmadd52luq	zmm22,zmm7,zmm1
-	vpmadd52huq	zmm23,zmm7,zmm1
-
-
-
-
-	mov	eax,1
-	kmovw	k1,eax
-	vpsrldq	zmm24,zmm18,8
-	vpsrldq	zmm0,zmm19,8
-	vpsrldq	zmm25,zmm20,8
-	vpsrldq	zmm1,zmm21,8
-	vpaddq	zmm18,zmm18,zmm24
-	vpaddq	zmm19,zmm19,zmm0
-	vpsrldq	zmm26,zmm22,8
-	vpsrldq	zmm2,zmm23,8
-	vpaddq	zmm20,zmm20,zmm25
-	vpaddq	zmm21,zmm21,zmm1
-	vpermq	zmm24,zmm18,0x2
-	vpermq	zmm0,zmm19,0x2
-	vpaddq	zmm22,zmm22,zmm26
-	vpaddq	zmm23,zmm23,zmm2
-
-	vpermq	zmm25,zmm20,0x2
-	vpermq	zmm1,zmm21,0x2
-	vpaddq	zmm18,zmm18,zmm24
-	vpaddq	zmm19,zmm19,zmm0
-	vpermq	zmm26,zmm22,0x2
-	vpermq	zmm2,zmm23,0x2
-	vpaddq	zmm20,zmm20,zmm25
-	vpaddq	zmm21,zmm21,zmm1
-	vextracti64x4	ymm24,zmm18,1
-	vextracti64x4	ymm0,zmm19,1
-	vpaddq	zmm22,zmm22,zmm26
-	vpaddq	zmm23,zmm23,zmm2
-
-	vextracti64x4	ymm25,zmm20,1
-	vextracti64x4	ymm1,zmm21,1
-	vextracti64x4	ymm26,zmm22,1
-	vextracti64x4	ymm2,zmm23,1
-	vpaddq	ymm18{k1}{z},ymm18,ymm24
-	vpaddq	ymm19{k1}{z},ymm19,ymm0
-	vpaddq	ymm20{k1}{z},ymm20,ymm25
-	vpaddq	ymm21{k1}{z},ymm21,ymm1
-	vpaddq	ymm22{k1}{z},ymm22,ymm26
-	vpaddq	ymm23{k1}{z},ymm23,ymm2
-
-
-
-	vpsrlq	ymm30,ymm18,44
-	vpsllq	ymm19,ymm19,8
-	vpandq	ymm0,ymm18,ymm28
-	vpaddq	ymm19,ymm19,ymm30
-
-	vpaddq	ymm20,ymm20,ymm19
-
-	vpsrlq	ymm30,ymm20,44
-	vpsllq	ymm21,ymm21,8
-	vpandq	ymm1,ymm20,ymm28
-	vpaddq	ymm21,ymm21,ymm30
-
-	vpaddq	ymm22,ymm22,ymm21
-
-	vpsrlq	ymm30,ymm22,42
-	vpsllq	ymm23,ymm23,10
-	vpandq	ymm2,ymm22,ymm29
-	vpaddq	ymm23,ymm23,ymm30
-
-	vpaddq	ymm0,ymm0,ymm23
-	vpsllq	ymm23,ymm23,2
-
-	vpaddq	ymm0,ymm0,ymm23
-
-	vpsrlq	ymm30,ymm0,44
-	vpandq	ymm0,ymm0,ymm28
-
-	vpaddq	ymm1,ymm1,ymm30
-
-
-
-	vmovq	QWORD[rdi],xmm0
-	vmovq	QWORD[8+rdi],xmm1
-	vmovq	QWORD[16+rdi],xmm2
-	vzeroall
-
-$L$no_data_vpmadd52_8x:
-	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
-	mov	rsi,QWORD[16+rsp]
-	DB	0F3h,0C3h		;repret
-
-$L$SEH_end_poly1305_blocks_vpmadd52_8x:
-
-ALIGN	32
-poly1305_emit_base2_44:
-	mov	QWORD[8+rsp],rdi	;WIN64 prologue
-	mov	QWORD[16+rsp],rsi
-	mov	rax,rsp
-$L$SEH_begin_poly1305_emit_base2_44:
-	mov	rdi,rcx
-	mov	rsi,rdx
-	mov	rdx,r8
-
-
-
-DB	243,15,30,250
-	mov	r8,QWORD[rdi]
-	mov	r9,QWORD[8+rdi]
-	mov	r10,QWORD[16+rdi]
-
-	mov	rax,r9
-	shr	r9,20
-	shl	rax,44
-	mov	rcx,r10
-	shr	r10,40
-	shl	rcx,24
-
-	add	r8,rax
-	adc	r9,rcx
-	adc	r10,0
-
-	mov	rax,r8
-	add	r8,5
-	mov	rcx,r9
-	adc	r9,0
-	adc	r10,0
-	shr	r10,2
-	cmovnz	rax,r8
-	cmovnz	rcx,r9
-
-	add	rax,QWORD[rdx]
-	adc	rcx,QWORD[8+rdx]
-	mov	QWORD[rsi],rax
-	mov	QWORD[8+rsi],rcx
-
-	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
-	mov	rsi,QWORD[16+rsp]
-	DB	0F3h,0C3h		;repret
-
-$L$SEH_end_poly1305_emit_base2_44:
 ALIGN	64
 $L$const:
 $L$mask24:
diff --git a/deps/openssl/config/archs/VC-WIN64A/asm/include/openssl/opensslv.h b/deps/openssl/config/archs/VC-WIN64A/asm/include/openssl/opensslv.h
index 38b44f1054ad3d..a410f0eddf361c 100644
--- a/deps/openssl/config/archs/VC-WIN64A/asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/VC-WIN64A/asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/VC-WIN64A/asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/VC-WIN64A/asm/include/openssl/pkcs7.h
index 3978fd087bca3b..0a95a93e59e262 100644
--- a/deps/openssl/config/archs/VC-WIN64A/asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/VC-WIN64A/asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/VC-WIN64A/asm_avx2/configdata.pm b/deps/openssl/config/archs/VC-WIN64A/asm_avx2/configdata.pm
index 08fdeedbf613bf..243ea4184ec432 100644
--- a/deps/openssl/config/archs/VC-WIN64A/asm_avx2/configdata.pm
+++ b/deps/openssl/config/archs/VC-WIN64A/asm_avx2/configdata.pm
@@ -168,7 +168,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -219,7 +219,7 @@ our %config = (
     ],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -271,11 +271,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "VC-WIN64A",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "lib",
@@ -290,7 +290,7 @@ our %target = (
     "LDFLAGS" => "/nologo /debug",
     "MT" => "mt",
     "MTFLAGS" => "-nologo",
-    "RANLIB" => "CODE(0x56478be29bd0)",
+    "RANLIB" => "CODE(0x55a9fd66b620)",
     "RC" => "rc",
     "_conf_fname_int" => [
         "Configurations/00-base-templates.conf",
@@ -356,7 +356,7 @@ our %target = (
     "mtoutflag" => "-outputresource:",
     "multilib" => "-x64",
     "perl_platform" => "Windows::MSVC",
-    "perlasm_scheme" => "auto",
+    "perlasm_scheme" => "nasm",
     "rcoutflag" => "/fo",
     "shared_cflag" => "",
     "shared_defflag" => "",
diff --git a/deps/openssl/config/archs/VC-WIN64A/asm_avx2/crypto/buildinf.h b/deps/openssl/config/archs/VC-WIN64A/asm_avx2/crypto/buildinf.h
index 196661655556bf..ebb9fb26fed3ea 100644
--- a/deps/openssl/config/archs/VC-WIN64A/asm_avx2/crypto/buildinf.h
+++ b/deps/openssl/config/archs/VC-WIN64A/asm_avx2/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: "
-#define DATE "built on: Sun Aug  6 00:42:38 2023 UTC"
+#define DATE "built on: Thu Oct 26 15:03:45 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/VC-WIN64A/asm_avx2/crypto/poly1305/poly1305-x86_64.asm b/deps/openssl/config/archs/VC-WIN64A/asm_avx2/crypto/poly1305/poly1305-x86_64.asm
index 26f683384d1806..fb3823608c949b 100644
--- a/deps/openssl/config/archs/VC-WIN64A/asm_avx2/crypto/poly1305/poly1305-x86_64.asm
+++ b/deps/openssl/config/archs/VC-WIN64A/asm_avx2/crypto/poly1305/poly1305-x86_64.asm
@@ -46,11 +46,6 @@ $L$SEH_begin_poly1305_init:
 	lea	rax,[poly1305_blocks_avx2]
 	bt	r9,37
 	cmovc	r10,rax
-	mov	rax,2149646336
-	shr	r9,32
-	and	r9,rax
-	cmp	r9,rax
-	je	NEAR $L$init_base2_44
 	mov	rax,0x0ffffffc0fffffff
 	mov	rcx,0x0ffffffc0ffffffc
 	and	rax,QWORD[rsi]
@@ -2605,1029 +2600,6 @@ $L$do_avx512_epilogue:
 	DB	0F3h,0C3h		;repret
 
 $L$SEH_end_poly1305_blocks_avx512:
-
-ALIGN	32
-poly1305_init_base2_44:
-	mov	QWORD[8+rsp],rdi	;WIN64 prologue
-	mov	QWORD[16+rsp],rsi
-	mov	rax,rsp
-$L$SEH_begin_poly1305_init_base2_44:
-	mov	rdi,rcx
-	mov	rsi,rdx
-	mov	rdx,r8
-
-
-
-	xor	rax,rax
-	mov	QWORD[rdi],rax
-	mov	QWORD[8+rdi],rax
-	mov	QWORD[16+rdi],rax
-
-$L$init_base2_44:
-	lea	r10,[poly1305_blocks_vpmadd52]
-	lea	r11,[poly1305_emit_base2_44]
-
-	mov	rax,0x0ffffffc0fffffff
-	mov	rcx,0x0ffffffc0ffffffc
-	and	rax,QWORD[rsi]
-	mov	r8,0x00000fffffffffff
-	and	rcx,QWORD[8+rsi]
-	mov	r9,0x00000fffffffffff
-	and	r8,rax
-	shrd	rax,rcx,44
-	mov	QWORD[40+rdi],r8
-	and	rax,r9
-	shr	rcx,24
-	mov	QWORD[48+rdi],rax
-	lea	rax,[rax*4+rax]
-	mov	QWORD[56+rdi],rcx
-	shl	rax,2
-	lea	rcx,[rcx*4+rcx]
-	shl	rcx,2
-	mov	QWORD[24+rdi],rax
-	mov	QWORD[32+rdi],rcx
-	mov	QWORD[64+rdi],-1
-	mov	QWORD[rdx],r10
-	mov	QWORD[8+rdx],r11
-	mov	eax,1
-	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
-	mov	rsi,QWORD[16+rsp]
-	DB	0F3h,0C3h		;repret
-
-$L$SEH_end_poly1305_init_base2_44:
-
-ALIGN	32
-poly1305_blocks_vpmadd52:
-	mov	QWORD[8+rsp],rdi	;WIN64 prologue
-	mov	QWORD[16+rsp],rsi
-	mov	rax,rsp
-$L$SEH_begin_poly1305_blocks_vpmadd52:
-	mov	rdi,rcx
-	mov	rsi,rdx
-	mov	rdx,r8
-	mov	rcx,r9
-
-
-
-DB	243,15,30,250
-	shr	rdx,4
-	jz	NEAR $L$no_data_vpmadd52
-
-	shl	rcx,40
-	mov	r8,QWORD[64+rdi]
-
-
-
-
-
-
-	mov	rax,3
-	mov	r10,1
-	cmp	rdx,4
-	cmovae	rax,r10
-	test	r8,r8
-	cmovns	rax,r10
-
-	and	rax,rdx
-	jz	NEAR $L$blocks_vpmadd52_4x
-
-	sub	rdx,rax
-	mov	r10d,7
-	mov	r11d,1
-	kmovw	k7,r10d
-	lea	r10,[$L$2_44_inp_permd]
-	kmovw	k1,r11d
-
-	vmovq	xmm21,rcx
-	vmovdqa64	ymm19,YMMWORD[r10]
-	vmovdqa64	ymm20,YMMWORD[32+r10]
-	vpermq	ymm21,ymm21,0xcf
-	vmovdqa64	ymm22,YMMWORD[64+r10]
-
-	vmovdqu64	ymm16{k7}{z},[rdi]
-	vmovdqu64	ymm3{k7}{z},[40+rdi]
-	vmovdqu64	ymm4{k7}{z},[32+rdi]
-	vmovdqu64	ymm5{k7}{z},[24+rdi]
-
-	vmovdqa64	ymm23,YMMWORD[96+r10]
-	vmovdqa64	ymm24,YMMWORD[128+r10]
-
-	jmp	NEAR $L$oop_vpmadd52
-
-ALIGN	32
-$L$oop_vpmadd52:
-	vmovdqu32	xmm18,XMMWORD[rsi]
-	lea	rsi,[16+rsi]
-
-	vpermd	ymm18,ymm19,ymm18
-	vpsrlvq	ymm18,ymm18,ymm20
-	vpandq	ymm18,ymm18,ymm22
-	vporq	ymm18,ymm18,ymm21
-
-	vpaddq	ymm16,ymm16,ymm18
-
-	vpermq	ymm0{k7}{z},ymm16,0
-	vpermq	ymm1{k7}{z},ymm16,85
-	vpermq	ymm2{k7}{z},ymm16,170
-
-	vpxord	ymm16,ymm16,ymm16
-	vpxord	ymm17,ymm17,ymm17
-
-	vpmadd52luq	ymm16,ymm0,ymm3
-	vpmadd52huq	ymm17,ymm0,ymm3
-
-	vpmadd52luq	ymm16,ymm1,ymm4
-	vpmadd52huq	ymm17,ymm1,ymm4
-
-	vpmadd52luq	ymm16,ymm2,ymm5
-	vpmadd52huq	ymm17,ymm2,ymm5
-
-	vpsrlvq	ymm18,ymm16,ymm23
-	vpsllvq	ymm17,ymm17,ymm24
-	vpandq	ymm16,ymm16,ymm22
-
-	vpaddq	ymm17,ymm17,ymm18
-
-	vpermq	ymm17,ymm17,147
-
-	vpaddq	ymm16,ymm16,ymm17
-
-	vpsrlvq	ymm18,ymm16,ymm23
-	vpandq	ymm16,ymm16,ymm22
-
-	vpermq	ymm18,ymm18,147
-
-	vpaddq	ymm16,ymm16,ymm18
-
-	vpermq	ymm18{k1}{z},ymm16,147
-
-	vpaddq	ymm16,ymm16,ymm18
-	vpsllq	ymm18,ymm18,2
-
-	vpaddq	ymm16,ymm16,ymm18
-
-	dec	rax
-	jnz	NEAR $L$oop_vpmadd52
-
-	vmovdqu64	YMMWORD[rdi]{k7},ymm16
-
-	test	rdx,rdx
-	jnz	NEAR $L$blocks_vpmadd52_4x
-
-$L$no_data_vpmadd52:
-	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
-	mov	rsi,QWORD[16+rsp]
-	DB	0F3h,0C3h		;repret
-
-$L$SEH_end_poly1305_blocks_vpmadd52:
-
-ALIGN	32
-poly1305_blocks_vpmadd52_4x:
-	mov	QWORD[8+rsp],rdi	;WIN64 prologue
-	mov	QWORD[16+rsp],rsi
-	mov	rax,rsp
-$L$SEH_begin_poly1305_blocks_vpmadd52_4x:
-	mov	rdi,rcx
-	mov	rsi,rdx
-	mov	rdx,r8
-	mov	rcx,r9
-
-
-
-	shr	rdx,4
-	jz	NEAR $L$no_data_vpmadd52_4x
-
-	shl	rcx,40
-	mov	r8,QWORD[64+rdi]
-
-$L$blocks_vpmadd52_4x:
-	vpbroadcastq	ymm31,rcx
-
-	vmovdqa64	ymm28,YMMWORD[$L$x_mask44]
-	mov	eax,5
-	vmovdqa64	ymm29,YMMWORD[$L$x_mask42]
-	kmovw	k1,eax
-
-	test	r8,r8
-	js	NEAR $L$init_vpmadd52
-
-	vmovq	xmm0,QWORD[rdi]
-	vmovq	xmm1,QWORD[8+rdi]
-	vmovq	xmm2,QWORD[16+rdi]
-
-	test	rdx,3
-	jnz	NEAR $L$blocks_vpmadd52_2x_do
-
-$L$blocks_vpmadd52_4x_do:
-	vpbroadcastq	ymm3,QWORD[64+rdi]
-	vpbroadcastq	ymm4,QWORD[96+rdi]
-	vpbroadcastq	ymm5,QWORD[128+rdi]
-	vpbroadcastq	ymm16,QWORD[160+rdi]
-
-$L$blocks_vpmadd52_4x_key_loaded:
-	vpsllq	ymm17,ymm5,2
-	vpaddq	ymm17,ymm17,ymm5
-	vpsllq	ymm17,ymm17,2
-
-	test	rdx,7
-	jz	NEAR $L$blocks_vpmadd52_8x
-
-	vmovdqu64	ymm26,YMMWORD[rsi]
-	vmovdqu64	ymm27,YMMWORD[32+rsi]
-	lea	rsi,[64+rsi]
-
-	vpunpcklqdq	ymm25,ymm26,ymm27
-	vpunpckhqdq	ymm27,ymm26,ymm27
-
-
-
-	vpsrlq	ymm26,ymm27,24
-	vporq	ymm26,ymm26,ymm31
-	vpaddq	ymm2,ymm2,ymm26
-	vpandq	ymm24,ymm25,ymm28
-	vpsrlq	ymm25,ymm25,44
-	vpsllq	ymm27,ymm27,20
-	vporq	ymm25,ymm25,ymm27
-	vpandq	ymm25,ymm25,ymm28
-
-	sub	rdx,4
-	jz	NEAR $L$tail_vpmadd52_4x
-	jmp	NEAR $L$oop_vpmadd52_4x
-	ud2
-
-ALIGN	32
-$L$init_vpmadd52:
-	vmovq	xmm16,QWORD[24+rdi]
-	vmovq	xmm2,QWORD[56+rdi]
-	vmovq	xmm17,QWORD[32+rdi]
-	vmovq	xmm3,QWORD[40+rdi]
-	vmovq	xmm4,QWORD[48+rdi]
-
-	vmovdqa	ymm0,ymm3
-	vmovdqa	ymm1,ymm4
-	vmovdqa	ymm5,ymm2
-
-	mov	eax,2
-
-$L$mul_init_vpmadd52:
-	vpxorq	ymm18,ymm18,ymm18
-	vpmadd52luq	ymm18,ymm16,ymm2
-	vpxorq	ymm19,ymm19,ymm19
-	vpmadd52huq	ymm19,ymm16,ymm2
-	vpxorq	ymm20,ymm20,ymm20
-	vpmadd52luq	ymm20,ymm17,ymm2
-	vpxorq	ymm21,ymm21,ymm21
-	vpmadd52huq	ymm21,ymm17,ymm2
-	vpxorq	ymm22,ymm22,ymm22
-	vpmadd52luq	ymm22,ymm3,ymm2
-	vpxorq	ymm23,ymm23,ymm23
-	vpmadd52huq	ymm23,ymm3,ymm2
-
-	vpmadd52luq	ymm18,ymm3,ymm0
-	vpmadd52huq	ymm19,ymm3,ymm0
-	vpmadd52luq	ymm20,ymm4,ymm0
-	vpmadd52huq	ymm21,ymm4,ymm0
-	vpmadd52luq	ymm22,ymm5,ymm0
-	vpmadd52huq	ymm23,ymm5,ymm0
-
-	vpmadd52luq	ymm18,ymm17,ymm1
-	vpmadd52huq	ymm19,ymm17,ymm1
-	vpmadd52luq	ymm20,ymm3,ymm1
-	vpmadd52huq	ymm21,ymm3,ymm1
-	vpmadd52luq	ymm22,ymm4,ymm1
-	vpmadd52huq	ymm23,ymm4,ymm1
-
-
-
-	vpsrlq	ymm30,ymm18,44
-	vpsllq	ymm19,ymm19,8
-	vpandq	ymm0,ymm18,ymm28
-	vpaddq	ymm19,ymm19,ymm30
-
-	vpaddq	ymm20,ymm20,ymm19
-
-	vpsrlq	ymm30,ymm20,44
-	vpsllq	ymm21,ymm21,8
-	vpandq	ymm1,ymm20,ymm28
-	vpaddq	ymm21,ymm21,ymm30
-
-	vpaddq	ymm22,ymm22,ymm21
-
-	vpsrlq	ymm30,ymm22,42
-	vpsllq	ymm23,ymm23,10
-	vpandq	ymm2,ymm22,ymm29
-	vpaddq	ymm23,ymm23,ymm30
-
-	vpaddq	ymm0,ymm0,ymm23
-	vpsllq	ymm23,ymm23,2
-
-	vpaddq	ymm0,ymm0,ymm23
-
-	vpsrlq	ymm30,ymm0,44
-	vpandq	ymm0,ymm0,ymm28
-
-	vpaddq	ymm1,ymm1,ymm30
-
-	dec	eax
-	jz	NEAR $L$done_init_vpmadd52
-
-	vpunpcklqdq	ymm4,ymm1,ymm4
-	vpbroadcastq	xmm1,xmm1
-	vpunpcklqdq	ymm5,ymm2,ymm5
-	vpbroadcastq	xmm2,xmm2
-	vpunpcklqdq	ymm3,ymm0,ymm3
-	vpbroadcastq	xmm0,xmm0
-
-	vpsllq	ymm16,ymm4,2
-	vpsllq	ymm17,ymm5,2
-	vpaddq	ymm16,ymm16,ymm4
-	vpaddq	ymm17,ymm17,ymm5
-	vpsllq	ymm16,ymm16,2
-	vpsllq	ymm17,ymm17,2
-
-	jmp	NEAR $L$mul_init_vpmadd52
-	ud2
-
-ALIGN	32
-$L$done_init_vpmadd52:
-	vinserti128	ymm4,ymm1,xmm4,1
-	vinserti128	ymm5,ymm2,xmm5,1
-	vinserti128	ymm3,ymm0,xmm3,1
-
-	vpermq	ymm4,ymm4,216
-	vpermq	ymm5,ymm5,216
-	vpermq	ymm3,ymm3,216
-
-	vpsllq	ymm16,ymm4,2
-	vpaddq	ymm16,ymm16,ymm4
-	vpsllq	ymm16,ymm16,2
-
-	vmovq	xmm0,QWORD[rdi]
-	vmovq	xmm1,QWORD[8+rdi]
-	vmovq	xmm2,QWORD[16+rdi]
-
-	test	rdx,3
-	jnz	NEAR $L$done_init_vpmadd52_2x
-
-	vmovdqu64	YMMWORD[64+rdi],ymm3
-	vpbroadcastq	ymm3,xmm3
-	vmovdqu64	YMMWORD[96+rdi],ymm4
-	vpbroadcastq	ymm4,xmm4
-	vmovdqu64	YMMWORD[128+rdi],ymm5
-	vpbroadcastq	ymm5,xmm5
-	vmovdqu64	YMMWORD[160+rdi],ymm16
-	vpbroadcastq	ymm16,xmm16
-
-	jmp	NEAR $L$blocks_vpmadd52_4x_key_loaded
-	ud2
-
-ALIGN	32
-$L$done_init_vpmadd52_2x:
-	vmovdqu64	YMMWORD[64+rdi],ymm3
-	vpsrldq	ymm3,ymm3,8
-	vmovdqu64	YMMWORD[96+rdi],ymm4
-	vpsrldq	ymm4,ymm4,8
-	vmovdqu64	YMMWORD[128+rdi],ymm5
-	vpsrldq	ymm5,ymm5,8
-	vmovdqu64	YMMWORD[160+rdi],ymm16
-	vpsrldq	ymm16,ymm16,8
-	jmp	NEAR $L$blocks_vpmadd52_2x_key_loaded
-	ud2
-
-ALIGN	32
-$L$blocks_vpmadd52_2x_do:
-	vmovdqu64	ymm5{k1}{z},[((128+8))+rdi]
-	vmovdqu64	ymm16{k1}{z},[((160+8))+rdi]
-	vmovdqu64	ymm3{k1}{z},[((64+8))+rdi]
-	vmovdqu64	ymm4{k1}{z},[((96+8))+rdi]
-
-$L$blocks_vpmadd52_2x_key_loaded:
-	vmovdqu64	ymm26,YMMWORD[rsi]
-	vpxorq	ymm27,ymm27,ymm27
-	lea	rsi,[32+rsi]
-
-	vpunpcklqdq	ymm25,ymm26,ymm27
-	vpunpckhqdq	ymm27,ymm26,ymm27
-
-
-
-	vpsrlq	ymm26,ymm27,24
-	vporq	ymm26,ymm26,ymm31
-	vpaddq	ymm2,ymm2,ymm26
-	vpandq	ymm24,ymm25,ymm28
-	vpsrlq	ymm25,ymm25,44
-	vpsllq	ymm27,ymm27,20
-	vporq	ymm25,ymm25,ymm27
-	vpandq	ymm25,ymm25,ymm28
-
-	jmp	NEAR $L$tail_vpmadd52_2x
-	ud2
-
-ALIGN	32
-$L$oop_vpmadd52_4x:
-
-	vpaddq	ymm0,ymm0,ymm24
-	vpaddq	ymm1,ymm1,ymm25
-
-	vpxorq	ymm18,ymm18,ymm18
-	vpmadd52luq	ymm18,ymm16,ymm2
-	vpxorq	ymm19,ymm19,ymm19
-	vpmadd52huq	ymm19,ymm16,ymm2
-	vpxorq	ymm20,ymm20,ymm20
-	vpmadd52luq	ymm20,ymm17,ymm2
-	vpxorq	ymm21,ymm21,ymm21
-	vpmadd52huq	ymm21,ymm17,ymm2
-	vpxorq	ymm22,ymm22,ymm22
-	vpmadd52luq	ymm22,ymm3,ymm2
-	vpxorq	ymm23,ymm23,ymm23
-	vpmadd52huq	ymm23,ymm3,ymm2
-
-	vmovdqu64	ymm26,YMMWORD[rsi]
-	vmovdqu64	ymm27,YMMWORD[32+rsi]
-	lea	rsi,[64+rsi]
-	vpmadd52luq	ymm18,ymm3,ymm0
-	vpmadd52huq	ymm19,ymm3,ymm0
-	vpmadd52luq	ymm20,ymm4,ymm0
-	vpmadd52huq	ymm21,ymm4,ymm0
-	vpmadd52luq	ymm22,ymm5,ymm0
-	vpmadd52huq	ymm23,ymm5,ymm0
-
-	vpunpcklqdq	ymm25,ymm26,ymm27
-	vpunpckhqdq	ymm27,ymm26,ymm27
-	vpmadd52luq	ymm18,ymm17,ymm1
-	vpmadd52huq	ymm19,ymm17,ymm1
-	vpmadd52luq	ymm20,ymm3,ymm1
-	vpmadd52huq	ymm21,ymm3,ymm1
-	vpmadd52luq	ymm22,ymm4,ymm1
-	vpmadd52huq	ymm23,ymm4,ymm1
-
-
-
-	vpsrlq	ymm30,ymm18,44
-	vpsllq	ymm19,ymm19,8
-	vpandq	ymm0,ymm18,ymm28
-	vpaddq	ymm19,ymm19,ymm30
-
-	vpsrlq	ymm26,ymm27,24
-	vporq	ymm26,ymm26,ymm31
-	vpaddq	ymm20,ymm20,ymm19
-
-	vpsrlq	ymm30,ymm20,44
-	vpsllq	ymm21,ymm21,8
-	vpandq	ymm1,ymm20,ymm28
-	vpaddq	ymm21,ymm21,ymm30
-
-	vpandq	ymm24,ymm25,ymm28
-	vpsrlq	ymm25,ymm25,44
-	vpsllq	ymm27,ymm27,20
-	vpaddq	ymm22,ymm22,ymm21
-
-	vpsrlq	ymm30,ymm22,42
-	vpsllq	ymm23,ymm23,10
-	vpandq	ymm2,ymm22,ymm29
-	vpaddq	ymm23,ymm23,ymm30
-
-	vpaddq	ymm2,ymm2,ymm26
-	vpaddq	ymm0,ymm0,ymm23
-	vpsllq	ymm23,ymm23,2
-
-	vpaddq	ymm0,ymm0,ymm23
-	vporq	ymm25,ymm25,ymm27
-	vpandq	ymm25,ymm25,ymm28
-
-	vpsrlq	ymm30,ymm0,44
-	vpandq	ymm0,ymm0,ymm28
-
-	vpaddq	ymm1,ymm1,ymm30
-
-	sub	rdx,4
-	jnz	NEAR $L$oop_vpmadd52_4x
-
-$L$tail_vpmadd52_4x:
-	vmovdqu64	ymm5,YMMWORD[128+rdi]
-	vmovdqu64	ymm16,YMMWORD[160+rdi]
-	vmovdqu64	ymm3,YMMWORD[64+rdi]
-	vmovdqu64	ymm4,YMMWORD[96+rdi]
-
-$L$tail_vpmadd52_2x:
-	vpsllq	ymm17,ymm5,2
-	vpaddq	ymm17,ymm17,ymm5
-	vpsllq	ymm17,ymm17,2
-
-
-	vpaddq	ymm0,ymm0,ymm24
-	vpaddq	ymm1,ymm1,ymm25
-
-	vpxorq	ymm18,ymm18,ymm18
-	vpmadd52luq	ymm18,ymm16,ymm2
-	vpxorq	ymm19,ymm19,ymm19
-	vpmadd52huq	ymm19,ymm16,ymm2
-	vpxorq	ymm20,ymm20,ymm20
-	vpmadd52luq	ymm20,ymm17,ymm2
-	vpxorq	ymm21,ymm21,ymm21
-	vpmadd52huq	ymm21,ymm17,ymm2
-	vpxorq	ymm22,ymm22,ymm22
-	vpmadd52luq	ymm22,ymm3,ymm2
-	vpxorq	ymm23,ymm23,ymm23
-	vpmadd52huq	ymm23,ymm3,ymm2
-
-	vpmadd52luq	ymm18,ymm3,ymm0
-	vpmadd52huq	ymm19,ymm3,ymm0
-	vpmadd52luq	ymm20,ymm4,ymm0
-	vpmadd52huq	ymm21,ymm4,ymm0
-	vpmadd52luq	ymm22,ymm5,ymm0
-	vpmadd52huq	ymm23,ymm5,ymm0
-
-	vpmadd52luq	ymm18,ymm17,ymm1
-	vpmadd52huq	ymm19,ymm17,ymm1
-	vpmadd52luq	ymm20,ymm3,ymm1
-	vpmadd52huq	ymm21,ymm3,ymm1
-	vpmadd52luq	ymm22,ymm4,ymm1
-	vpmadd52huq	ymm23,ymm4,ymm1
-
-
-
-
-	mov	eax,1
-	kmovw	k1,eax
-	vpsrldq	ymm24,ymm18,8
-	vpsrldq	ymm0,ymm19,8
-	vpsrldq	ymm25,ymm20,8
-	vpsrldq	ymm1,ymm21,8
-	vpaddq	ymm18,ymm18,ymm24
-	vpaddq	ymm19,ymm19,ymm0
-	vpsrldq	ymm26,ymm22,8
-	vpsrldq	ymm2,ymm23,8
-	vpaddq	ymm20,ymm20,ymm25
-	vpaddq	ymm21,ymm21,ymm1
-	vpermq	ymm24,ymm18,0x2
-	vpermq	ymm0,ymm19,0x2
-	vpaddq	ymm22,ymm22,ymm26
-	vpaddq	ymm23,ymm23,ymm2
-
-	vpermq	ymm25,ymm20,0x2
-	vpermq	ymm1,ymm21,0x2
-	vpaddq	ymm18{k1}{z},ymm18,ymm24
-	vpaddq	ymm19{k1}{z},ymm19,ymm0
-	vpermq	ymm26,ymm22,0x2
-	vpermq	ymm2,ymm23,0x2
-	vpaddq	ymm20{k1}{z},ymm20,ymm25
-	vpaddq	ymm21{k1}{z},ymm21,ymm1
-	vpaddq	ymm22{k1}{z},ymm22,ymm26
-	vpaddq	ymm23{k1}{z},ymm23,ymm2
-
-
-
-	vpsrlq	ymm30,ymm18,44
-	vpsllq	ymm19,ymm19,8
-	vpandq	ymm0,ymm18,ymm28
-	vpaddq	ymm19,ymm19,ymm30
-
-	vpaddq	ymm20,ymm20,ymm19
-
-	vpsrlq	ymm30,ymm20,44
-	vpsllq	ymm21,ymm21,8
-	vpandq	ymm1,ymm20,ymm28
-	vpaddq	ymm21,ymm21,ymm30
-
-	vpaddq	ymm22,ymm22,ymm21
-
-	vpsrlq	ymm30,ymm22,42
-	vpsllq	ymm23,ymm23,10
-	vpandq	ymm2,ymm22,ymm29
-	vpaddq	ymm23,ymm23,ymm30
-
-	vpaddq	ymm0,ymm0,ymm23
-	vpsllq	ymm23,ymm23,2
-
-	vpaddq	ymm0,ymm0,ymm23
-
-	vpsrlq	ymm30,ymm0,44
-	vpandq	ymm0,ymm0,ymm28
-
-	vpaddq	ymm1,ymm1,ymm30
-
-
-	sub	rdx,2
-	ja	NEAR $L$blocks_vpmadd52_4x_do
-
-	vmovq	QWORD[rdi],xmm0
-	vmovq	QWORD[8+rdi],xmm1
-	vmovq	QWORD[16+rdi],xmm2
-	vzeroall
-
-$L$no_data_vpmadd52_4x:
-	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
-	mov	rsi,QWORD[16+rsp]
-	DB	0F3h,0C3h		;repret
-
-$L$SEH_end_poly1305_blocks_vpmadd52_4x:
-
-ALIGN	32
-poly1305_blocks_vpmadd52_8x:
-	mov	QWORD[8+rsp],rdi	;WIN64 prologue
-	mov	QWORD[16+rsp],rsi
-	mov	rax,rsp
-$L$SEH_begin_poly1305_blocks_vpmadd52_8x:
-	mov	rdi,rcx
-	mov	rsi,rdx
-	mov	rdx,r8
-	mov	rcx,r9
-
-
-
-	shr	rdx,4
-	jz	NEAR $L$no_data_vpmadd52_8x
-
-	shl	rcx,40
-	mov	r8,QWORD[64+rdi]
-
-	vmovdqa64	ymm28,YMMWORD[$L$x_mask44]
-	vmovdqa64	ymm29,YMMWORD[$L$x_mask42]
-
-	test	r8,r8
-	js	NEAR $L$init_vpmadd52
-
-	vmovq	xmm0,QWORD[rdi]
-	vmovq	xmm1,QWORD[8+rdi]
-	vmovq	xmm2,QWORD[16+rdi]
-
-$L$blocks_vpmadd52_8x:
-
-
-
-	vmovdqu64	ymm5,YMMWORD[128+rdi]
-	vmovdqu64	ymm16,YMMWORD[160+rdi]
-	vmovdqu64	ymm3,YMMWORD[64+rdi]
-	vmovdqu64	ymm4,YMMWORD[96+rdi]
-
-	vpsllq	ymm17,ymm5,2
-	vpaddq	ymm17,ymm17,ymm5
-	vpsllq	ymm17,ymm17,2
-
-	vpbroadcastq	ymm8,xmm5
-	vpbroadcastq	ymm6,xmm3
-	vpbroadcastq	ymm7,xmm4
-
-	vpxorq	ymm18,ymm18,ymm18
-	vpmadd52luq	ymm18,ymm16,ymm8
-	vpxorq	ymm19,ymm19,ymm19
-	vpmadd52huq	ymm19,ymm16,ymm8
-	vpxorq	ymm20,ymm20,ymm20
-	vpmadd52luq	ymm20,ymm17,ymm8
-	vpxorq	ymm21,ymm21,ymm21
-	vpmadd52huq	ymm21,ymm17,ymm8
-	vpxorq	ymm22,ymm22,ymm22
-	vpmadd52luq	ymm22,ymm3,ymm8
-	vpxorq	ymm23,ymm23,ymm23
-	vpmadd52huq	ymm23,ymm3,ymm8
-
-	vpmadd52luq	ymm18,ymm3,ymm6
-	vpmadd52huq	ymm19,ymm3,ymm6
-	vpmadd52luq	ymm20,ymm4,ymm6
-	vpmadd52huq	ymm21,ymm4,ymm6
-	vpmadd52luq	ymm22,ymm5,ymm6
-	vpmadd52huq	ymm23,ymm5,ymm6
-
-	vpmadd52luq	ymm18,ymm17,ymm7
-	vpmadd52huq	ymm19,ymm17,ymm7
-	vpmadd52luq	ymm20,ymm3,ymm7
-	vpmadd52huq	ymm21,ymm3,ymm7
-	vpmadd52luq	ymm22,ymm4,ymm7
-	vpmadd52huq	ymm23,ymm4,ymm7
-
-
-
-	vpsrlq	ymm30,ymm18,44
-	vpsllq	ymm19,ymm19,8
-	vpandq	ymm6,ymm18,ymm28
-	vpaddq	ymm19,ymm19,ymm30
-
-	vpaddq	ymm20,ymm20,ymm19
-
-	vpsrlq	ymm30,ymm20,44
-	vpsllq	ymm21,ymm21,8
-	vpandq	ymm7,ymm20,ymm28
-	vpaddq	ymm21,ymm21,ymm30
-
-	vpaddq	ymm22,ymm22,ymm21
-
-	vpsrlq	ymm30,ymm22,42
-	vpsllq	ymm23,ymm23,10
-	vpandq	ymm8,ymm22,ymm29
-	vpaddq	ymm23,ymm23,ymm30
-
-	vpaddq	ymm6,ymm6,ymm23
-	vpsllq	ymm23,ymm23,2
-
-	vpaddq	ymm6,ymm6,ymm23
-
-	vpsrlq	ymm30,ymm6,44
-	vpandq	ymm6,ymm6,ymm28
-
-	vpaddq	ymm7,ymm7,ymm30
-
-
-
-
-
-	vpunpcklqdq	ymm26,ymm8,ymm5
-	vpunpckhqdq	ymm5,ymm8,ymm5
-	vpunpcklqdq	ymm24,ymm6,ymm3
-	vpunpckhqdq	ymm3,ymm6,ymm3
-	vpunpcklqdq	ymm25,ymm7,ymm4
-	vpunpckhqdq	ymm4,ymm7,ymm4
-	vshufi64x2	zmm8,zmm26,zmm5,0x44
-	vshufi64x2	zmm6,zmm24,zmm3,0x44
-	vshufi64x2	zmm7,zmm25,zmm4,0x44
-
-	vmovdqu64	zmm26,ZMMWORD[rsi]
-	vmovdqu64	zmm27,ZMMWORD[64+rsi]
-	lea	rsi,[128+rsi]
-
-	vpsllq	zmm10,zmm8,2
-	vpsllq	zmm9,zmm7,2
-	vpaddq	zmm10,zmm10,zmm8
-	vpaddq	zmm9,zmm9,zmm7
-	vpsllq	zmm10,zmm10,2
-	vpsllq	zmm9,zmm9,2
-
-	vpbroadcastq	zmm31,rcx
-	vpbroadcastq	zmm28,xmm28
-	vpbroadcastq	zmm29,xmm29
-
-	vpbroadcastq	zmm16,xmm9
-	vpbroadcastq	zmm17,xmm10
-	vpbroadcastq	zmm3,xmm6
-	vpbroadcastq	zmm4,xmm7
-	vpbroadcastq	zmm5,xmm8
-
-	vpunpcklqdq	zmm25,zmm26,zmm27
-	vpunpckhqdq	zmm27,zmm26,zmm27
-
-
-
-	vpsrlq	zmm26,zmm27,24
-	vporq	zmm26,zmm26,zmm31
-	vpaddq	zmm2,zmm2,zmm26
-	vpandq	zmm24,zmm25,zmm28
-	vpsrlq	zmm25,zmm25,44
-	vpsllq	zmm27,zmm27,20
-	vporq	zmm25,zmm25,zmm27
-	vpandq	zmm25,zmm25,zmm28
-
-	sub	rdx,8
-	jz	NEAR $L$tail_vpmadd52_8x
-	jmp	NEAR $L$oop_vpmadd52_8x
-
-ALIGN	32
-$L$oop_vpmadd52_8x:
-
-	vpaddq	zmm0,zmm0,zmm24
-	vpaddq	zmm1,zmm1,zmm25
-
-	vpxorq	zmm18,zmm18,zmm18
-	vpmadd52luq	zmm18,zmm16,zmm2
-	vpxorq	zmm19,zmm19,zmm19
-	vpmadd52huq	zmm19,zmm16,zmm2
-	vpxorq	zmm20,zmm20,zmm20
-	vpmadd52luq	zmm20,zmm17,zmm2
-	vpxorq	zmm21,zmm21,zmm21
-	vpmadd52huq	zmm21,zmm17,zmm2
-	vpxorq	zmm22,zmm22,zmm22
-	vpmadd52luq	zmm22,zmm3,zmm2
-	vpxorq	zmm23,zmm23,zmm23
-	vpmadd52huq	zmm23,zmm3,zmm2
-
-	vmovdqu64	zmm26,ZMMWORD[rsi]
-	vmovdqu64	zmm27,ZMMWORD[64+rsi]
-	lea	rsi,[128+rsi]
-	vpmadd52luq	zmm18,zmm3,zmm0
-	vpmadd52huq	zmm19,zmm3,zmm0
-	vpmadd52luq	zmm20,zmm4,zmm0
-	vpmadd52huq	zmm21,zmm4,zmm0
-	vpmadd52luq	zmm22,zmm5,zmm0
-	vpmadd52huq	zmm23,zmm5,zmm0
-
-	vpunpcklqdq	zmm25,zmm26,zmm27
-	vpunpckhqdq	zmm27,zmm26,zmm27
-	vpmadd52luq	zmm18,zmm17,zmm1
-	vpmadd52huq	zmm19,zmm17,zmm1
-	vpmadd52luq	zmm20,zmm3,zmm1
-	vpmadd52huq	zmm21,zmm3,zmm1
-	vpmadd52luq	zmm22,zmm4,zmm1
-	vpmadd52huq	zmm23,zmm4,zmm1
-
-
-
-	vpsrlq	zmm30,zmm18,44
-	vpsllq	zmm19,zmm19,8
-	vpandq	zmm0,zmm18,zmm28
-	vpaddq	zmm19,zmm19,zmm30
-
-	vpsrlq	zmm26,zmm27,24
-	vporq	zmm26,zmm26,zmm31
-	vpaddq	zmm20,zmm20,zmm19
-
-	vpsrlq	zmm30,zmm20,44
-	vpsllq	zmm21,zmm21,8
-	vpandq	zmm1,zmm20,zmm28
-	vpaddq	zmm21,zmm21,zmm30
-
-	vpandq	zmm24,zmm25,zmm28
-	vpsrlq	zmm25,zmm25,44
-	vpsllq	zmm27,zmm27,20
-	vpaddq	zmm22,zmm22,zmm21
-
-	vpsrlq	zmm30,zmm22,42
-	vpsllq	zmm23,zmm23,10
-	vpandq	zmm2,zmm22,zmm29
-	vpaddq	zmm23,zmm23,zmm30
-
-	vpaddq	zmm2,zmm2,zmm26
-	vpaddq	zmm0,zmm0,zmm23
-	vpsllq	zmm23,zmm23,2
-
-	vpaddq	zmm0,zmm0,zmm23
-	vporq	zmm25,zmm25,zmm27
-	vpandq	zmm25,zmm25,zmm28
-
-	vpsrlq	zmm30,zmm0,44
-	vpandq	zmm0,zmm0,zmm28
-
-	vpaddq	zmm1,zmm1,zmm30
-
-	sub	rdx,8
-	jnz	NEAR $L$oop_vpmadd52_8x
-
-$L$tail_vpmadd52_8x:
-
-	vpaddq	zmm0,zmm0,zmm24
-	vpaddq	zmm1,zmm1,zmm25
-
-	vpxorq	zmm18,zmm18,zmm18
-	vpmadd52luq	zmm18,zmm9,zmm2
-	vpxorq	zmm19,zmm19,zmm19
-	vpmadd52huq	zmm19,zmm9,zmm2
-	vpxorq	zmm20,zmm20,zmm20
-	vpmadd52luq	zmm20,zmm10,zmm2
-	vpxorq	zmm21,zmm21,zmm21
-	vpmadd52huq	zmm21,zmm10,zmm2
-	vpxorq	zmm22,zmm22,zmm22
-	vpmadd52luq	zmm22,zmm6,zmm2
-	vpxorq	zmm23,zmm23,zmm23
-	vpmadd52huq	zmm23,zmm6,zmm2
-
-	vpmadd52luq	zmm18,zmm6,zmm0
-	vpmadd52huq	zmm19,zmm6,zmm0
-	vpmadd52luq	zmm20,zmm7,zmm0
-	vpmadd52huq	zmm21,zmm7,zmm0
-	vpmadd52luq	zmm22,zmm8,zmm0
-	vpmadd52huq	zmm23,zmm8,zmm0
-
-	vpmadd52luq	zmm18,zmm10,zmm1
-	vpmadd52huq	zmm19,zmm10,zmm1
-	vpmadd52luq	zmm20,zmm6,zmm1
-	vpmadd52huq	zmm21,zmm6,zmm1
-	vpmadd52luq	zmm22,zmm7,zmm1
-	vpmadd52huq	zmm23,zmm7,zmm1
-
-
-
-
-	mov	eax,1
-	kmovw	k1,eax
-	vpsrldq	zmm24,zmm18,8
-	vpsrldq	zmm0,zmm19,8
-	vpsrldq	zmm25,zmm20,8
-	vpsrldq	zmm1,zmm21,8
-	vpaddq	zmm18,zmm18,zmm24
-	vpaddq	zmm19,zmm19,zmm0
-	vpsrldq	zmm26,zmm22,8
-	vpsrldq	zmm2,zmm23,8
-	vpaddq	zmm20,zmm20,zmm25
-	vpaddq	zmm21,zmm21,zmm1
-	vpermq	zmm24,zmm18,0x2
-	vpermq	zmm0,zmm19,0x2
-	vpaddq	zmm22,zmm22,zmm26
-	vpaddq	zmm23,zmm23,zmm2
-
-	vpermq	zmm25,zmm20,0x2
-	vpermq	zmm1,zmm21,0x2
-	vpaddq	zmm18,zmm18,zmm24
-	vpaddq	zmm19,zmm19,zmm0
-	vpermq	zmm26,zmm22,0x2
-	vpermq	zmm2,zmm23,0x2
-	vpaddq	zmm20,zmm20,zmm25
-	vpaddq	zmm21,zmm21,zmm1
-	vextracti64x4	ymm24,zmm18,1
-	vextracti64x4	ymm0,zmm19,1
-	vpaddq	zmm22,zmm22,zmm26
-	vpaddq	zmm23,zmm23,zmm2
-
-	vextracti64x4	ymm25,zmm20,1
-	vextracti64x4	ymm1,zmm21,1
-	vextracti64x4	ymm26,zmm22,1
-	vextracti64x4	ymm2,zmm23,1
-	vpaddq	ymm18{k1}{z},ymm18,ymm24
-	vpaddq	ymm19{k1}{z},ymm19,ymm0
-	vpaddq	ymm20{k1}{z},ymm20,ymm25
-	vpaddq	ymm21{k1}{z},ymm21,ymm1
-	vpaddq	ymm22{k1}{z},ymm22,ymm26
-	vpaddq	ymm23{k1}{z},ymm23,ymm2
-
-
-
-	vpsrlq	ymm30,ymm18,44
-	vpsllq	ymm19,ymm19,8
-	vpandq	ymm0,ymm18,ymm28
-	vpaddq	ymm19,ymm19,ymm30
-
-	vpaddq	ymm20,ymm20,ymm19
-
-	vpsrlq	ymm30,ymm20,44
-	vpsllq	ymm21,ymm21,8
-	vpandq	ymm1,ymm20,ymm28
-	vpaddq	ymm21,ymm21,ymm30
-
-	vpaddq	ymm22,ymm22,ymm21
-
-	vpsrlq	ymm30,ymm22,42
-	vpsllq	ymm23,ymm23,10
-	vpandq	ymm2,ymm22,ymm29
-	vpaddq	ymm23,ymm23,ymm30
-
-	vpaddq	ymm0,ymm0,ymm23
-	vpsllq	ymm23,ymm23,2
-
-	vpaddq	ymm0,ymm0,ymm23
-
-	vpsrlq	ymm30,ymm0,44
-	vpandq	ymm0,ymm0,ymm28
-
-	vpaddq	ymm1,ymm1,ymm30
-
-
-
-	vmovq	QWORD[rdi],xmm0
-	vmovq	QWORD[8+rdi],xmm1
-	vmovq	QWORD[16+rdi],xmm2
-	vzeroall
-
-$L$no_data_vpmadd52_8x:
-	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
-	mov	rsi,QWORD[16+rsp]
-	DB	0F3h,0C3h		;repret
-
-$L$SEH_end_poly1305_blocks_vpmadd52_8x:
-
-ALIGN	32
-poly1305_emit_base2_44:
-	mov	QWORD[8+rsp],rdi	;WIN64 prologue
-	mov	QWORD[16+rsp],rsi
-	mov	rax,rsp
-$L$SEH_begin_poly1305_emit_base2_44:
-	mov	rdi,rcx
-	mov	rsi,rdx
-	mov	rdx,r8
-
-
-
-DB	243,15,30,250
-	mov	r8,QWORD[rdi]
-	mov	r9,QWORD[8+rdi]
-	mov	r10,QWORD[16+rdi]
-
-	mov	rax,r9
-	shr	r9,20
-	shl	rax,44
-	mov	rcx,r10
-	shr	r10,40
-	shl	rcx,24
-
-	add	r8,rax
-	adc	r9,rcx
-	adc	r10,0
-
-	mov	rax,r8
-	add	r8,5
-	mov	rcx,r9
-	adc	r9,0
-	adc	r10,0
-	shr	r10,2
-	cmovnz	rax,r8
-	cmovnz	rcx,r9
-
-	add	rax,QWORD[rdx]
-	adc	rcx,QWORD[8+rdx]
-	mov	QWORD[rsi],rax
-	mov	QWORD[8+rsi],rcx
-
-	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
-	mov	rsi,QWORD[16+rsp]
-	DB	0F3h,0C3h		;repret
-
-$L$SEH_end_poly1305_emit_base2_44:
 ALIGN	64
 $L$const:
 $L$mask24:
diff --git a/deps/openssl/config/archs/VC-WIN64A/asm_avx2/include/openssl/opensslv.h b/deps/openssl/config/archs/VC-WIN64A/asm_avx2/include/openssl/opensslv.h
index 38b44f1054ad3d..a410f0eddf361c 100644
--- a/deps/openssl/config/archs/VC-WIN64A/asm_avx2/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/VC-WIN64A/asm_avx2/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/VC-WIN64A/asm_avx2/include/openssl/pkcs7.h b/deps/openssl/config/archs/VC-WIN64A/asm_avx2/include/openssl/pkcs7.h
index 3978fd087bca3b..0a95a93e59e262 100644
--- a/deps/openssl/config/archs/VC-WIN64A/asm_avx2/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/VC-WIN64A/asm_avx2/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/VC-WIN64A/no-asm/configdata.pm b/deps/openssl/config/archs/VC-WIN64A/no-asm/configdata.pm
index 37fe7ad1554464..8216effe724d74 100644
--- a/deps/openssl/config/archs/VC-WIN64A/no-asm/configdata.pm
+++ b/deps/openssl/config/archs/VC-WIN64A/no-asm/configdata.pm
@@ -166,7 +166,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -218,7 +218,7 @@ our %config = (
     ],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-asm no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -271,11 +271,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "VC-WIN64A",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "lib",
@@ -290,7 +290,7 @@ our %target = (
     "LDFLAGS" => "/nologo /debug",
     "MT" => "mt",
     "MTFLAGS" => "-nologo",
-    "RANLIB" => "CODE(0x55ad7db3afe8)",
+    "RANLIB" => "CODE(0x555a33e1b438)",
     "RC" => "rc",
     "_conf_fname_int" => [
         "Configurations/00-base-templates.conf",
@@ -356,7 +356,7 @@ our %target = (
     "mtoutflag" => "-outputresource:",
     "multilib" => "-x64",
     "perl_platform" => "Windows::MSVC",
-    "perlasm_scheme" => "auto",
+    "perlasm_scheme" => "nasm",
     "rcoutflag" => "/fo",
     "shared_cflag" => "",
     "shared_defflag" => "",
diff --git a/deps/openssl/config/archs/VC-WIN64A/no-asm/crypto/buildinf.h b/deps/openssl/config/archs/VC-WIN64A/no-asm/crypto/buildinf.h
index f0e9d087e2267d..369ab9a8a4cd45 100644
--- a/deps/openssl/config/archs/VC-WIN64A/no-asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/VC-WIN64A/no-asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: "
-#define DATE "built on: Sun Aug  6 00:43:05 2023 UTC"
+#define DATE "built on: Thu Oct 26 15:04:07 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/VC-WIN64A/no-asm/include/openssl/opensslv.h b/deps/openssl/config/archs/VC-WIN64A/no-asm/include/openssl/opensslv.h
index 38b44f1054ad3d..a410f0eddf361c 100644
--- a/deps/openssl/config/archs/VC-WIN64A/no-asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/VC-WIN64A/no-asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/VC-WIN64A/no-asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/VC-WIN64A/no-asm/include/openssl/pkcs7.h
index 3978fd087bca3b..0a95a93e59e262 100644
--- a/deps/openssl/config/archs/VC-WIN64A/no-asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/VC-WIN64A/no-asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/aix64-gcc-as/asm/configdata.pm b/deps/openssl/config/archs/aix64-gcc-as/asm/configdata.pm
index ca05289b718d86..510129745cd0c6 100644
--- a/deps/openssl/config/archs/aix64-gcc-as/asm/configdata.pm
+++ b/deps/openssl/config/archs/aix64-gcc-as/asm/configdata.pm
@@ -156,7 +156,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -206,7 +206,7 @@ our %config = (
     ],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -258,11 +258,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "aix64-gcc-as",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar -X64",
diff --git a/deps/openssl/config/archs/aix64-gcc-as/asm/crypto/buildinf.h b/deps/openssl/config/archs/aix64-gcc-as/asm/crypto/buildinf.h
index 3f01432e2b1840..7d0c5f9befa8ba 100644
--- a/deps/openssl/config/archs/aix64-gcc-as/asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/aix64-gcc-as/asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: aix64-gcc-as"
-#define DATE "built on: Sun Aug  6 00:24:21 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:47:40 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/aix64-gcc-as/asm/include/openssl/opensslv.h b/deps/openssl/config/archs/aix64-gcc-as/asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/aix64-gcc-as/asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/aix64-gcc-as/asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/aix64-gcc-as/asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/aix64-gcc-as/asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/aix64-gcc-as/asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/aix64-gcc-as/asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/aix64-gcc-as/asm_avx2/configdata.pm b/deps/openssl/config/archs/aix64-gcc-as/asm_avx2/configdata.pm
index a8d6fc77f0ac2d..65c498fd6d0e27 100644
--- a/deps/openssl/config/archs/aix64-gcc-as/asm_avx2/configdata.pm
+++ b/deps/openssl/config/archs/aix64-gcc-as/asm_avx2/configdata.pm
@@ -156,7 +156,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -206,7 +206,7 @@ our %config = (
     ],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -258,11 +258,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "aix64-gcc-as",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar -X64",
diff --git a/deps/openssl/config/archs/aix64-gcc-as/asm_avx2/crypto/buildinf.h b/deps/openssl/config/archs/aix64-gcc-as/asm_avx2/crypto/buildinf.h
index ec624a65971b4b..f2880ddb869f23 100644
--- a/deps/openssl/config/archs/aix64-gcc-as/asm_avx2/crypto/buildinf.h
+++ b/deps/openssl/config/archs/aix64-gcc-as/asm_avx2/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: aix64-gcc-as"
-#define DATE "built on: Sun Aug  6 00:24:41 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:47:59 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/aix64-gcc-as/asm_avx2/include/openssl/opensslv.h b/deps/openssl/config/archs/aix64-gcc-as/asm_avx2/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/aix64-gcc-as/asm_avx2/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/aix64-gcc-as/asm_avx2/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/aix64-gcc-as/asm_avx2/include/openssl/pkcs7.h b/deps/openssl/config/archs/aix64-gcc-as/asm_avx2/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/aix64-gcc-as/asm_avx2/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/aix64-gcc-as/asm_avx2/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/aix64-gcc-as/no-asm/configdata.pm b/deps/openssl/config/archs/aix64-gcc-as/no-asm/configdata.pm
index fdfbcce8adc844..24ad5c6241368a 100644
--- a/deps/openssl/config/archs/aix64-gcc-as/no-asm/configdata.pm
+++ b/deps/openssl/config/archs/aix64-gcc-as/no-asm/configdata.pm
@@ -154,7 +154,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -205,7 +205,7 @@ our %config = (
     ],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-asm no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -258,11 +258,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "aix64-gcc-as",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar -X64",
diff --git a/deps/openssl/config/archs/aix64-gcc-as/no-asm/crypto/buildinf.h b/deps/openssl/config/archs/aix64-gcc-as/no-asm/crypto/buildinf.h
index 83233146a50c97..f7891d1f2dcf82 100644
--- a/deps/openssl/config/archs/aix64-gcc-as/no-asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/aix64-gcc-as/no-asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: aix64-gcc-as"
-#define DATE "built on: Sun Aug  6 00:25:01 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:48:18 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/aix64-gcc-as/no-asm/include/openssl/opensslv.h b/deps/openssl/config/archs/aix64-gcc-as/no-asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/aix64-gcc-as/no-asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/aix64-gcc-as/no-asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/aix64-gcc-as/no-asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/aix64-gcc-as/no-asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/aix64-gcc-as/no-asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/aix64-gcc-as/no-asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/darwin-i386-cc/asm/configdata.pm b/deps/openssl/config/archs/darwin-i386-cc/asm/configdata.pm
index ba53b9f9cea130..ee6540933123b5 100644
--- a/deps/openssl/config/archs/darwin-i386-cc/asm/configdata.pm
+++ b/deps/openssl/config/archs/darwin-i386-cc/asm/configdata.pm
@@ -156,7 +156,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -206,7 +206,7 @@ our %config = (
     ],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -258,11 +258,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "darwin-i386-cc",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/darwin-i386-cc/asm/crypto/buildinf.h b/deps/openssl/config/archs/darwin-i386-cc/asm/crypto/buildinf.h
index e98ef7735cb4ed..10dc2211417972 100644
--- a/deps/openssl/config/archs/darwin-i386-cc/asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/darwin-i386-cc/asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: darwin-i386-cc"
-#define DATE "built on: Sun Aug  6 00:28:31 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:51:44 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/darwin-i386-cc/asm/include/openssl/opensslv.h b/deps/openssl/config/archs/darwin-i386-cc/asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/darwin-i386-cc/asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/darwin-i386-cc/asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/darwin-i386-cc/asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/darwin-i386-cc/asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/darwin-i386-cc/asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/darwin-i386-cc/asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/darwin-i386-cc/asm_avx2/configdata.pm b/deps/openssl/config/archs/darwin-i386-cc/asm_avx2/configdata.pm
index a1999fe03a4772..6b70420111afc6 100644
--- a/deps/openssl/config/archs/darwin-i386-cc/asm_avx2/configdata.pm
+++ b/deps/openssl/config/archs/darwin-i386-cc/asm_avx2/configdata.pm
@@ -156,7 +156,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -206,7 +206,7 @@ our %config = (
     ],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -258,11 +258,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "darwin-i386-cc",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/darwin-i386-cc/asm_avx2/crypto/buildinf.h b/deps/openssl/config/archs/darwin-i386-cc/asm_avx2/crypto/buildinf.h
index 76159a1731d678..f2e82653eee930 100644
--- a/deps/openssl/config/archs/darwin-i386-cc/asm_avx2/crypto/buildinf.h
+++ b/deps/openssl/config/archs/darwin-i386-cc/asm_avx2/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: darwin-i386-cc"
-#define DATE "built on: Sun Aug  6 00:28:51 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:52:03 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/darwin-i386-cc/asm_avx2/include/openssl/opensslv.h b/deps/openssl/config/archs/darwin-i386-cc/asm_avx2/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/darwin-i386-cc/asm_avx2/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/darwin-i386-cc/asm_avx2/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/darwin-i386-cc/asm_avx2/include/openssl/pkcs7.h b/deps/openssl/config/archs/darwin-i386-cc/asm_avx2/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/darwin-i386-cc/asm_avx2/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/darwin-i386-cc/asm_avx2/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/darwin-i386-cc/no-asm/configdata.pm b/deps/openssl/config/archs/darwin-i386-cc/no-asm/configdata.pm
index 97fab50db92bdf..51670419239bfc 100644
--- a/deps/openssl/config/archs/darwin-i386-cc/no-asm/configdata.pm
+++ b/deps/openssl/config/archs/darwin-i386-cc/no-asm/configdata.pm
@@ -154,7 +154,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -205,7 +205,7 @@ our %config = (
     ],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-asm no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -258,11 +258,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "darwin-i386-cc",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/darwin-i386-cc/no-asm/crypto/buildinf.h b/deps/openssl/config/archs/darwin-i386-cc/no-asm/crypto/buildinf.h
index 67ace143c5c393..f9b9c4c980b695 100644
--- a/deps/openssl/config/archs/darwin-i386-cc/no-asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/darwin-i386-cc/no-asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: darwin-i386-cc"
-#define DATE "built on: Sun Aug  6 00:29:11 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:52:23 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/darwin-i386-cc/no-asm/include/openssl/opensslv.h b/deps/openssl/config/archs/darwin-i386-cc/no-asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/darwin-i386-cc/no-asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/darwin-i386-cc/no-asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/darwin-i386-cc/no-asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/darwin-i386-cc/no-asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/darwin-i386-cc/no-asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/darwin-i386-cc/no-asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/darwin64-arm64-cc/asm/configdata.pm b/deps/openssl/config/archs/darwin64-arm64-cc/asm/configdata.pm
index 9b51a15ef51371..532f2649c95127 100644
--- a/deps/openssl/config/archs/darwin64-arm64-cc/asm/configdata.pm
+++ b/deps/openssl/config/archs/darwin64-arm64-cc/asm/configdata.pm
@@ -156,7 +156,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -206,7 +206,7 @@ our %config = (
     ],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -258,11 +258,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "darwin64-arm64-cc",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/darwin64-arm64-cc/asm/crypto/aes/aesv8-armx.S b/deps/openssl/config/archs/darwin64-arm64-cc/asm/crypto/aes/aesv8-armx.S
index 5e3afc1ced813d..ae20ad9ff6fbcb 100644
--- a/deps/openssl/config/archs/darwin64-arm64-cc/asm/crypto/aes/aesv8-armx.S
+++ b/deps/openssl/config/archs/darwin64-arm64-cc/asm/crypto/aes/aesv8-armx.S
@@ -103,7 +103,7 @@ L192:
 Loop192:
 	tbl	v6.16b,{v4.16b},v2.16b
 	ext	v5.16b,v0.16b,v3.16b,#12
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
 	st1	{v4.4s},[x2],#16
 	sub	x2,x2,#8
 #else
@@ -1510,7 +1510,7 @@ _aes_v8_ctr32_encrypt_blocks:
 	ldr	w5,[x3,#240]
 
 	ldr	w8, [x4, #12]
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
 	ld1	{v0.16b},[x4]
 #else
 	ld1	{v0.4s},[x4]
@@ -1527,7 +1527,7 @@ _aes_v8_ctr32_encrypt_blocks:
 	add	x7,x3,#32
 	mov	w6,w5
 	csel	x12,xzr,x12,lo
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev	w8, w8
 #endif
 	orr	v1.16b,v0.16b,v0.16b
diff --git a/deps/openssl/config/archs/darwin64-arm64-cc/asm/crypto/buildinf.h b/deps/openssl/config/archs/darwin64-arm64-cc/asm/crypto/buildinf.h
index 2e38ca1fc8f695..25b8011da926c1 100644
--- a/deps/openssl/config/archs/darwin64-arm64-cc/asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/darwin64-arm64-cc/asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: darwin64-arm64-cc"
-#define DATE "built on: Sun Aug  6 00:29:30 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:52:40 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/darwin64-arm64-cc/asm/crypto/modes/ghashv8-armx.S b/deps/openssl/config/archs/darwin64-arm64-cc/asm/crypto/modes/ghashv8-armx.S
index 200c0d031253ea..dc71d8508de6f8 100644
--- a/deps/openssl/config/archs/darwin64-arm64-cc/asm/crypto/modes/ghashv8-armx.S
+++ b/deps/openssl/config/archs/darwin64-arm64-cc/asm/crypto/modes/ghashv8-armx.S
@@ -101,7 +101,7 @@ _gcm_gmult_v8:
 	movi	v19.16b,#0xe1
 	ld1	{v20.2d,v21.2d},[x1]	//load twisted H, ...
 	shl	v19.2d,v19.2d,#57
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v17.16b,v17.16b
 #endif
 	ext	v3.16b,v17.16b,v17.16b,#8
@@ -126,7 +126,7 @@ _gcm_gmult_v8:
 	eor	v18.16b,v18.16b,v2.16b
 	eor	v0.16b,v0.16b,v18.16b
 
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v0.16b,v0.16b
 #endif
 	ext	v0.16b,v0.16b,v0.16b,#8
@@ -163,14 +163,14 @@ _gcm_ghash_v8:
 	ext	v0.16b,v0.16b,v0.16b,#8		//rotate Xi
 	ld1	{v16.2d},[x2],#16	//load [rotated] I[0]
 	shl	v19.2d,v19.2d,#57		//compose 0xc2.0 constant
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v16.16b,v16.16b
 	rev64	v0.16b,v0.16b
 #endif
 	ext	v3.16b,v16.16b,v16.16b,#8		//rotate I[0]
 	b.lo	Lodd_tail_v8		//x3 was less than 32
 	ld1	{v17.2d},[x2],x12	//load [rotated] I[1]
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v17.16b,v17.16b
 #endif
 	ext	v7.16b,v17.16b,v17.16b,#8
@@ -202,13 +202,13 @@ Loop_mod2x_v8:
 	eor	v18.16b,v0.16b,v2.16b
 	eor	v1.16b,v1.16b,v17.16b
 	ld1	{v17.2d},[x2],x12	//load [rotated] I[i+3]
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v16.16b,v16.16b
 #endif
 	eor	v1.16b,v1.16b,v18.16b
 	pmull	v18.1q,v0.1d,v19.1d		//1st phase of reduction
 
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v17.16b,v17.16b
 #endif
 	ins	v2.d[0],v1.d[1]
@@ -258,7 +258,7 @@ Lodd_tail_v8:
 	eor	v0.16b,v0.16b,v18.16b
 
 Ldone_v8:
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v0.16b,v0.16b
 #endif
 	ext	v0.16b,v0.16b,v0.16b,#8
@@ -277,7 +277,7 @@ Lgcm_ghash_v8_4x:
 	shl	v19.2d,v19.2d,#57		//compose 0xc2.0 constant
 
 	ld1	{v4.2d,v5.2d,v6.2d,v7.2d},[x2],#64
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v0.16b,v0.16b
 	rev64	v5.16b,v5.16b
 	rev64	v6.16b,v6.16b
@@ -321,7 +321,7 @@ Loop4x:
 	eor	v16.16b,v4.16b,v0.16b
 	ld1	{v4.2d,v5.2d,v6.2d,v7.2d},[x2],#64
 	ext	v3.16b,v16.16b,v16.16b,#8
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v5.16b,v5.16b
 	rev64	v6.16b,v6.16b
 	rev64	v7.16b,v7.16b
@@ -404,7 +404,7 @@ Lthree:
 	eor	v1.16b,v1.16b,v17.16b
 	ld1	{v4.2d,v5.2d,v6.2d},[x2]
 	eor	v1.16b,v1.16b,v18.16b
-#ifndef	__ARMEB__
+#ifndef	__AARCH64EB__
 	rev64	v5.16b,v5.16b
 	rev64	v6.16b,v6.16b
 	rev64	v4.16b,v4.16b
@@ -456,7 +456,7 @@ Ltwo:
 	eor	v1.16b,v1.16b,v17.16b
 	ld1	{v4.2d,v5.2d},[x2]
 	eor	v1.16b,v1.16b,v18.16b
-#ifndef	__ARMEB__
+#ifndef	__AARCH64EB__
 	rev64	v5.16b,v5.16b
 	rev64	v4.16b,v4.16b
 #endif
@@ -499,7 +499,7 @@ Lone:
 	eor	v1.16b,v1.16b,v17.16b
 	ld1	{v4.2d},[x2]
 	eor	v1.16b,v1.16b,v18.16b
-#ifndef	__ARMEB__
+#ifndef	__AARCH64EB__
 	rev64	v4.16b,v4.16b
 #endif
 
@@ -539,7 +539,7 @@ Ldone4x:
 	eor	v0.16b,v0.16b,v18.16b
 	ext	v0.16b,v0.16b,v0.16b,#8
 
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v0.16b,v0.16b
 #endif
 	st1	{v0.2d},[x0]		//write out Xi
diff --git a/deps/openssl/config/archs/darwin64-arm64-cc/asm/crypto/poly1305/poly1305-armv8.S b/deps/openssl/config/archs/darwin64-arm64-cc/asm/crypto/poly1305/poly1305-armv8.S
index 90b6d357ac1483..a044e14cb61f5f 100644
--- a/deps/openssl/config/archs/darwin64-arm64-cc/asm/crypto/poly1305/poly1305-armv8.S
+++ b/deps/openssl/config/archs/darwin64-arm64-cc/asm/crypto/poly1305/poly1305-armv8.S
@@ -28,7 +28,7 @@ _poly1305_init:
 	ldp	x7,x8,[x1]		// load key
 	mov	x9,#0xfffffffc0fffffff
 	movk	x9,#0x0fff,lsl#48
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x7,x7			// flip bytes
 	rev	x8,x8
 #endif
@@ -75,7 +75,7 @@ Lpoly1305_blocks:
 Loop:
 	ldp	x10,x11,[x1],#16	// load input
 	sub	x2,x2,#16
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x10,x10
 	rev	x11,x11
 #endif
@@ -140,13 +140,13 @@ Lpoly1305_emit:
 	csel	x4,x4,x12,eq
 	csel	x5,x5,x13,eq
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	ror	x10,x10,#32		// flip nonce words
 	ror	x11,x11,#32
 #endif
 	adds	x4,x4,x10		// accumulate nonce
 	adc	x5,x5,x11
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x4,x4			// flip output bytes
 	rev	x5,x5
 #endif
@@ -266,7 +266,7 @@ Lblocks_neon:
 	adcs	x5,x5,xzr
 	adc	x6,x6,xzr
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x12,x12
 	rev	x13,x13
 #endif
@@ -312,7 +312,7 @@ Lbase2_64_neon:
 	ldp	x12,x13,[x1],#16	// load input
 	sub	x2,x2,#16
 	add	x9,x8,x8,lsr#2	// s1 = r1 + (r1 >> 2)
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x12,x12
 	rev	x13,x13
 #endif
@@ -397,7 +397,7 @@ Ldo_neon:
 	lsl	x3,x3,#24
 	add	x15,x0,#48
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x8,x8
 	rev	x12,x12
 	rev	x9,x9
@@ -433,7 +433,7 @@ Ldo_neon:
 	ld1	{v4.4s,v5.4s,v6.4s,v7.4s},[x15],#64
 	ld1	{v8.4s},[x15]
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x8,x8
 	rev	x12,x12
 	rev	x9,x9
@@ -494,7 +494,7 @@ Loop_neon:
 	umull	v20.2d,v14.2s,v1.s[2]
 	ldp	x9,x13,[x16],#48
 	umull	v19.2d,v14.2s,v0.s[2]
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x8,x8
 	rev	x12,x12
 	rev	x9,x9
@@ -559,7 +559,7 @@ Loop_neon:
 	umlal	v23.2d,v11.2s,v3.s[0]
 	umlal	v20.2d,v11.2s,v8.s[0]
 	umlal	v21.2d,v11.2s,v0.s[0]
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x8,x8
 	rev	x12,x12
 	rev	x9,x9
@@ -840,13 +840,13 @@ Lpoly1305_emit_neon:
 	csel	x4,x4,x12,eq
 	csel	x5,x5,x13,eq
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	ror	x10,x10,#32		// flip nonce words
 	ror	x11,x11,#32
 #endif
 	adds	x4,x4,x10		// accumulate nonce
 	adc	x5,x5,x11
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x4,x4			// flip output bytes
 	rev	x5,x5
 #endif
diff --git a/deps/openssl/config/archs/darwin64-arm64-cc/asm/include/openssl/opensslv.h b/deps/openssl/config/archs/darwin64-arm64-cc/asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/darwin64-arm64-cc/asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/darwin64-arm64-cc/asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/darwin64-arm64-cc/asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/darwin64-arm64-cc/asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/darwin64-arm64-cc/asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/darwin64-arm64-cc/asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/configdata.pm b/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/configdata.pm
index a465039cbfa855..ce36db2197645b 100644
--- a/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/configdata.pm
+++ b/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/configdata.pm
@@ -156,7 +156,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -206,7 +206,7 @@ our %config = (
     ],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -258,11 +258,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "darwin64-arm64-cc",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/crypto/aes/aesv8-armx.S b/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/crypto/aes/aesv8-armx.S
index 5e3afc1ced813d..ae20ad9ff6fbcb 100644
--- a/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/crypto/aes/aesv8-armx.S
+++ b/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/crypto/aes/aesv8-armx.S
@@ -103,7 +103,7 @@ L192:
 Loop192:
 	tbl	v6.16b,{v4.16b},v2.16b
 	ext	v5.16b,v0.16b,v3.16b,#12
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
 	st1	{v4.4s},[x2],#16
 	sub	x2,x2,#8
 #else
@@ -1510,7 +1510,7 @@ _aes_v8_ctr32_encrypt_blocks:
 	ldr	w5,[x3,#240]
 
 	ldr	w8, [x4, #12]
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
 	ld1	{v0.16b},[x4]
 #else
 	ld1	{v0.4s},[x4]
@@ -1527,7 +1527,7 @@ _aes_v8_ctr32_encrypt_blocks:
 	add	x7,x3,#32
 	mov	w6,w5
 	csel	x12,xzr,x12,lo
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev	w8, w8
 #endif
 	orr	v1.16b,v0.16b,v0.16b
diff --git a/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/crypto/buildinf.h b/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/crypto/buildinf.h
index 513091049d0260..398666786c6285 100644
--- a/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/crypto/buildinf.h
+++ b/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: darwin64-arm64-cc"
-#define DATE "built on: Sun Aug  6 00:29:49 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:52:59 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/crypto/modes/ghashv8-armx.S b/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/crypto/modes/ghashv8-armx.S
index 200c0d031253ea..dc71d8508de6f8 100644
--- a/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/crypto/modes/ghashv8-armx.S
+++ b/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/crypto/modes/ghashv8-armx.S
@@ -101,7 +101,7 @@ _gcm_gmult_v8:
 	movi	v19.16b,#0xe1
 	ld1	{v20.2d,v21.2d},[x1]	//load twisted H, ...
 	shl	v19.2d,v19.2d,#57
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v17.16b,v17.16b
 #endif
 	ext	v3.16b,v17.16b,v17.16b,#8
@@ -126,7 +126,7 @@ _gcm_gmult_v8:
 	eor	v18.16b,v18.16b,v2.16b
 	eor	v0.16b,v0.16b,v18.16b
 
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v0.16b,v0.16b
 #endif
 	ext	v0.16b,v0.16b,v0.16b,#8
@@ -163,14 +163,14 @@ _gcm_ghash_v8:
 	ext	v0.16b,v0.16b,v0.16b,#8		//rotate Xi
 	ld1	{v16.2d},[x2],#16	//load [rotated] I[0]
 	shl	v19.2d,v19.2d,#57		//compose 0xc2.0 constant
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v16.16b,v16.16b
 	rev64	v0.16b,v0.16b
 #endif
 	ext	v3.16b,v16.16b,v16.16b,#8		//rotate I[0]
 	b.lo	Lodd_tail_v8		//x3 was less than 32
 	ld1	{v17.2d},[x2],x12	//load [rotated] I[1]
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v17.16b,v17.16b
 #endif
 	ext	v7.16b,v17.16b,v17.16b,#8
@@ -202,13 +202,13 @@ Loop_mod2x_v8:
 	eor	v18.16b,v0.16b,v2.16b
 	eor	v1.16b,v1.16b,v17.16b
 	ld1	{v17.2d},[x2],x12	//load [rotated] I[i+3]
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v16.16b,v16.16b
 #endif
 	eor	v1.16b,v1.16b,v18.16b
 	pmull	v18.1q,v0.1d,v19.1d		//1st phase of reduction
 
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v17.16b,v17.16b
 #endif
 	ins	v2.d[0],v1.d[1]
@@ -258,7 +258,7 @@ Lodd_tail_v8:
 	eor	v0.16b,v0.16b,v18.16b
 
 Ldone_v8:
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v0.16b,v0.16b
 #endif
 	ext	v0.16b,v0.16b,v0.16b,#8
@@ -277,7 +277,7 @@ Lgcm_ghash_v8_4x:
 	shl	v19.2d,v19.2d,#57		//compose 0xc2.0 constant
 
 	ld1	{v4.2d,v5.2d,v6.2d,v7.2d},[x2],#64
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v0.16b,v0.16b
 	rev64	v5.16b,v5.16b
 	rev64	v6.16b,v6.16b
@@ -321,7 +321,7 @@ Loop4x:
 	eor	v16.16b,v4.16b,v0.16b
 	ld1	{v4.2d,v5.2d,v6.2d,v7.2d},[x2],#64
 	ext	v3.16b,v16.16b,v16.16b,#8
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v5.16b,v5.16b
 	rev64	v6.16b,v6.16b
 	rev64	v7.16b,v7.16b
@@ -404,7 +404,7 @@ Lthree:
 	eor	v1.16b,v1.16b,v17.16b
 	ld1	{v4.2d,v5.2d,v6.2d},[x2]
 	eor	v1.16b,v1.16b,v18.16b
-#ifndef	__ARMEB__
+#ifndef	__AARCH64EB__
 	rev64	v5.16b,v5.16b
 	rev64	v6.16b,v6.16b
 	rev64	v4.16b,v4.16b
@@ -456,7 +456,7 @@ Ltwo:
 	eor	v1.16b,v1.16b,v17.16b
 	ld1	{v4.2d,v5.2d},[x2]
 	eor	v1.16b,v1.16b,v18.16b
-#ifndef	__ARMEB__
+#ifndef	__AARCH64EB__
 	rev64	v5.16b,v5.16b
 	rev64	v4.16b,v4.16b
 #endif
@@ -499,7 +499,7 @@ Lone:
 	eor	v1.16b,v1.16b,v17.16b
 	ld1	{v4.2d},[x2]
 	eor	v1.16b,v1.16b,v18.16b
-#ifndef	__ARMEB__
+#ifndef	__AARCH64EB__
 	rev64	v4.16b,v4.16b
 #endif
 
@@ -539,7 +539,7 @@ Ldone4x:
 	eor	v0.16b,v0.16b,v18.16b
 	ext	v0.16b,v0.16b,v0.16b,#8
 
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v0.16b,v0.16b
 #endif
 	st1	{v0.2d},[x0]		//write out Xi
diff --git a/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/crypto/poly1305/poly1305-armv8.S b/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/crypto/poly1305/poly1305-armv8.S
index 90b6d357ac1483..a044e14cb61f5f 100644
--- a/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/crypto/poly1305/poly1305-armv8.S
+++ b/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/crypto/poly1305/poly1305-armv8.S
@@ -28,7 +28,7 @@ _poly1305_init:
 	ldp	x7,x8,[x1]		// load key
 	mov	x9,#0xfffffffc0fffffff
 	movk	x9,#0x0fff,lsl#48
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x7,x7			// flip bytes
 	rev	x8,x8
 #endif
@@ -75,7 +75,7 @@ Lpoly1305_blocks:
 Loop:
 	ldp	x10,x11,[x1],#16	// load input
 	sub	x2,x2,#16
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x10,x10
 	rev	x11,x11
 #endif
@@ -140,13 +140,13 @@ Lpoly1305_emit:
 	csel	x4,x4,x12,eq
 	csel	x5,x5,x13,eq
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	ror	x10,x10,#32		// flip nonce words
 	ror	x11,x11,#32
 #endif
 	adds	x4,x4,x10		// accumulate nonce
 	adc	x5,x5,x11
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x4,x4			// flip output bytes
 	rev	x5,x5
 #endif
@@ -266,7 +266,7 @@ Lblocks_neon:
 	adcs	x5,x5,xzr
 	adc	x6,x6,xzr
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x12,x12
 	rev	x13,x13
 #endif
@@ -312,7 +312,7 @@ Lbase2_64_neon:
 	ldp	x12,x13,[x1],#16	// load input
 	sub	x2,x2,#16
 	add	x9,x8,x8,lsr#2	// s1 = r1 + (r1 >> 2)
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x12,x12
 	rev	x13,x13
 #endif
@@ -397,7 +397,7 @@ Ldo_neon:
 	lsl	x3,x3,#24
 	add	x15,x0,#48
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x8,x8
 	rev	x12,x12
 	rev	x9,x9
@@ -433,7 +433,7 @@ Ldo_neon:
 	ld1	{v4.4s,v5.4s,v6.4s,v7.4s},[x15],#64
 	ld1	{v8.4s},[x15]
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x8,x8
 	rev	x12,x12
 	rev	x9,x9
@@ -494,7 +494,7 @@ Loop_neon:
 	umull	v20.2d,v14.2s,v1.s[2]
 	ldp	x9,x13,[x16],#48
 	umull	v19.2d,v14.2s,v0.s[2]
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x8,x8
 	rev	x12,x12
 	rev	x9,x9
@@ -559,7 +559,7 @@ Loop_neon:
 	umlal	v23.2d,v11.2s,v3.s[0]
 	umlal	v20.2d,v11.2s,v8.s[0]
 	umlal	v21.2d,v11.2s,v0.s[0]
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x8,x8
 	rev	x12,x12
 	rev	x9,x9
@@ -840,13 +840,13 @@ Lpoly1305_emit_neon:
 	csel	x4,x4,x12,eq
 	csel	x5,x5,x13,eq
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	ror	x10,x10,#32		// flip nonce words
 	ror	x11,x11,#32
 #endif
 	adds	x4,x4,x10		// accumulate nonce
 	adc	x5,x5,x11
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x4,x4			// flip output bytes
 	rev	x5,x5
 #endif
diff --git a/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/include/openssl/opensslv.h b/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/include/openssl/pkcs7.h b/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/darwin64-arm64-cc/asm_avx2/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/darwin64-arm64-cc/no-asm/configdata.pm b/deps/openssl/config/archs/darwin64-arm64-cc/no-asm/configdata.pm
index 6519d8eb5ee0d2..d1c07ea505db01 100644
--- a/deps/openssl/config/archs/darwin64-arm64-cc/no-asm/configdata.pm
+++ b/deps/openssl/config/archs/darwin64-arm64-cc/no-asm/configdata.pm
@@ -154,7 +154,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -205,7 +205,7 @@ our %config = (
     ],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-asm no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -258,11 +258,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "darwin64-arm64-cc",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/darwin64-arm64-cc/no-asm/crypto/buildinf.h b/deps/openssl/config/archs/darwin64-arm64-cc/no-asm/crypto/buildinf.h
index bf5b5aecd602cd..f8a747399b32f4 100644
--- a/deps/openssl/config/archs/darwin64-arm64-cc/no-asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/darwin64-arm64-cc/no-asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: darwin64-arm64-cc"
-#define DATE "built on: Sun Aug  6 00:30:09 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:53:18 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/darwin64-arm64-cc/no-asm/include/openssl/opensslv.h b/deps/openssl/config/archs/darwin64-arm64-cc/no-asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/darwin64-arm64-cc/no-asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/darwin64-arm64-cc/no-asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/darwin64-arm64-cc/no-asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/darwin64-arm64-cc/no-asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/darwin64-arm64-cc/no-asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/darwin64-arm64-cc/no-asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/darwin64-x86_64-cc/asm/configdata.pm b/deps/openssl/config/archs/darwin64-x86_64-cc/asm/configdata.pm
index 8f523192cad9d4..fbffdc36072be9 100644
--- a/deps/openssl/config/archs/darwin64-x86_64-cc/asm/configdata.pm
+++ b/deps/openssl/config/archs/darwin64-x86_64-cc/asm/configdata.pm
@@ -156,7 +156,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -206,7 +206,7 @@ our %config = (
     ],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -258,11 +258,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "darwin64-x86_64-cc",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/darwin64-x86_64-cc/asm/crypto/buildinf.h b/deps/openssl/config/archs/darwin64-x86_64-cc/asm/crypto/buildinf.h
index 2c108157902d0c..5d70cfc584bb4c 100644
--- a/deps/openssl/config/archs/darwin64-x86_64-cc/asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/darwin64-x86_64-cc/asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: darwin64-x86_64-cc"
-#define DATE "built on: Sun Aug  6 00:27:25 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:50:40 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/darwin64-x86_64-cc/asm/include/openssl/opensslv.h b/deps/openssl/config/archs/darwin64-x86_64-cc/asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/darwin64-x86_64-cc/asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/darwin64-x86_64-cc/asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/darwin64-x86_64-cc/asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/darwin64-x86_64-cc/asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/darwin64-x86_64-cc/asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/darwin64-x86_64-cc/asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/darwin64-x86_64-cc/asm_avx2/configdata.pm b/deps/openssl/config/archs/darwin64-x86_64-cc/asm_avx2/configdata.pm
index d036b582d78c68..e76d49d0c7c8c4 100644
--- a/deps/openssl/config/archs/darwin64-x86_64-cc/asm_avx2/configdata.pm
+++ b/deps/openssl/config/archs/darwin64-x86_64-cc/asm_avx2/configdata.pm
@@ -156,7 +156,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -206,7 +206,7 @@ our %config = (
     ],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -258,11 +258,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "darwin64-x86_64-cc",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/darwin64-x86_64-cc/asm_avx2/crypto/buildinf.h b/deps/openssl/config/archs/darwin64-x86_64-cc/asm_avx2/crypto/buildinf.h
index 994cec42e962cd..400bfc2f11b14f 100644
--- a/deps/openssl/config/archs/darwin64-x86_64-cc/asm_avx2/crypto/buildinf.h
+++ b/deps/openssl/config/archs/darwin64-x86_64-cc/asm_avx2/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: darwin64-x86_64-cc"
-#define DATE "built on: Sun Aug  6 00:27:49 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:51:03 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/darwin64-x86_64-cc/asm_avx2/include/openssl/opensslv.h b/deps/openssl/config/archs/darwin64-x86_64-cc/asm_avx2/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/darwin64-x86_64-cc/asm_avx2/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/darwin64-x86_64-cc/asm_avx2/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/darwin64-x86_64-cc/asm_avx2/include/openssl/pkcs7.h b/deps/openssl/config/archs/darwin64-x86_64-cc/asm_avx2/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/darwin64-x86_64-cc/asm_avx2/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/darwin64-x86_64-cc/asm_avx2/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/darwin64-x86_64-cc/no-asm/configdata.pm b/deps/openssl/config/archs/darwin64-x86_64-cc/no-asm/configdata.pm
index e85b222e7d012d..5b1ec98359201f 100644
--- a/deps/openssl/config/archs/darwin64-x86_64-cc/no-asm/configdata.pm
+++ b/deps/openssl/config/archs/darwin64-x86_64-cc/no-asm/configdata.pm
@@ -154,7 +154,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -205,7 +205,7 @@ our %config = (
     ],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-asm no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -258,11 +258,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "darwin64-x86_64-cc",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/darwin64-x86_64-cc/no-asm/crypto/buildinf.h b/deps/openssl/config/archs/darwin64-x86_64-cc/no-asm/crypto/buildinf.h
index fb875ca7f85df2..935727e4cc5d08 100644
--- a/deps/openssl/config/archs/darwin64-x86_64-cc/no-asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/darwin64-x86_64-cc/no-asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: darwin64-x86_64-cc"
-#define DATE "built on: Sun Aug  6 00:28:13 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:51:26 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/darwin64-x86_64-cc/no-asm/include/openssl/opensslv.h b/deps/openssl/config/archs/darwin64-x86_64-cc/no-asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/darwin64-x86_64-cc/no-asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/darwin64-x86_64-cc/no-asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/darwin64-x86_64-cc/no-asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/darwin64-x86_64-cc/no-asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/darwin64-x86_64-cc/no-asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/darwin64-x86_64-cc/no-asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux-aarch64/asm/configdata.pm b/deps/openssl/config/archs/linux-aarch64/asm/configdata.pm
index 8d48c4016f8c8b..fd7fbe3f636d8a 100644
--- a/deps/openssl/config/archs/linux-aarch64/asm/configdata.pm
+++ b/deps/openssl/config/archs/linux-aarch64/asm/configdata.pm
@@ -159,7 +159,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -207,7 +207,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux-aarch64",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux-aarch64/asm/crypto/aes/aesv8-armx.S b/deps/openssl/config/archs/linux-aarch64/asm/crypto/aes/aesv8-armx.S
index 51c4d7208da2ba..0d2a81daf9d2bf 100644
--- a/deps/openssl/config/archs/linux-aarch64/asm/crypto/aes/aesv8-armx.S
+++ b/deps/openssl/config/archs/linux-aarch64/asm/crypto/aes/aesv8-armx.S
@@ -103,7 +103,7 @@ aes_v8_set_encrypt_key:
 .Loop192:
 	tbl	v6.16b,{v4.16b},v2.16b
 	ext	v5.16b,v0.16b,v3.16b,#12
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
 	st1	{v4.4s},[x2],#16
 	sub	x2,x2,#8
 #else
@@ -1510,7 +1510,7 @@ aes_v8_ctr32_encrypt_blocks:
 	ldr	w5,[x3,#240]
 
 	ldr	w8, [x4, #12]
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
 	ld1	{v0.16b},[x4]
 #else
 	ld1	{v0.4s},[x4]
@@ -1527,7 +1527,7 @@ aes_v8_ctr32_encrypt_blocks:
 	add	x7,x3,#32
 	mov	w6,w5
 	csel	x12,xzr,x12,lo
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev	w8, w8
 #endif
 	orr	v1.16b,v0.16b,v0.16b
diff --git a/deps/openssl/config/archs/linux-aarch64/asm/crypto/buildinf.h b/deps/openssl/config/archs/linux-aarch64/asm/crypto/buildinf.h
index 59ce7dfcd536af..aa138ec0af4f2f 100644
--- a/deps/openssl/config/archs/linux-aarch64/asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux-aarch64/asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux-aarch64"
-#define DATE "built on: Sun Aug  6 00:30:30 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:53:36 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux-aarch64/asm/crypto/modes/ghashv8-armx.S b/deps/openssl/config/archs/linux-aarch64/asm/crypto/modes/ghashv8-armx.S
index acd52eb9568633..ea6a66a229e10f 100644
--- a/deps/openssl/config/archs/linux-aarch64/asm/crypto/modes/ghashv8-armx.S
+++ b/deps/openssl/config/archs/linux-aarch64/asm/crypto/modes/ghashv8-armx.S
@@ -101,7 +101,7 @@ gcm_gmult_v8:
 	movi	v19.16b,#0xe1
 	ld1	{v20.2d,v21.2d},[x1]	//load twisted H, ...
 	shl	v19.2d,v19.2d,#57
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v17.16b,v17.16b
 #endif
 	ext	v3.16b,v17.16b,v17.16b,#8
@@ -126,7 +126,7 @@ gcm_gmult_v8:
 	eor	v18.16b,v18.16b,v2.16b
 	eor	v0.16b,v0.16b,v18.16b
 
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v0.16b,v0.16b
 #endif
 	ext	v0.16b,v0.16b,v0.16b,#8
@@ -163,14 +163,14 @@ gcm_ghash_v8:
 	ext	v0.16b,v0.16b,v0.16b,#8		//rotate Xi
 	ld1	{v16.2d},[x2],#16	//load [rotated] I[0]
 	shl	v19.2d,v19.2d,#57		//compose 0xc2.0 constant
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v16.16b,v16.16b
 	rev64	v0.16b,v0.16b
 #endif
 	ext	v3.16b,v16.16b,v16.16b,#8		//rotate I[0]
 	b.lo	.Lodd_tail_v8		//x3 was less than 32
 	ld1	{v17.2d},[x2],x12	//load [rotated] I[1]
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v17.16b,v17.16b
 #endif
 	ext	v7.16b,v17.16b,v17.16b,#8
@@ -202,13 +202,13 @@ gcm_ghash_v8:
 	eor	v18.16b,v0.16b,v2.16b
 	eor	v1.16b,v1.16b,v17.16b
 	ld1	{v17.2d},[x2],x12	//load [rotated] I[i+3]
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v16.16b,v16.16b
 #endif
 	eor	v1.16b,v1.16b,v18.16b
 	pmull	v18.1q,v0.1d,v19.1d		//1st phase of reduction
 
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v17.16b,v17.16b
 #endif
 	ins	v2.d[0],v1.d[1]
@@ -258,7 +258,7 @@ gcm_ghash_v8:
 	eor	v0.16b,v0.16b,v18.16b
 
 .Ldone_v8:
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v0.16b,v0.16b
 #endif
 	ext	v0.16b,v0.16b,v0.16b,#8
@@ -277,7 +277,7 @@ gcm_ghash_v8_4x:
 	shl	v19.2d,v19.2d,#57		//compose 0xc2.0 constant
 
 	ld1	{v4.2d,v5.2d,v6.2d,v7.2d},[x2],#64
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v0.16b,v0.16b
 	rev64	v5.16b,v5.16b
 	rev64	v6.16b,v6.16b
@@ -321,7 +321,7 @@ gcm_ghash_v8_4x:
 	eor	v16.16b,v4.16b,v0.16b
 	ld1	{v4.2d,v5.2d,v6.2d,v7.2d},[x2],#64
 	ext	v3.16b,v16.16b,v16.16b,#8
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v5.16b,v5.16b
 	rev64	v6.16b,v6.16b
 	rev64	v7.16b,v7.16b
@@ -404,7 +404,7 @@ gcm_ghash_v8_4x:
 	eor	v1.16b,v1.16b,v17.16b
 	ld1	{v4.2d,v5.2d,v6.2d},[x2]
 	eor	v1.16b,v1.16b,v18.16b
-#ifndef	__ARMEB__
+#ifndef	__AARCH64EB__
 	rev64	v5.16b,v5.16b
 	rev64	v6.16b,v6.16b
 	rev64	v4.16b,v4.16b
@@ -456,7 +456,7 @@ gcm_ghash_v8_4x:
 	eor	v1.16b,v1.16b,v17.16b
 	ld1	{v4.2d,v5.2d},[x2]
 	eor	v1.16b,v1.16b,v18.16b
-#ifndef	__ARMEB__
+#ifndef	__AARCH64EB__
 	rev64	v5.16b,v5.16b
 	rev64	v4.16b,v4.16b
 #endif
@@ -499,7 +499,7 @@ gcm_ghash_v8_4x:
 	eor	v1.16b,v1.16b,v17.16b
 	ld1	{v4.2d},[x2]
 	eor	v1.16b,v1.16b,v18.16b
-#ifndef	__ARMEB__
+#ifndef	__AARCH64EB__
 	rev64	v4.16b,v4.16b
 #endif
 
@@ -539,7 +539,7 @@ gcm_ghash_v8_4x:
 	eor	v0.16b,v0.16b,v18.16b
 	ext	v0.16b,v0.16b,v0.16b,#8
 
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v0.16b,v0.16b
 #endif
 	st1	{v0.2d},[x0]		//write out Xi
diff --git a/deps/openssl/config/archs/linux-aarch64/asm/crypto/poly1305/poly1305-armv8.S b/deps/openssl/config/archs/linux-aarch64/asm/crypto/poly1305/poly1305-armv8.S
index ea8f390224053a..98ebf48535e5e9 100644
--- a/deps/openssl/config/archs/linux-aarch64/asm/crypto/poly1305/poly1305-armv8.S
+++ b/deps/openssl/config/archs/linux-aarch64/asm/crypto/poly1305/poly1305-armv8.S
@@ -28,7 +28,7 @@ poly1305_init:
 	ldp	x7,x8,[x1]		// load key
 	mov	x9,#0xfffffffc0fffffff
 	movk	x9,#0x0fff,lsl#48
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x7,x7			// flip bytes
 	rev	x8,x8
 #endif
@@ -75,7 +75,7 @@ poly1305_blocks:
 .Loop:
 	ldp	x10,x11,[x1],#16	// load input
 	sub	x2,x2,#16
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x10,x10
 	rev	x11,x11
 #endif
@@ -140,13 +140,13 @@ poly1305_emit:
 	csel	x4,x4,x12,eq
 	csel	x5,x5,x13,eq
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	ror	x10,x10,#32		// flip nonce words
 	ror	x11,x11,#32
 #endif
 	adds	x4,x4,x10		// accumulate nonce
 	adc	x5,x5,x11
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x4,x4			// flip output bytes
 	rev	x5,x5
 #endif
@@ -266,7 +266,7 @@ poly1305_blocks_neon:
 	adcs	x5,x5,xzr
 	adc	x6,x6,xzr
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x12,x12
 	rev	x13,x13
 #endif
@@ -312,7 +312,7 @@ poly1305_blocks_neon:
 	ldp	x12,x13,[x1],#16	// load input
 	sub	x2,x2,#16
 	add	x9,x8,x8,lsr#2	// s1 = r1 + (r1 >> 2)
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x12,x12
 	rev	x13,x13
 #endif
@@ -397,7 +397,7 @@ poly1305_blocks_neon:
 	lsl	x3,x3,#24
 	add	x15,x0,#48
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x8,x8
 	rev	x12,x12
 	rev	x9,x9
@@ -433,7 +433,7 @@ poly1305_blocks_neon:
 	ld1	{v4.4s,v5.4s,v6.4s,v7.4s},[x15],#64
 	ld1	{v8.4s},[x15]
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x8,x8
 	rev	x12,x12
 	rev	x9,x9
@@ -494,7 +494,7 @@ poly1305_blocks_neon:
 	umull	v20.2d,v14.2s,v1.s[2]
 	ldp	x9,x13,[x16],#48
 	umull	v19.2d,v14.2s,v0.s[2]
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x8,x8
 	rev	x12,x12
 	rev	x9,x9
@@ -559,7 +559,7 @@ poly1305_blocks_neon:
 	umlal	v23.2d,v11.2s,v3.s[0]
 	umlal	v20.2d,v11.2s,v8.s[0]
 	umlal	v21.2d,v11.2s,v0.s[0]
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x8,x8
 	rev	x12,x12
 	rev	x9,x9
@@ -840,13 +840,13 @@ poly1305_emit_neon:
 	csel	x4,x4,x12,eq
 	csel	x5,x5,x13,eq
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	ror	x10,x10,#32		// flip nonce words
 	ror	x11,x11,#32
 #endif
 	adds	x4,x4,x10		// accumulate nonce
 	adc	x5,x5,x11
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x4,x4			// flip output bytes
 	rev	x5,x5
 #endif
diff --git a/deps/openssl/config/archs/linux-aarch64/asm/include/openssl/opensslv.h b/deps/openssl/config/archs/linux-aarch64/asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux-aarch64/asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux-aarch64/asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux-aarch64/asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux-aarch64/asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux-aarch64/asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux-aarch64/asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux-aarch64/asm_avx2/configdata.pm b/deps/openssl/config/archs/linux-aarch64/asm_avx2/configdata.pm
index 9d498a04297dd0..2802640171fd6e 100644
--- a/deps/openssl/config/archs/linux-aarch64/asm_avx2/configdata.pm
+++ b/deps/openssl/config/archs/linux-aarch64/asm_avx2/configdata.pm
@@ -159,7 +159,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -207,7 +207,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux-aarch64",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux-aarch64/asm_avx2/crypto/aes/aesv8-armx.S b/deps/openssl/config/archs/linux-aarch64/asm_avx2/crypto/aes/aesv8-armx.S
index 51c4d7208da2ba..0d2a81daf9d2bf 100644
--- a/deps/openssl/config/archs/linux-aarch64/asm_avx2/crypto/aes/aesv8-armx.S
+++ b/deps/openssl/config/archs/linux-aarch64/asm_avx2/crypto/aes/aesv8-armx.S
@@ -103,7 +103,7 @@ aes_v8_set_encrypt_key:
 .Loop192:
 	tbl	v6.16b,{v4.16b},v2.16b
 	ext	v5.16b,v0.16b,v3.16b,#12
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
 	st1	{v4.4s},[x2],#16
 	sub	x2,x2,#8
 #else
@@ -1510,7 +1510,7 @@ aes_v8_ctr32_encrypt_blocks:
 	ldr	w5,[x3,#240]
 
 	ldr	w8, [x4, #12]
-#ifdef __ARMEB__
+#ifdef __AARCH64EB__
 	ld1	{v0.16b},[x4]
 #else
 	ld1	{v0.4s},[x4]
@@ -1527,7 +1527,7 @@ aes_v8_ctr32_encrypt_blocks:
 	add	x7,x3,#32
 	mov	w6,w5
 	csel	x12,xzr,x12,lo
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev	w8, w8
 #endif
 	orr	v1.16b,v0.16b,v0.16b
diff --git a/deps/openssl/config/archs/linux-aarch64/asm_avx2/crypto/buildinf.h b/deps/openssl/config/archs/linux-aarch64/asm_avx2/crypto/buildinf.h
index 8044c52de8534f..fe50bcb0f8eebe 100644
--- a/deps/openssl/config/archs/linux-aarch64/asm_avx2/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux-aarch64/asm_avx2/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux-aarch64"
-#define DATE "built on: Sun Aug  6 00:30:52 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:53:55 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux-aarch64/asm_avx2/crypto/modes/ghashv8-armx.S b/deps/openssl/config/archs/linux-aarch64/asm_avx2/crypto/modes/ghashv8-armx.S
index acd52eb9568633..ea6a66a229e10f 100644
--- a/deps/openssl/config/archs/linux-aarch64/asm_avx2/crypto/modes/ghashv8-armx.S
+++ b/deps/openssl/config/archs/linux-aarch64/asm_avx2/crypto/modes/ghashv8-armx.S
@@ -101,7 +101,7 @@ gcm_gmult_v8:
 	movi	v19.16b,#0xe1
 	ld1	{v20.2d,v21.2d},[x1]	//load twisted H, ...
 	shl	v19.2d,v19.2d,#57
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v17.16b,v17.16b
 #endif
 	ext	v3.16b,v17.16b,v17.16b,#8
@@ -126,7 +126,7 @@ gcm_gmult_v8:
 	eor	v18.16b,v18.16b,v2.16b
 	eor	v0.16b,v0.16b,v18.16b
 
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v0.16b,v0.16b
 #endif
 	ext	v0.16b,v0.16b,v0.16b,#8
@@ -163,14 +163,14 @@ gcm_ghash_v8:
 	ext	v0.16b,v0.16b,v0.16b,#8		//rotate Xi
 	ld1	{v16.2d},[x2],#16	//load [rotated] I[0]
 	shl	v19.2d,v19.2d,#57		//compose 0xc2.0 constant
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v16.16b,v16.16b
 	rev64	v0.16b,v0.16b
 #endif
 	ext	v3.16b,v16.16b,v16.16b,#8		//rotate I[0]
 	b.lo	.Lodd_tail_v8		//x3 was less than 32
 	ld1	{v17.2d},[x2],x12	//load [rotated] I[1]
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v17.16b,v17.16b
 #endif
 	ext	v7.16b,v17.16b,v17.16b,#8
@@ -202,13 +202,13 @@ gcm_ghash_v8:
 	eor	v18.16b,v0.16b,v2.16b
 	eor	v1.16b,v1.16b,v17.16b
 	ld1	{v17.2d},[x2],x12	//load [rotated] I[i+3]
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v16.16b,v16.16b
 #endif
 	eor	v1.16b,v1.16b,v18.16b
 	pmull	v18.1q,v0.1d,v19.1d		//1st phase of reduction
 
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v17.16b,v17.16b
 #endif
 	ins	v2.d[0],v1.d[1]
@@ -258,7 +258,7 @@ gcm_ghash_v8:
 	eor	v0.16b,v0.16b,v18.16b
 
 .Ldone_v8:
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v0.16b,v0.16b
 #endif
 	ext	v0.16b,v0.16b,v0.16b,#8
@@ -277,7 +277,7 @@ gcm_ghash_v8_4x:
 	shl	v19.2d,v19.2d,#57		//compose 0xc2.0 constant
 
 	ld1	{v4.2d,v5.2d,v6.2d,v7.2d},[x2],#64
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v0.16b,v0.16b
 	rev64	v5.16b,v5.16b
 	rev64	v6.16b,v6.16b
@@ -321,7 +321,7 @@ gcm_ghash_v8_4x:
 	eor	v16.16b,v4.16b,v0.16b
 	ld1	{v4.2d,v5.2d,v6.2d,v7.2d},[x2],#64
 	ext	v3.16b,v16.16b,v16.16b,#8
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v5.16b,v5.16b
 	rev64	v6.16b,v6.16b
 	rev64	v7.16b,v7.16b
@@ -404,7 +404,7 @@ gcm_ghash_v8_4x:
 	eor	v1.16b,v1.16b,v17.16b
 	ld1	{v4.2d,v5.2d,v6.2d},[x2]
 	eor	v1.16b,v1.16b,v18.16b
-#ifndef	__ARMEB__
+#ifndef	__AARCH64EB__
 	rev64	v5.16b,v5.16b
 	rev64	v6.16b,v6.16b
 	rev64	v4.16b,v4.16b
@@ -456,7 +456,7 @@ gcm_ghash_v8_4x:
 	eor	v1.16b,v1.16b,v17.16b
 	ld1	{v4.2d,v5.2d},[x2]
 	eor	v1.16b,v1.16b,v18.16b
-#ifndef	__ARMEB__
+#ifndef	__AARCH64EB__
 	rev64	v5.16b,v5.16b
 	rev64	v4.16b,v4.16b
 #endif
@@ -499,7 +499,7 @@ gcm_ghash_v8_4x:
 	eor	v1.16b,v1.16b,v17.16b
 	ld1	{v4.2d},[x2]
 	eor	v1.16b,v1.16b,v18.16b
-#ifndef	__ARMEB__
+#ifndef	__AARCH64EB__
 	rev64	v4.16b,v4.16b
 #endif
 
@@ -539,7 +539,7 @@ gcm_ghash_v8_4x:
 	eor	v0.16b,v0.16b,v18.16b
 	ext	v0.16b,v0.16b,v0.16b,#8
 
-#ifndef __ARMEB__
+#ifndef __AARCH64EB__
 	rev64	v0.16b,v0.16b
 #endif
 	st1	{v0.2d},[x0]		//write out Xi
diff --git a/deps/openssl/config/archs/linux-aarch64/asm_avx2/crypto/poly1305/poly1305-armv8.S b/deps/openssl/config/archs/linux-aarch64/asm_avx2/crypto/poly1305/poly1305-armv8.S
index ea8f390224053a..98ebf48535e5e9 100644
--- a/deps/openssl/config/archs/linux-aarch64/asm_avx2/crypto/poly1305/poly1305-armv8.S
+++ b/deps/openssl/config/archs/linux-aarch64/asm_avx2/crypto/poly1305/poly1305-armv8.S
@@ -28,7 +28,7 @@ poly1305_init:
 	ldp	x7,x8,[x1]		// load key
 	mov	x9,#0xfffffffc0fffffff
 	movk	x9,#0x0fff,lsl#48
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x7,x7			// flip bytes
 	rev	x8,x8
 #endif
@@ -75,7 +75,7 @@ poly1305_blocks:
 .Loop:
 	ldp	x10,x11,[x1],#16	// load input
 	sub	x2,x2,#16
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x10,x10
 	rev	x11,x11
 #endif
@@ -140,13 +140,13 @@ poly1305_emit:
 	csel	x4,x4,x12,eq
 	csel	x5,x5,x13,eq
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	ror	x10,x10,#32		// flip nonce words
 	ror	x11,x11,#32
 #endif
 	adds	x4,x4,x10		// accumulate nonce
 	adc	x5,x5,x11
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x4,x4			// flip output bytes
 	rev	x5,x5
 #endif
@@ -266,7 +266,7 @@ poly1305_blocks_neon:
 	adcs	x5,x5,xzr
 	adc	x6,x6,xzr
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x12,x12
 	rev	x13,x13
 #endif
@@ -312,7 +312,7 @@ poly1305_blocks_neon:
 	ldp	x12,x13,[x1],#16	// load input
 	sub	x2,x2,#16
 	add	x9,x8,x8,lsr#2	// s1 = r1 + (r1 >> 2)
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x12,x12
 	rev	x13,x13
 #endif
@@ -397,7 +397,7 @@ poly1305_blocks_neon:
 	lsl	x3,x3,#24
 	add	x15,x0,#48
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x8,x8
 	rev	x12,x12
 	rev	x9,x9
@@ -433,7 +433,7 @@ poly1305_blocks_neon:
 	ld1	{v4.4s,v5.4s,v6.4s,v7.4s},[x15],#64
 	ld1	{v8.4s},[x15]
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x8,x8
 	rev	x12,x12
 	rev	x9,x9
@@ -494,7 +494,7 @@ poly1305_blocks_neon:
 	umull	v20.2d,v14.2s,v1.s[2]
 	ldp	x9,x13,[x16],#48
 	umull	v19.2d,v14.2s,v0.s[2]
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x8,x8
 	rev	x12,x12
 	rev	x9,x9
@@ -559,7 +559,7 @@ poly1305_blocks_neon:
 	umlal	v23.2d,v11.2s,v3.s[0]
 	umlal	v20.2d,v11.2s,v8.s[0]
 	umlal	v21.2d,v11.2s,v0.s[0]
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x8,x8
 	rev	x12,x12
 	rev	x9,x9
@@ -840,13 +840,13 @@ poly1305_emit_neon:
 	csel	x4,x4,x12,eq
 	csel	x5,x5,x13,eq
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	ror	x10,x10,#32		// flip nonce words
 	ror	x11,x11,#32
 #endif
 	adds	x4,x4,x10		// accumulate nonce
 	adc	x5,x5,x11
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x4,x4			// flip output bytes
 	rev	x5,x5
 #endif
diff --git a/deps/openssl/config/archs/linux-aarch64/asm_avx2/include/openssl/opensslv.h b/deps/openssl/config/archs/linux-aarch64/asm_avx2/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux-aarch64/asm_avx2/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux-aarch64/asm_avx2/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux-aarch64/asm_avx2/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux-aarch64/asm_avx2/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux-aarch64/asm_avx2/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux-aarch64/asm_avx2/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux-aarch64/no-asm/configdata.pm b/deps/openssl/config/archs/linux-aarch64/no-asm/configdata.pm
index 31514639fa12cd..bf7ab392cebcd7 100644
--- a/deps/openssl/config/archs/linux-aarch64/no-asm/configdata.pm
+++ b/deps/openssl/config/archs/linux-aarch64/no-asm/configdata.pm
@@ -157,7 +157,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -206,7 +206,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-asm no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux-aarch64",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux-aarch64/no-asm/crypto/buildinf.h b/deps/openssl/config/archs/linux-aarch64/no-asm/crypto/buildinf.h
index 2c556e7c636514..e40fd9e8fa7be3 100644
--- a/deps/openssl/config/archs/linux-aarch64/no-asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux-aarch64/no-asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux-aarch64"
-#define DATE "built on: Sun Aug  6 00:31:14 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:54:15 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux-aarch64/no-asm/include/openssl/opensslv.h b/deps/openssl/config/archs/linux-aarch64/no-asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux-aarch64/no-asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux-aarch64/no-asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux-aarch64/no-asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux-aarch64/no-asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux-aarch64/no-asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux-aarch64/no-asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux-armv4/asm/configdata.pm b/deps/openssl/config/archs/linux-armv4/asm/configdata.pm
index b6536beee0911a..79653867c073ee 100644
--- a/deps/openssl/config/archs/linux-armv4/asm/configdata.pm
+++ b/deps/openssl/config/archs/linux-armv4/asm/configdata.pm
@@ -159,7 +159,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -207,7 +207,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux-armv4",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux-armv4/asm/crypto/aes/bsaes-armv7.S b/deps/openssl/config/archs/linux-armv4/asm/crypto/aes/bsaes-armv7.S
index 4b7f662140fba1..545d7f76c8a168 100644
--- a/deps/openssl/config/archs/linux-armv4/asm/crypto/aes/bsaes-armv7.S
+++ b/deps/openssl/config/archs/linux-armv4/asm/crypto/aes/bsaes-armv7.S
@@ -1131,7 +1131,7 @@ ossl_bsaes_cbc_encrypt:
 	vstmia	r4, {q7}
 
 .align	2
-
+0:
 #endif
 
 	vld1.8	{q15}, [r8]		@ load IV
@@ -1391,7 +1391,7 @@ ossl_bsaes_ctr32_encrypt_blocks:
 	vstmia	r12, {q7}			@ save last round key
 
 .align	2
-	add	r12, r3, #248
+0:	add	r12, r3, #248
 	vld1.8	{q0}, [r8]		@ load counter
 	add	r8, r6, #.LREVM0SR-.LM0	@ borrow r8
 	vldmia	r12, {q4}			@ load round0 key
@@ -1626,7 +1626,7 @@ ossl_bsaes_xts_encrypt:
 	vstmia	r12, {q7}
 
 .align	2
-	sub	sp, #0x90			@ place for tweak[9]
+0:	sub	sp, #0x90			@ place for tweak[9]
 #endif
 
 	vld1.8	{q8}, [r0]			@ initial tweak
@@ -2112,7 +2112,7 @@ ossl_bsaes_xts_decrypt:
 	vstmia	r4, {q7}
 
 .align	2
-	sub	sp, #0x90			@ place for tweak[9]
+0:	sub	sp, #0x90			@ place for tweak[9]
 #endif
 	vld1.8	{q8}, [r0]			@ initial tweak
 	adr	r2, .Lxts_magic
diff --git a/deps/openssl/config/archs/linux-armv4/asm/crypto/buildinf.h b/deps/openssl/config/archs/linux-armv4/asm/crypto/buildinf.h
index 16acd7cb38014e..470b8436be3e9a 100644
--- a/deps/openssl/config/archs/linux-armv4/asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux-armv4/asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux-armv4"
-#define DATE "built on: Sun Aug  6 00:31:35 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:54:32 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux-armv4/asm/include/openssl/opensslv.h b/deps/openssl/config/archs/linux-armv4/asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux-armv4/asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux-armv4/asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux-armv4/asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux-armv4/asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux-armv4/asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux-armv4/asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux-armv4/asm_avx2/configdata.pm b/deps/openssl/config/archs/linux-armv4/asm_avx2/configdata.pm
index 2d6713a69fe77a..61ce2baaf0268d 100644
--- a/deps/openssl/config/archs/linux-armv4/asm_avx2/configdata.pm
+++ b/deps/openssl/config/archs/linux-armv4/asm_avx2/configdata.pm
@@ -159,7 +159,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -207,7 +207,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux-armv4",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux-armv4/asm_avx2/crypto/aes/bsaes-armv7.S b/deps/openssl/config/archs/linux-armv4/asm_avx2/crypto/aes/bsaes-armv7.S
index 4b7f662140fba1..545d7f76c8a168 100644
--- a/deps/openssl/config/archs/linux-armv4/asm_avx2/crypto/aes/bsaes-armv7.S
+++ b/deps/openssl/config/archs/linux-armv4/asm_avx2/crypto/aes/bsaes-armv7.S
@@ -1131,7 +1131,7 @@ ossl_bsaes_cbc_encrypt:
 	vstmia	r4, {q7}
 
 .align	2
-
+0:
 #endif
 
 	vld1.8	{q15}, [r8]		@ load IV
@@ -1391,7 +1391,7 @@ ossl_bsaes_ctr32_encrypt_blocks:
 	vstmia	r12, {q7}			@ save last round key
 
 .align	2
-	add	r12, r3, #248
+0:	add	r12, r3, #248
 	vld1.8	{q0}, [r8]		@ load counter
 	add	r8, r6, #.LREVM0SR-.LM0	@ borrow r8
 	vldmia	r12, {q4}			@ load round0 key
@@ -1626,7 +1626,7 @@ ossl_bsaes_xts_encrypt:
 	vstmia	r12, {q7}
 
 .align	2
-	sub	sp, #0x90			@ place for tweak[9]
+0:	sub	sp, #0x90			@ place for tweak[9]
 #endif
 
 	vld1.8	{q8}, [r0]			@ initial tweak
@@ -2112,7 +2112,7 @@ ossl_bsaes_xts_decrypt:
 	vstmia	r4, {q7}
 
 .align	2
-	sub	sp, #0x90			@ place for tweak[9]
+0:	sub	sp, #0x90			@ place for tweak[9]
 #endif
 	vld1.8	{q8}, [r0]			@ initial tweak
 	adr	r2, .Lxts_magic
diff --git a/deps/openssl/config/archs/linux-armv4/asm_avx2/crypto/buildinf.h b/deps/openssl/config/archs/linux-armv4/asm_avx2/crypto/buildinf.h
index 2ee5795e784c20..34de4e5471460b 100644
--- a/deps/openssl/config/archs/linux-armv4/asm_avx2/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux-armv4/asm_avx2/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux-armv4"
-#define DATE "built on: Sun Aug  6 00:31:58 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:54:52 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux-armv4/asm_avx2/include/openssl/opensslv.h b/deps/openssl/config/archs/linux-armv4/asm_avx2/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux-armv4/asm_avx2/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux-armv4/asm_avx2/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux-armv4/asm_avx2/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux-armv4/asm_avx2/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux-armv4/asm_avx2/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux-armv4/asm_avx2/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux-armv4/no-asm/configdata.pm b/deps/openssl/config/archs/linux-armv4/no-asm/configdata.pm
index bee312afe923a3..3945676082d3a7 100644
--- a/deps/openssl/config/archs/linux-armv4/no-asm/configdata.pm
+++ b/deps/openssl/config/archs/linux-armv4/no-asm/configdata.pm
@@ -157,7 +157,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -206,7 +206,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-asm no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux-armv4",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux-armv4/no-asm/crypto/buildinf.h b/deps/openssl/config/archs/linux-armv4/no-asm/crypto/buildinf.h
index 37415a157b7a5a..06676dd0a62428 100644
--- a/deps/openssl/config/archs/linux-armv4/no-asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux-armv4/no-asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux-armv4"
-#define DATE "built on: Sun Aug  6 00:32:20 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:55:11 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux-armv4/no-asm/include/openssl/opensslv.h b/deps/openssl/config/archs/linux-armv4/no-asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux-armv4/no-asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux-armv4/no-asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux-armv4/no-asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux-armv4/no-asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux-armv4/no-asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux-armv4/no-asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux-elf/asm/configdata.pm b/deps/openssl/config/archs/linux-elf/asm/configdata.pm
index fe754b5ea008b5..f42b25e4813c2c 100644
--- a/deps/openssl/config/archs/linux-elf/asm/configdata.pm
+++ b/deps/openssl/config/archs/linux-elf/asm/configdata.pm
@@ -159,7 +159,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -207,7 +207,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux-elf",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux-elf/asm/crypto/buildinf.h b/deps/openssl/config/archs/linux-elf/asm/crypto/buildinf.h
index f58e1b3b022376..9cfe51eea4fc93 100644
--- a/deps/openssl/config/archs/linux-elf/asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux-elf/asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux-elf"
-#define DATE "built on: Sun Aug  6 00:32:41 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:55:29 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux-elf/asm/include/openssl/opensslv.h b/deps/openssl/config/archs/linux-elf/asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux-elf/asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux-elf/asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux-elf/asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux-elf/asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux-elf/asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux-elf/asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux-elf/asm_avx2/configdata.pm b/deps/openssl/config/archs/linux-elf/asm_avx2/configdata.pm
index 083f6bc78525da..0af1ae16add5e7 100644
--- a/deps/openssl/config/archs/linux-elf/asm_avx2/configdata.pm
+++ b/deps/openssl/config/archs/linux-elf/asm_avx2/configdata.pm
@@ -159,7 +159,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -207,7 +207,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux-elf",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux-elf/asm_avx2/crypto/buildinf.h b/deps/openssl/config/archs/linux-elf/asm_avx2/crypto/buildinf.h
index cfff344f504f1f..32a9cc3b4e7b0b 100644
--- a/deps/openssl/config/archs/linux-elf/asm_avx2/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux-elf/asm_avx2/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux-elf"
-#define DATE "built on: Sun Aug  6 00:33:04 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:55:49 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux-elf/asm_avx2/include/openssl/opensslv.h b/deps/openssl/config/archs/linux-elf/asm_avx2/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux-elf/asm_avx2/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux-elf/asm_avx2/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux-elf/asm_avx2/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux-elf/asm_avx2/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux-elf/asm_avx2/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux-elf/asm_avx2/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux-elf/no-asm/configdata.pm b/deps/openssl/config/archs/linux-elf/no-asm/configdata.pm
index a5e1137b149e7a..6b8469360a6939 100644
--- a/deps/openssl/config/archs/linux-elf/no-asm/configdata.pm
+++ b/deps/openssl/config/archs/linux-elf/no-asm/configdata.pm
@@ -157,7 +157,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -206,7 +206,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-asm no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux-elf",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux-elf/no-asm/crypto/buildinf.h b/deps/openssl/config/archs/linux-elf/no-asm/crypto/buildinf.h
index 0dd30616b28e66..d5ca31dd991bac 100644
--- a/deps/openssl/config/archs/linux-elf/no-asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux-elf/no-asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux-elf"
-#define DATE "built on: Sun Aug  6 00:33:27 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:56:09 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux-elf/no-asm/include/openssl/opensslv.h b/deps/openssl/config/archs/linux-elf/no-asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux-elf/no-asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux-elf/no-asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux-elf/no-asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux-elf/no-asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux-elf/no-asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux-elf/no-asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux-ppc64le/asm/configdata.pm b/deps/openssl/config/archs/linux-ppc64le/asm/configdata.pm
index f979f6f060f9b6..c8aa0d7fe32340 100644
--- a/deps/openssl/config/archs/linux-ppc64le/asm/configdata.pm
+++ b/deps/openssl/config/archs/linux-ppc64le/asm/configdata.pm
@@ -159,7 +159,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -207,7 +207,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux-ppc64le",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux-ppc64le/asm/crypto/buildinf.h b/deps/openssl/config/archs/linux-ppc64le/asm/crypto/buildinf.h
index c45299350be3f9..d1e3acb464a422 100644
--- a/deps/openssl/config/archs/linux-ppc64le/asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux-ppc64le/asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux-ppc64le"
-#define DATE "built on: Sun Aug  6 00:35:08 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:57:32 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux-ppc64le/asm/include/openssl/opensslv.h b/deps/openssl/config/archs/linux-ppc64le/asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux-ppc64le/asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux-ppc64le/asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux-ppc64le/asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux-ppc64le/asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux-ppc64le/asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux-ppc64le/asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux-ppc64le/asm_avx2/configdata.pm b/deps/openssl/config/archs/linux-ppc64le/asm_avx2/configdata.pm
index 08080140eb2e78..0ea84d2ce335f5 100644
--- a/deps/openssl/config/archs/linux-ppc64le/asm_avx2/configdata.pm
+++ b/deps/openssl/config/archs/linux-ppc64le/asm_avx2/configdata.pm
@@ -159,7 +159,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -207,7 +207,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux-ppc64le",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux-ppc64le/asm_avx2/crypto/buildinf.h b/deps/openssl/config/archs/linux-ppc64le/asm_avx2/crypto/buildinf.h
index 2395cef1030cd0..e29cf2d622f37b 100644
--- a/deps/openssl/config/archs/linux-ppc64le/asm_avx2/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux-ppc64le/asm_avx2/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux-ppc64le"
-#define DATE "built on: Sun Aug  6 00:35:31 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:57:51 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux-ppc64le/asm_avx2/include/openssl/opensslv.h b/deps/openssl/config/archs/linux-ppc64le/asm_avx2/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux-ppc64le/asm_avx2/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux-ppc64le/asm_avx2/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux-ppc64le/asm_avx2/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux-ppc64le/asm_avx2/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux-ppc64le/asm_avx2/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux-ppc64le/asm_avx2/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux-ppc64le/no-asm/configdata.pm b/deps/openssl/config/archs/linux-ppc64le/no-asm/configdata.pm
index 189ada48854119..fe396100caff68 100644
--- a/deps/openssl/config/archs/linux-ppc64le/no-asm/configdata.pm
+++ b/deps/openssl/config/archs/linux-ppc64le/no-asm/configdata.pm
@@ -157,7 +157,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -206,7 +206,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-asm no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux-ppc64le",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux-ppc64le/no-asm/crypto/buildinf.h b/deps/openssl/config/archs/linux-ppc64le/no-asm/crypto/buildinf.h
index bf4a292031de3f..38c6d24008d45c 100644
--- a/deps/openssl/config/archs/linux-ppc64le/no-asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux-ppc64le/no-asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux-ppc64le"
-#define DATE "built on: Sun Aug  6 00:35:54 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:58:10 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux-ppc64le/no-asm/include/openssl/opensslv.h b/deps/openssl/config/archs/linux-ppc64le/no-asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux-ppc64le/no-asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux-ppc64le/no-asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux-ppc64le/no-asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux-ppc64le/no-asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux-ppc64le/no-asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux-ppc64le/no-asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux-x86_64/asm/configdata.pm b/deps/openssl/config/archs/linux-x86_64/asm/configdata.pm
index 133c99bdb8379f..8c177223983873 100644
--- a/deps/openssl/config/archs/linux-x86_64/asm/configdata.pm
+++ b/deps/openssl/config/archs/linux-x86_64/asm/configdata.pm
@@ -159,7 +159,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -207,7 +207,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux-x86_64",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux-x86_64/asm/crypto/buildinf.h b/deps/openssl/config/archs/linux-x86_64/asm/crypto/buildinf.h
index 13c3b4c33b64c4..c453e042ec2cd8 100644
--- a/deps/openssl/config/archs/linux-x86_64/asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux-x86_64/asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux-x86_64"
-#define DATE "built on: Sun Aug  6 00:33:49 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:56:27 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux-x86_64/asm/include/openssl/opensslv.h b/deps/openssl/config/archs/linux-x86_64/asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux-x86_64/asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux-x86_64/asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux-x86_64/asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux-x86_64/asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux-x86_64/asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux-x86_64/asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux-x86_64/asm_avx2/configdata.pm b/deps/openssl/config/archs/linux-x86_64/asm_avx2/configdata.pm
index 682f020891c38e..82a028a7500db9 100644
--- a/deps/openssl/config/archs/linux-x86_64/asm_avx2/configdata.pm
+++ b/deps/openssl/config/archs/linux-x86_64/asm_avx2/configdata.pm
@@ -159,7 +159,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -207,7 +207,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux-x86_64",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux-x86_64/asm_avx2/crypto/buildinf.h b/deps/openssl/config/archs/linux-x86_64/asm_avx2/crypto/buildinf.h
index 1d83deffde45f4..dd77a730662bb9 100644
--- a/deps/openssl/config/archs/linux-x86_64/asm_avx2/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux-x86_64/asm_avx2/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux-x86_64"
-#define DATE "built on: Sun Aug  6 00:34:19 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:56:50 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux-x86_64/asm_avx2/include/openssl/opensslv.h b/deps/openssl/config/archs/linux-x86_64/asm_avx2/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux-x86_64/asm_avx2/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux-x86_64/asm_avx2/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux-x86_64/asm_avx2/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux-x86_64/asm_avx2/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux-x86_64/asm_avx2/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux-x86_64/asm_avx2/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux-x86_64/no-asm/configdata.pm b/deps/openssl/config/archs/linux-x86_64/no-asm/configdata.pm
index 3beffa26651377..74531136b16293 100644
--- a/deps/openssl/config/archs/linux-x86_64/no-asm/configdata.pm
+++ b/deps/openssl/config/archs/linux-x86_64/no-asm/configdata.pm
@@ -157,7 +157,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -206,7 +206,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-asm no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux-x86_64",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux-x86_64/no-asm/crypto/buildinf.h b/deps/openssl/config/archs/linux-x86_64/no-asm/crypto/buildinf.h
index c3499dd469d71a..eb1d92ca3b85e8 100644
--- a/deps/openssl/config/archs/linux-x86_64/no-asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux-x86_64/no-asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux-x86_64"
-#define DATE "built on: Sun Aug  6 00:34:48 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:57:14 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux-x86_64/no-asm/include/openssl/opensslv.h b/deps/openssl/config/archs/linux-x86_64/no-asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux-x86_64/no-asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux-x86_64/no-asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux-x86_64/no-asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux-x86_64/no-asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux-x86_64/no-asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux-x86_64/no-asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux32-s390x/asm/configdata.pm b/deps/openssl/config/archs/linux32-s390x/asm/configdata.pm
index b4729ad28f92ae..077d1fe8d7f266 100644
--- a/deps/openssl/config/archs/linux32-s390x/asm/configdata.pm
+++ b/deps/openssl/config/archs/linux32-s390x/asm/configdata.pm
@@ -159,7 +159,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -207,7 +207,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux32-s390x",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux32-s390x/asm/crypto/buildinf.h b/deps/openssl/config/archs/linux32-s390x/asm/crypto/buildinf.h
index 210dcc63df0ff1..12e34e0b8d87b4 100644
--- a/deps/openssl/config/archs/linux32-s390x/asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux32-s390x/asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux32-s390x"
-#define DATE "built on: Sun Aug  6 00:36:17 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:58:28 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux32-s390x/asm/include/openssl/opensslv.h b/deps/openssl/config/archs/linux32-s390x/asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux32-s390x/asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux32-s390x/asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux32-s390x/asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux32-s390x/asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux32-s390x/asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux32-s390x/asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux32-s390x/asm_avx2/configdata.pm b/deps/openssl/config/archs/linux32-s390x/asm_avx2/configdata.pm
index e3ec7d01486663..1a3bfbead00cc9 100644
--- a/deps/openssl/config/archs/linux32-s390x/asm_avx2/configdata.pm
+++ b/deps/openssl/config/archs/linux32-s390x/asm_avx2/configdata.pm
@@ -159,7 +159,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -207,7 +207,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux32-s390x",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux32-s390x/asm_avx2/crypto/buildinf.h b/deps/openssl/config/archs/linux32-s390x/asm_avx2/crypto/buildinf.h
index e689eb7c7734ff..cc34b5b48f7286 100644
--- a/deps/openssl/config/archs/linux32-s390x/asm_avx2/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux32-s390x/asm_avx2/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux32-s390x"
-#define DATE "built on: Sun Aug  6 00:36:40 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:58:48 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux32-s390x/asm_avx2/include/openssl/opensslv.h b/deps/openssl/config/archs/linux32-s390x/asm_avx2/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux32-s390x/asm_avx2/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux32-s390x/asm_avx2/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux32-s390x/asm_avx2/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux32-s390x/asm_avx2/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux32-s390x/asm_avx2/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux32-s390x/asm_avx2/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux32-s390x/no-asm/configdata.pm b/deps/openssl/config/archs/linux32-s390x/no-asm/configdata.pm
index a71b8dcf839746..e3a8f82fe7462c 100644
--- a/deps/openssl/config/archs/linux32-s390x/no-asm/configdata.pm
+++ b/deps/openssl/config/archs/linux32-s390x/no-asm/configdata.pm
@@ -157,7 +157,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -206,7 +206,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-asm no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux32-s390x",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux32-s390x/no-asm/crypto/buildinf.h b/deps/openssl/config/archs/linux32-s390x/no-asm/crypto/buildinf.h
index 7c01ad4e90df3b..d228feb5a19ee6 100644
--- a/deps/openssl/config/archs/linux32-s390x/no-asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux32-s390x/no-asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux32-s390x"
-#define DATE "built on: Sun Aug  6 00:37:03 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:59:08 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux32-s390x/no-asm/include/openssl/opensslv.h b/deps/openssl/config/archs/linux32-s390x/no-asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux32-s390x/no-asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux32-s390x/no-asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux32-s390x/no-asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux32-s390x/no-asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux32-s390x/no-asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux32-s390x/no-asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux64-loongarch64/no-asm/configdata.pm b/deps/openssl/config/archs/linux64-loongarch64/no-asm/configdata.pm
index 9576c99c906303..f8186f5553dd14 100644
--- a/deps/openssl/config/archs/linux64-loongarch64/no-asm/configdata.pm
+++ b/deps/openssl/config/archs/linux64-loongarch64/no-asm/configdata.pm
@@ -157,7 +157,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -206,7 +206,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-asm no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux64-loongarch64",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux64-loongarch64/no-asm/crypto/buildinf.h b/deps/openssl/config/archs/linux64-loongarch64/no-asm/crypto/buildinf.h
index 4e95343a9fb4cd..3ba7a434358453 100644
--- a/deps/openssl/config/archs/linux64-loongarch64/no-asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux64-loongarch64/no-asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux64-loongarch64"
-#define DATE "built on: Sun Aug  6 00:45:10 2023 UTC"
+#define DATE "built on: Thu Oct 26 15:05:52 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux64-loongarch64/no-asm/include/openssl/opensslv.h b/deps/openssl/config/archs/linux64-loongarch64/no-asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux64-loongarch64/no-asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux64-loongarch64/no-asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux64-loongarch64/no-asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux64-loongarch64/no-asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux64-loongarch64/no-asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux64-loongarch64/no-asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux64-mips64/asm/configdata.pm b/deps/openssl/config/archs/linux64-mips64/asm/configdata.pm
index dbfc0d2736f05a..223edd33ddacd4 100644
--- a/deps/openssl/config/archs/linux64-mips64/asm/configdata.pm
+++ b/deps/openssl/config/archs/linux64-mips64/asm/configdata.pm
@@ -162,7 +162,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -210,7 +210,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -262,11 +262,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux64-mips64",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux64-mips64/asm/crypto/buildinf.h b/deps/openssl/config/archs/linux64-mips64/asm/crypto/buildinf.h
index 6b70def08e855a..1f63d54c12ba01 100644
--- a/deps/openssl/config/archs/linux64-mips64/asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux64-mips64/asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux64-mips64"
-#define DATE "built on: Sun Aug  6 00:38:36 2023 UTC"
+#define DATE "built on: Thu Oct 26 15:00:22 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux64-mips64/asm/include/openssl/opensslv.h b/deps/openssl/config/archs/linux64-mips64/asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux64-mips64/asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux64-mips64/asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux64-mips64/asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux64-mips64/asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux64-mips64/asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux64-mips64/asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux64-mips64/asm_avx2/configdata.pm b/deps/openssl/config/archs/linux64-mips64/asm_avx2/configdata.pm
index 3b8e66e40539e8..ab9529b1189573 100644
--- a/deps/openssl/config/archs/linux64-mips64/asm_avx2/configdata.pm
+++ b/deps/openssl/config/archs/linux64-mips64/asm_avx2/configdata.pm
@@ -162,7 +162,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -210,7 +210,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -262,11 +262,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux64-mips64",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux64-mips64/asm_avx2/crypto/buildinf.h b/deps/openssl/config/archs/linux64-mips64/asm_avx2/crypto/buildinf.h
index 594e838897cbbb..492782784a2fed 100644
--- a/deps/openssl/config/archs/linux64-mips64/asm_avx2/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux64-mips64/asm_avx2/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux64-mips64"
-#define DATE "built on: Sun Aug  6 00:38:59 2023 UTC"
+#define DATE "built on: Thu Oct 26 15:00:41 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux64-mips64/asm_avx2/include/openssl/opensslv.h b/deps/openssl/config/archs/linux64-mips64/asm_avx2/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux64-mips64/asm_avx2/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux64-mips64/asm_avx2/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux64-mips64/asm_avx2/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux64-mips64/asm_avx2/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux64-mips64/asm_avx2/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux64-mips64/asm_avx2/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux64-mips64/no-asm/configdata.pm b/deps/openssl/config/archs/linux64-mips64/no-asm/configdata.pm
index 01bb1010d678bf..60fd68cd9d1b05 100644
--- a/deps/openssl/config/archs/linux64-mips64/no-asm/configdata.pm
+++ b/deps/openssl/config/archs/linux64-mips64/no-asm/configdata.pm
@@ -157,7 +157,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -206,7 +206,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-asm no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux64-mips64",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux64-mips64/no-asm/crypto/buildinf.h b/deps/openssl/config/archs/linux64-mips64/no-asm/crypto/buildinf.h
index 1c1ffc1c348702..b2da592e4a422c 100644
--- a/deps/openssl/config/archs/linux64-mips64/no-asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux64-mips64/no-asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux64-mips64"
-#define DATE "built on: Sun Aug  6 00:39:21 2023 UTC"
+#define DATE "built on: Thu Oct 26 15:00:59 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux64-mips64/no-asm/include/openssl/opensslv.h b/deps/openssl/config/archs/linux64-mips64/no-asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux64-mips64/no-asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux64-mips64/no-asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux64-mips64/no-asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux64-mips64/no-asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux64-mips64/no-asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux64-mips64/no-asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux64-riscv64/no-asm/configdata.pm b/deps/openssl/config/archs/linux64-riscv64/no-asm/configdata.pm
index 2618989ca8c17c..b807271a07fd32 100644
--- a/deps/openssl/config/archs/linux64-riscv64/no-asm/configdata.pm
+++ b/deps/openssl/config/archs/linux64-riscv64/no-asm/configdata.pm
@@ -157,7 +157,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -206,7 +206,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-asm no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux64-riscv64",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux64-riscv64/no-asm/crypto/buildinf.h b/deps/openssl/config/archs/linux64-riscv64/no-asm/crypto/buildinf.h
index f8ee87111d60b3..2c8f14b9fd31f8 100644
--- a/deps/openssl/config/archs/linux64-riscv64/no-asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux64-riscv64/no-asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux64-riscv64"
-#define DATE "built on: Sun Aug  6 00:44:48 2023 UTC"
+#define DATE "built on: Thu Oct 26 15:05:34 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux64-riscv64/no-asm/include/openssl/opensslv.h b/deps/openssl/config/archs/linux64-riscv64/no-asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux64-riscv64/no-asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux64-riscv64/no-asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux64-riscv64/no-asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux64-riscv64/no-asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux64-riscv64/no-asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux64-riscv64/no-asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux64-s390x/asm/configdata.pm b/deps/openssl/config/archs/linux64-s390x/asm/configdata.pm
index 31e57b928cac04..7ca0547e9d1176 100644
--- a/deps/openssl/config/archs/linux64-s390x/asm/configdata.pm
+++ b/deps/openssl/config/archs/linux64-s390x/asm/configdata.pm
@@ -159,7 +159,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -207,7 +207,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux64-s390x",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux64-s390x/asm/crypto/buildinf.h b/deps/openssl/config/archs/linux64-s390x/asm/crypto/buildinf.h
index b10344ae3019e1..aad4edb0f23308 100644
--- a/deps/openssl/config/archs/linux64-s390x/asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux64-s390x/asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux64-s390x"
-#define DATE "built on: Sun Aug  6 00:37:26 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:59:26 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux64-s390x/asm/include/openssl/opensslv.h b/deps/openssl/config/archs/linux64-s390x/asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux64-s390x/asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux64-s390x/asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux64-s390x/asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux64-s390x/asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux64-s390x/asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux64-s390x/asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux64-s390x/asm_avx2/configdata.pm b/deps/openssl/config/archs/linux64-s390x/asm_avx2/configdata.pm
index f7a270be6046c4..67f9b59a4f1473 100644
--- a/deps/openssl/config/archs/linux64-s390x/asm_avx2/configdata.pm
+++ b/deps/openssl/config/archs/linux64-s390x/asm_avx2/configdata.pm
@@ -159,7 +159,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -207,7 +207,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux64-s390x",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux64-s390x/asm_avx2/crypto/buildinf.h b/deps/openssl/config/archs/linux64-s390x/asm_avx2/crypto/buildinf.h
index c602e1eed19db4..49a18326cda364 100644
--- a/deps/openssl/config/archs/linux64-s390x/asm_avx2/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux64-s390x/asm_avx2/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux64-s390x"
-#define DATE "built on: Sun Aug  6 00:37:50 2023 UTC"
+#define DATE "built on: Thu Oct 26 14:59:45 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux64-s390x/asm_avx2/include/openssl/opensslv.h b/deps/openssl/config/archs/linux64-s390x/asm_avx2/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux64-s390x/asm_avx2/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux64-s390x/asm_avx2/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux64-s390x/asm_avx2/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux64-s390x/asm_avx2/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux64-s390x/asm_avx2/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux64-s390x/asm_avx2/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/linux64-s390x/no-asm/configdata.pm b/deps/openssl/config/archs/linux64-s390x/no-asm/configdata.pm
index a44e5d6c7ea1d1..0511cc0ad771f1 100644
--- a/deps/openssl/config/archs/linux64-s390x/no-asm/configdata.pm
+++ b/deps/openssl/config/archs/linux64-s390x/no-asm/configdata.pm
@@ -157,7 +157,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -206,7 +206,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-asm no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -259,11 +259,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned char",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "linux64-s390x",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/linux64-s390x/no-asm/crypto/buildinf.h b/deps/openssl/config/archs/linux64-s390x/no-asm/crypto/buildinf.h
index 6d7b9134d30329..56f3cb4a199951 100644
--- a/deps/openssl/config/archs/linux64-s390x/no-asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/linux64-s390x/no-asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: linux64-s390x"
-#define DATE "built on: Sun Aug  6 00:38:14 2023 UTC"
+#define DATE "built on: Thu Oct 26 15:00:04 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/linux64-s390x/no-asm/include/openssl/opensslv.h b/deps/openssl/config/archs/linux64-s390x/no-asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/linux64-s390x/no-asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/linux64-s390x/no-asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/linux64-s390x/no-asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/linux64-s390x/no-asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/linux64-s390x/no-asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/linux64-s390x/no-asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/solaris-x86-gcc/asm/configdata.pm b/deps/openssl/config/archs/solaris-x86-gcc/asm/configdata.pm
index d60b22c0286e85..5ab80e6faf2eee 100644
--- a/deps/openssl/config/archs/solaris-x86-gcc/asm/configdata.pm
+++ b/deps/openssl/config/archs/solaris-x86-gcc/asm/configdata.pm
@@ -156,7 +156,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -204,7 +204,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -256,11 +256,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "solaris-x86-gcc",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/solaris-x86-gcc/asm/crypto/buildinf.h b/deps/openssl/config/archs/solaris-x86-gcc/asm/crypto/buildinf.h
index 6c58b044ea9707..468c40de382836 100644
--- a/deps/openssl/config/archs/solaris-x86-gcc/asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/solaris-x86-gcc/asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: solaris-x86-gcc"
-#define DATE "built on: Sun Aug  6 00:39:44 2023 UTC"
+#define DATE "built on: Thu Oct 26 15:01:17 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/solaris-x86-gcc/asm/include/openssl/opensslv.h b/deps/openssl/config/archs/solaris-x86-gcc/asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/solaris-x86-gcc/asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/solaris-x86-gcc/asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/solaris-x86-gcc/asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/solaris-x86-gcc/asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/solaris-x86-gcc/asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/solaris-x86-gcc/asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/solaris-x86-gcc/asm_avx2/configdata.pm b/deps/openssl/config/archs/solaris-x86-gcc/asm_avx2/configdata.pm
index ec632ff0f28c57..7e2449164988b9 100644
--- a/deps/openssl/config/archs/solaris-x86-gcc/asm_avx2/configdata.pm
+++ b/deps/openssl/config/archs/solaris-x86-gcc/asm_avx2/configdata.pm
@@ -156,7 +156,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -204,7 +204,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -256,11 +256,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "solaris-x86-gcc",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/solaris-x86-gcc/asm_avx2/crypto/buildinf.h b/deps/openssl/config/archs/solaris-x86-gcc/asm_avx2/crypto/buildinf.h
index 01fe3449426840..805dcab06bb3b9 100644
--- a/deps/openssl/config/archs/solaris-x86-gcc/asm_avx2/crypto/buildinf.h
+++ b/deps/openssl/config/archs/solaris-x86-gcc/asm_avx2/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: solaris-x86-gcc"
-#define DATE "built on: Sun Aug  6 00:40:07 2023 UTC"
+#define DATE "built on: Thu Oct 26 15:01:37 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/solaris-x86-gcc/asm_avx2/include/openssl/opensslv.h b/deps/openssl/config/archs/solaris-x86-gcc/asm_avx2/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/solaris-x86-gcc/asm_avx2/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/solaris-x86-gcc/asm_avx2/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/solaris-x86-gcc/asm_avx2/include/openssl/pkcs7.h b/deps/openssl/config/archs/solaris-x86-gcc/asm_avx2/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/solaris-x86-gcc/asm_avx2/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/solaris-x86-gcc/asm_avx2/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/solaris-x86-gcc/no-asm/configdata.pm b/deps/openssl/config/archs/solaris-x86-gcc/no-asm/configdata.pm
index 5dc7107bb26bbd..cade32bd647c0b 100644
--- a/deps/openssl/config/archs/solaris-x86-gcc/no-asm/configdata.pm
+++ b/deps/openssl/config/archs/solaris-x86-gcc/no-asm/configdata.pm
@@ -154,7 +154,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -203,7 +203,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-asm no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -256,11 +256,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "solaris-x86-gcc",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/solaris-x86-gcc/no-asm/crypto/buildinf.h b/deps/openssl/config/archs/solaris-x86-gcc/no-asm/crypto/buildinf.h
index d9d8f29beefec3..8201c478c71fe0 100644
--- a/deps/openssl/config/archs/solaris-x86-gcc/no-asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/solaris-x86-gcc/no-asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: solaris-x86-gcc"
-#define DATE "built on: Sun Aug  6 00:40:30 2023 UTC"
+#define DATE "built on: Thu Oct 26 15:01:58 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/solaris-x86-gcc/no-asm/include/openssl/opensslv.h b/deps/openssl/config/archs/solaris-x86-gcc/no-asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/solaris-x86-gcc/no-asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/solaris-x86-gcc/no-asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/solaris-x86-gcc/no-asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/solaris-x86-gcc/no-asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/solaris-x86-gcc/no-asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/solaris-x86-gcc/no-asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/solaris64-x86_64-gcc/asm/configdata.pm b/deps/openssl/config/archs/solaris64-x86_64-gcc/asm/configdata.pm
index 199dee44226d9f..48232d7ea1f9e6 100644
--- a/deps/openssl/config/archs/solaris64-x86_64-gcc/asm/configdata.pm
+++ b/deps/openssl/config/archs/solaris64-x86_64-gcc/asm/configdata.pm
@@ -156,7 +156,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -204,7 +204,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -256,11 +256,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "solaris64-x86_64-gcc",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/solaris64-x86_64-gcc/asm/crypto/buildinf.h b/deps/openssl/config/archs/solaris64-x86_64-gcc/asm/crypto/buildinf.h
index 45e22d76fd5e66..f953c4d35bb5b0 100644
--- a/deps/openssl/config/archs/solaris64-x86_64-gcc/asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/solaris64-x86_64-gcc/asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: solaris64-x86_64-gcc"
-#define DATE "built on: Sun Aug  6 00:40:52 2023 UTC"
+#define DATE "built on: Thu Oct 26 15:02:16 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/solaris64-x86_64-gcc/asm/include/openssl/opensslv.h b/deps/openssl/config/archs/solaris64-x86_64-gcc/asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/solaris64-x86_64-gcc/asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/solaris64-x86_64-gcc/asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/solaris64-x86_64-gcc/asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/solaris64-x86_64-gcc/asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/solaris64-x86_64-gcc/asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/solaris64-x86_64-gcc/asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/solaris64-x86_64-gcc/asm_avx2/configdata.pm b/deps/openssl/config/archs/solaris64-x86_64-gcc/asm_avx2/configdata.pm
index df9f4cc099ead6..4a7a3cf873a3e4 100644
--- a/deps/openssl/config/archs/solaris64-x86_64-gcc/asm_avx2/configdata.pm
+++ b/deps/openssl/config/archs/solaris64-x86_64-gcc/asm_avx2/configdata.pm
@@ -156,7 +156,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -204,7 +204,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -256,11 +256,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "solaris64-x86_64-gcc",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/solaris64-x86_64-gcc/asm_avx2/crypto/buildinf.h b/deps/openssl/config/archs/solaris64-x86_64-gcc/asm_avx2/crypto/buildinf.h
index 9bff7519bf2417..0fcdd941db1ba8 100644
--- a/deps/openssl/config/archs/solaris64-x86_64-gcc/asm_avx2/crypto/buildinf.h
+++ b/deps/openssl/config/archs/solaris64-x86_64-gcc/asm_avx2/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: solaris64-x86_64-gcc"
-#define DATE "built on: Sun Aug  6 00:41:20 2023 UTC"
+#define DATE "built on: Thu Oct 26 15:02:40 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/solaris64-x86_64-gcc/asm_avx2/include/openssl/opensslv.h b/deps/openssl/config/archs/solaris64-x86_64-gcc/asm_avx2/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/solaris64-x86_64-gcc/asm_avx2/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/solaris64-x86_64-gcc/asm_avx2/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/solaris64-x86_64-gcc/asm_avx2/include/openssl/pkcs7.h b/deps/openssl/config/archs/solaris64-x86_64-gcc/asm_avx2/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/solaris64-x86_64-gcc/asm_avx2/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/solaris64-x86_64-gcc/asm_avx2/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/config/archs/solaris64-x86_64-gcc/no-asm/configdata.pm b/deps/openssl/config/archs/solaris64-x86_64-gcc/no-asm/configdata.pm
index a15e817f8966e5..902cd2bbbf9f69 100644
--- a/deps/openssl/config/archs/solaris64-x86_64-gcc/no-asm/configdata.pm
+++ b/deps/openssl/config/archs/solaris64-x86_64-gcc/no-asm/configdata.pm
@@ -154,7 +154,7 @@ our %config = (
     ],
     "dynamic_engines" => "0",
     "ex_libs" => [],
-    "full_version" => "3.0.10+quic",
+    "full_version" => "3.0.12+quic",
     "includes" => [],
     "lflags" => [],
     "lib_defines" => [
@@ -203,7 +203,7 @@ our %config = (
     "openssl_sys_defines" => [],
     "openssldir" => "",
     "options" => "enable-ssl-trace enable-fips no-afalgeng no-asan no-asm no-buildtest-c++ no-comp no-crypto-mdebug no-crypto-mdebug-backtrace no-devcryptoeng no-dynamic-engine no-ec_nistp_64_gcc_128 no-egd no-external-tests no-fuzz-afl no-fuzz-libfuzzer no-ktls no-loadereng no-md2 no-msan no-rc5 no-sctp no-shared no-ssl3 no-ssl3-method no-trace no-ubsan no-unit-test no-uplink no-weak-ssl-ciphers no-zlib no-zlib-dynamic",
-    "patch" => "10",
+    "patch" => "12",
     "perl_archname" => "x86_64-linux-gnu-thread-multi",
     "perl_cmd" => "/usr/bin/perl",
     "perl_version" => "5.34.0",
@@ -256,11 +256,11 @@ our %config = (
     "prerelease" => "",
     "processor" => "",
     "rc4_int" => "unsigned int",
-    "release_date" => "1 Aug 2023",
+    "release_date" => "24 Oct 2023",
     "shlib_version" => "81.3",
     "sourcedir" => ".",
     "target" => "solaris64-x86_64-gcc",
-    "version" => "3.0.10"
+    "version" => "3.0.12"
 );
 our %target = (
     "AR" => "ar",
diff --git a/deps/openssl/config/archs/solaris64-x86_64-gcc/no-asm/crypto/buildinf.h b/deps/openssl/config/archs/solaris64-x86_64-gcc/no-asm/crypto/buildinf.h
index c9d1cb2473635d..84378d6580e182 100644
--- a/deps/openssl/config/archs/solaris64-x86_64-gcc/no-asm/crypto/buildinf.h
+++ b/deps/openssl/config/archs/solaris64-x86_64-gcc/no-asm/crypto/buildinf.h
@@ -11,7 +11,7 @@
  */
 
 #define PLATFORM "platform: solaris64-x86_64-gcc"
-#define DATE "built on: Sun Aug  6 00:41:48 2023 UTC"
+#define DATE "built on: Thu Oct 26 15:03:03 2023 UTC"
 
 /*
  * Generate compiler_flags as an array of individual characters. This is a
diff --git a/deps/openssl/config/archs/solaris64-x86_64-gcc/no-asm/include/openssl/opensslv.h b/deps/openssl/config/archs/solaris64-x86_64-gcc/no-asm/include/openssl/opensslv.h
index 06ba6600ff29ce..ea36c0ca51c2ab 100644
--- a/deps/openssl/config/archs/solaris64-x86_64-gcc/no-asm/include/openssl/opensslv.h
+++ b/deps/openssl/config/archs/solaris64-x86_64-gcc/no-asm/include/openssl/opensslv.h
@@ -29,7 +29,7 @@ extern "C" {
  */
 # define OPENSSL_VERSION_MAJOR  3
 # define OPENSSL_VERSION_MINOR  0
-# define OPENSSL_VERSION_PATCH  10
+# define OPENSSL_VERSION_PATCH  12
 
 /*
  * Additional version information
@@ -74,21 +74,21 @@ extern "C" {
  * longer variant with OPENSSL_VERSION_PRE_RELEASE_STR and
  * OPENSSL_VERSION_BUILD_METADATA_STR appended.
  */
-# define OPENSSL_VERSION_STR "3.0.10"
-# define OPENSSL_FULL_VERSION_STR "3.0.10+quic"
+# define OPENSSL_VERSION_STR "3.0.12"
+# define OPENSSL_FULL_VERSION_STR "3.0.12+quic"
 
 /*
  * SECTION 3: ADDITIONAL METADATA
  *
  * These strings are defined separately to allow them to be parsable.
  */
-# define OPENSSL_RELEASE_DATE "1 Aug 2023"
+# define OPENSSL_RELEASE_DATE "24 Oct 2023"
 
 /*
  * SECTION 4: BACKWARD COMPATIBILITY
  */
 
-# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.10+quic 1 Aug 2023"
+# define OPENSSL_VERSION_TEXT "OpenSSL 3.0.12+quic 24 Oct 2023"
 
 /* Synthesize OPENSSL_VERSION_NUMBER with the layout 0xMNN00PPSL */
 # ifdef OPENSSL_VERSION_PRE_RELEASE
diff --git a/deps/openssl/config/archs/solaris64-x86_64-gcc/no-asm/include/openssl/pkcs7.h b/deps/openssl/config/archs/solaris64-x86_64-gcc/no-asm/include/openssl/pkcs7.h
index 557a0a7264beec..0ce79bf4fa160e 100644
--- a/deps/openssl/config/archs/solaris64-x86_64-gcc/no-asm/include/openssl/pkcs7.h
+++ b/deps/openssl/config/archs/solaris64-x86_64-gcc/no-asm/include/openssl/pkcs7.h
@@ -2,7 +2,7 @@
  * WARNING: do not edit!
  * Generated by Makefile from include/openssl/pkcs7.h.in
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,8 +56,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/openssl-cl_asm.gypi b/deps/openssl/openssl-cl_asm.gypi
index 8791e005bf0f41..cd10355c171228 100644
--- a/deps/openssl/openssl-cl_asm.gypi
+++ b/deps/openssl/openssl-cl_asm.gypi
@@ -1,6 +1,6 @@
 {
   'conditions': [
-    ['target_arch=="ppc64" and OS=="aix"', {
+    ['target_arch=="ppc64" and OS in ("aix", "os400")', {
       'includes': ['config/archs/aix64-gcc-as/asm/openssl-cl.gypi'],
     }, 'target_arch=="ppc64" and OS=="linux" and node_byteorder =="little"', {
       'includes': ['config/archs/linux-ppc64le/asm/openssl-cl.gypi'],
diff --git a/deps/openssl/openssl-cl_asm_avx2.gypi b/deps/openssl/openssl-cl_asm_avx2.gypi
index 815598676770c6..50b5a9c375bd8d 100644
--- a/deps/openssl/openssl-cl_asm_avx2.gypi
+++ b/deps/openssl/openssl-cl_asm_avx2.gypi
@@ -1,6 +1,6 @@
 {
   'conditions': [
-    ['target_arch=="ppc64" and OS=="aix"', {
+    ['target_arch=="ppc64" and OS in ("aix", "os400")', {
       'includes': ['config/archs/aix64-gcc-as/asm_avx2/openssl-cl.gypi'],
     }, 'target_arch=="ppc64" and OS=="linux" and node_byteorder =="little"', {
       'includes': ['config/archs/linux-ppc64le/asm_avx2/openssl-cl.gypi'],
diff --git a/deps/openssl/openssl-cl_no_asm.gypi b/deps/openssl/openssl-cl_no_asm.gypi
index 22bcf1c3c77d84..0964fb36739b3a 100644
--- a/deps/openssl/openssl-cl_no_asm.gypi
+++ b/deps/openssl/openssl-cl_no_asm.gypi
@@ -1,6 +1,6 @@
 {
   'conditions': [
-    ['target_arch=="ppc64" and OS=="aix"', {
+    ['target_arch=="ppc64" and OS in ("aix", "os400")', {
       'includes': ['config/archs/aix64-gcc-as/no-asm/openssl-cl.gypi'],
     }, 'target_arch=="ppc64" and OS=="linux" and node_byteorder =="little"', {
       'includes': ['config/archs/linux-ppc64le/no-asm/openssl-cl.gypi'],
diff --git a/deps/openssl/openssl-fips_asm.gypi b/deps/openssl/openssl-fips_asm.gypi
index d0717df2a5094f..631df9eb893288 100644
--- a/deps/openssl/openssl-fips_asm.gypi
+++ b/deps/openssl/openssl-fips_asm.gypi
@@ -1,6 +1,6 @@
 {
   'conditions': [
-    ['target_arch=="ppc64" and OS=="aix"', {
+    ['target_arch=="ppc64" and OS in ("aix", "os400")', {
       'includes': ['config/archs/aix64-gcc-as/asm/openssl-fips.gypi'],
     }, 'target_arch=="ppc64" and OS=="linux" and node_byteorder =="little"', {
       'includes': ['config/archs/linux-ppc64le/asm/openssl-fips.gypi'],
diff --git a/deps/openssl/openssl-fips_asm_avx2.gypi b/deps/openssl/openssl-fips_asm_avx2.gypi
index d2a2a4bc11413f..4d63cacf29d040 100644
--- a/deps/openssl/openssl-fips_asm_avx2.gypi
+++ b/deps/openssl/openssl-fips_asm_avx2.gypi
@@ -1,6 +1,6 @@
 {
   'conditions': [
-    ['target_arch=="ppc64" and OS=="aix"', {
+    ['target_arch=="ppc64" and OS in ("aix", "os400")', {
       'includes': ['config/archs/aix64-gcc-as/asm_avx2/openssl-fips.gypi'],
     }, 'target_arch=="ppc64" and OS=="linux" and node_byteorder =="little"', {
       'includes': ['config/archs/linux-ppc64le/asm_avx2/openssl-fips.gypi'],
diff --git a/deps/openssl/openssl-fips_no_asm.gypi b/deps/openssl/openssl-fips_no_asm.gypi
index d598bde68c783d..7fdfd772abbce8 100644
--- a/deps/openssl/openssl-fips_no_asm.gypi
+++ b/deps/openssl/openssl-fips_no_asm.gypi
@@ -1,7 +1,7 @@
 {
   'defines': ['OPENSSL_NO_ASM'],
   'conditions': [
-    ['target_arch=="ppc64" and OS=="aix"', {
+    ['target_arch=="ppc64" and OS in ("aix", "os400")', {
       'includes': ['config/archs/aix64-gcc-as/no-asm/openssl-fips.gypi'],
     }, 'target_arch=="ppc64" and OS=="linux" and node_byteorder =="little"', {
       'includes': ['config/archs/linux-ppc64le/no-asm/openssl-fips.gypi'],
diff --git a/deps/openssl/openssl/CHANGES.md b/deps/openssl/openssl/CHANGES.md
index 374fdc662cb94c..7d892d57ac0914 100644
--- a/deps/openssl/openssl/CHANGES.md
+++ b/deps/openssl/openssl/CHANGES.md
@@ -28,12 +28,44 @@ breaking changes, and mappings for the large list of deprecated functions.
 
 [Migration guide]: https://github.com/openssl/openssl/tree/master/doc/man7/migration_guide.pod
 
-### Changes between 3.0.10 and 3.0.10+quic [1 Aug 2023]
+### Changes between 3.0.12 and 3.0.12+quic [24 Oct 2023]
 
 * Add QUIC API support from BoringSSL
 
    *Todd Short*
 
+### Changes between 3.0.11 and 3.0.12 [24 Oct 2023]
+
+ * Fix incorrect key and IV resizing issues when calling EVP_EncryptInit_ex2(),
+   EVP_DecryptInit_ex2() or EVP_CipherInit_ex2() with OSSL_PARAM parameters
+   that alter the key or IV length ([CVE-2023-5363]).
+
+   *Paul Dale*
+
+### Changes between 3.0.10 and 3.0.11 [19 Sep 2023]
+
+ * Fix POLY1305 MAC implementation corrupting XMM registers on Windows.
+
+   The POLY1305 MAC (message authentication code) implementation in OpenSSL
+   does not save the contents of non-volatile XMM registers on Windows 64
+   platform when calculating the MAC of data larger than 64 bytes. Before
+   returning to the caller all the XMM registers are set to zero rather than
+   restoring their previous content. The vulnerable code is used only on newer
+   x86_64 processors supporting the AVX512-IFMA instructions.
+
+   The consequences of this kind of internal application state corruption can
+   be various - from no consequences, if the calling application does not
+   depend on the contents of non-volatile XMM registers at all, to the worst
+   consequences, where the attacker could get complete control of the
+   application process. However given the contents of the registers are just
+   zeroized so the attacker cannot put arbitrary values inside, the most likely
+   consequence, if any, would be an incorrect result of some application
+   dependent calculations or a crash leading to a denial of service.
+
+   ([CVE-2023-4807])
+
+   *Bernd Edlinger*
+
 ### Changes between 3.0.9 and 3.0.10 [1 Aug 2023]
 
  * Fix excessive time spent checking DH q parameter value.
@@ -19714,6 +19746,8 @@ ndif
 
 
 
+[CVE-2023-5363]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-5363
+[CVE-2023-4807]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-4807
 [CVE-2023-3817]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-3817
 [CVE-2023-3446]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-3446
 [CVE-2023-2975]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-2975
diff --git a/deps/openssl/openssl/Configurations/10-main.conf b/deps/openssl/openssl/Configurations/10-main.conf
index 8010087b46dcea..280a75b213f25c 100644
--- a/deps/openssl/openssl/Configurations/10-main.conf
+++ b/deps/openssl/openssl/Configurations/10-main.conf
@@ -9,19 +9,22 @@ sub vc_win64a_info {
             $vc_win64a_info = { AS        => "nasm",
                                 ASFLAGS   => "-g",
                                 asflags   => "-Ox -f win64 -DNEAR",
-                                asoutflag => "-o " };
+                                asoutflag => "-o ",
+                                perlasm_scheme => "nasm" };
         } elsif ($disabled{asm}) {
             # assembler is still used to compile uplink shim
             $vc_win64a_info = { AS        => "ml64",
                                 ASFLAGS   => "/nologo /Zi",
                                 asflags   => "/c /Cp /Cx",
-                                asoutflag => "/Fo" };
+                                asoutflag => "/Fo",
+                                perlasm_scheme => "masm" };
         } else {
             $die->("NASM not found - make sure it's installed and available on %PATH%\n");
             $vc_win64a_info = { AS        => "{unknown}",
                                 ASFLAGS   => "",
                                 asflags   => "",
-                                asoutflag => "" };
+                                asoutflag => "",
+                                perlasm_scheme => "auto" };
         }
     }
     return $vc_win64a_info;
@@ -1416,7 +1419,7 @@ my %targets = (
         sys_id           => "WIN64A",
         uplink_arch      => 'x86_64',
         asm_arch         => 'x86_64',
-        perlasm_scheme   => "auto",
+        perlasm_scheme   => sub { vc_win64a_info()->{perlasm_scheme} },
         multilib         => "-x64",
     },
     "VC-WIN32" => {
diff --git a/deps/openssl/openssl/Configurations/README.md b/deps/openssl/openssl/Configurations/README.md
index be8c394d0872b2..de3d8bad8a02d4 100644
--- a/deps/openssl/openssl/Configurations/README.md
+++ b/deps/openssl/openssl/Configurations/README.md
@@ -233,8 +233,14 @@ In each table entry, the following keys are significant:
                                                 is ILP32;
                            RC4_CHAR             RC4 key schedule is made
                                                 up of 'unsigned char's;
+                                                Note: should not be used
+                                                for new configuration
+                                                targets
                            RC4_INT              RC4 key schedule is made
                                                 up of 'unsigned int's;
+                                                Note: should not be used
+                                                for new configuration
+                                                targets
 
 [1] as part of the target configuration, one can have a key called
   `inherit_from` that indicates what other configurations to inherit
diff --git a/deps/openssl/openssl/Configurations/unix-Makefile.tmpl b/deps/openssl/openssl/Configurations/unix-Makefile.tmpl
index 17e194f1ef754a..a48fae5fb8b8fe 100644
--- a/deps/openssl/openssl/Configurations/unix-Makefile.tmpl
+++ b/deps/openssl/openssl/Configurations/unix-Makefile.tmpl
@@ -614,28 +614,28 @@ uninstall_sw: uninstall_runtime uninstall_modules uninstall_engines uninstall_de
 install_docs: install_man_docs install_html_docs
 
 uninstall_docs: uninstall_man_docs uninstall_html_docs
-	$(RM) -r $(DESTDIR)$(DOCDIR)
+	$(RM) -r "$(DESTDIR)$(DOCDIR)"
 
 {- output_off() if $disabled{fips}; "" -}
 install_fips: build_sw $(INSTALL_FIPSMODULECONF)
 	@[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1)
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(MODULESDIR)
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(OPENSSLDIR)
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(MODULESDIR)"
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(OPENSSLDIR)"
 	@$(ECHO) "*** Installing FIPS module"
 	@$(ECHO) "install $(INSTALL_FIPSMODULE) -> $(DESTDIR)$(MODULESDIR)/$(FIPSMODULENAME)"
-	@cp "$(INSTALL_FIPSMODULE)" $(DESTDIR)$(MODULESDIR)/$(FIPSMODULENAME).new
-	@chmod 755 $(DESTDIR)$(MODULESDIR)/$(FIPSMODULENAME).new
-	@mv -f $(DESTDIR)$(MODULESDIR)/$(FIPSMODULENAME).new \
-	       $(DESTDIR)$(MODULESDIR)/$(FIPSMODULENAME)
+	@cp "$(INSTALL_FIPSMODULE)" "$(DESTDIR)$(MODULESDIR)/$(FIPSMODULENAME).new"
+	@chmod 755 "$(DESTDIR)$(MODULESDIR)/$(FIPSMODULENAME).new"
+	@mv -f "$(DESTDIR)$(MODULESDIR)/$(FIPSMODULENAME).new" \
+	       "$(DESTDIR)$(MODULESDIR)/$(FIPSMODULENAME)"
 	@$(ECHO) "*** Installing FIPS module configuration"
 	@$(ECHO) "install $(INSTALL_FIPSMODULECONF) -> $(DESTDIR)$(OPENSSLDIR)/fipsmodule.cnf"
-	@cp $(INSTALL_FIPSMODULECONF) $(DESTDIR)$(OPENSSLDIR)/fipsmodule.cnf
+	@cp $(INSTALL_FIPSMODULECONF) "$(DESTDIR)$(OPENSSLDIR)/fipsmodule.cnf"
 
 uninstall_fips:
 	@$(ECHO) "*** Uninstalling FIPS module configuration"
-	$(RM) $(DESTDIR)$(OPENSSLDIR)/fipsmodule.cnf
+	$(RM) "$(DESTDIR)$(OPENSSLDIR)/fipsmodule.cnf"
 	@$(ECHO) "*** Uninstalling FIPS module"
-	$(RM) $(DESTDIR)$(MODULESDIR)/$(FIPSMODULENAME)
+	$(RM) "$(DESTDIR)$(MODULESDIR)/$(FIPSMODULENAME)"
 {- if ($disabled{fips}) { output_on(); } else { output_off(); } "" -}
 install_fips:
 	@$(ECHO) "The 'install_fips' target requires the 'enable-fips' option"
@@ -646,75 +646,75 @@ uninstall_fips:
 
 
 install_ssldirs:
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(OPENSSLDIR)/certs
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(OPENSSLDIR)/private
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(OPENSSLDIR)/misc
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(OPENSSLDIR)/certs"
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(OPENSSLDIR)/private"
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(OPENSSLDIR)/misc"
 	@set -e; for x in dummy $(MISC_SCRIPTS); do \
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		x1=`echo "$$x" | cut -f1 -d:`; \
 		x2=`echo "$$x" | cut -f2 -d:`; \
 		fn=`basename $$x1`; \
 		$(ECHO) "install $$x1 -> $(DESTDIR)$(OPENSSLDIR)/misc/$$fn"; \
-		cp $$x1 $(DESTDIR)$(OPENSSLDIR)/misc/$$fn.new; \
-		chmod 755 $(DESTDIR)$(OPENSSLDIR)/misc/$$fn.new; \
-		mv -f $(DESTDIR)$(OPENSSLDIR)/misc/$$fn.new \
-		      $(DESTDIR)$(OPENSSLDIR)/misc/$$fn; \
+		cp $$x1 "$(DESTDIR)$(OPENSSLDIR)/misc/$$fn.new"; \
+		chmod 755 "$(DESTDIR)$(OPENSSLDIR)/misc/$$fn.new"; \
+		mv -f "$(DESTDIR)$(OPENSSLDIR)/misc/$$fn.new" \
+		      "$(DESTDIR)$(OPENSSLDIR)/misc/$$fn"; \
 		if [ "$$x1" != "$$x2" ]; then \
 			ln=`basename "$$x2"`; \
 			: {- output_off() unless windowsdll(); "" -}; \
 			$(ECHO) "copy $(DESTDIR)$(OPENSSLDIR)/misc/$$ln -> $(DESTDIR)$(OPENSSLDIR)/misc/$$fn"; \
-			cp $(DESTDIR)$(OPENSSLDIR)/misc/$$fn $(DESTDIR)$(OPENSSLDIR)/misc/$$ln; \
+			cp "$(DESTDIR)$(OPENSSLDIR)/misc/$$fn" "$(DESTDIR)$(OPENSSLDIR)/misc/$$ln"; \
 			: {- output_on() unless windowsdll();
 			     output_off() if windowsdll(); "" -}; \
 			$(ECHO) "link $(DESTDIR)$(OPENSSLDIR)/misc/$$ln -> $(DESTDIR)$(OPENSSLDIR)/misc/$$fn"; \
-			ln -sf $$fn $(DESTDIR)$(OPENSSLDIR)/misc/$$ln; \
+			ln -sf $$fn "$(DESTDIR)$(OPENSSLDIR)/misc/$$ln"; \
 			: {- output_on() if windowsdll(); "" -}; \
 		fi; \
 	done
 	@$(ECHO) "install $(SRCDIR)/apps/openssl.cnf -> $(DESTDIR)$(OPENSSLDIR)/openssl.cnf.dist"
-	@cp $(SRCDIR)/apps/openssl.cnf $(DESTDIR)$(OPENSSLDIR)/openssl.cnf.new
-	@chmod 644 $(DESTDIR)$(OPENSSLDIR)/openssl.cnf.new
-	@mv -f  $(DESTDIR)$(OPENSSLDIR)/openssl.cnf.new $(DESTDIR)$(OPENSSLDIR)/openssl.cnf.dist
+	@cp $(SRCDIR)/apps/openssl.cnf "$(DESTDIR)$(OPENSSLDIR)/openssl.cnf.new"
+	@chmod 644 "$(DESTDIR)$(OPENSSLDIR)/openssl.cnf.new"
+	@mv -f  "$(DESTDIR)$(OPENSSLDIR)/openssl.cnf.new" "$(DESTDIR)$(OPENSSLDIR)/openssl.cnf.dist"
 	@if [ ! -f "$(DESTDIR)$(OPENSSLDIR)/openssl.cnf" ]; then \
 		$(ECHO) "install $(SRCDIR)/apps/openssl.cnf -> $(DESTDIR)$(OPENSSLDIR)/openssl.cnf"; \
-		cp $(SRCDIR)/apps/openssl.cnf $(DESTDIR)$(OPENSSLDIR)/openssl.cnf; \
-		chmod 644 $(DESTDIR)$(OPENSSLDIR)/openssl.cnf; \
+		cp $(SRCDIR)/apps/openssl.cnf "$(DESTDIR)$(OPENSSLDIR)/openssl.cnf"; \
+		chmod 644 "$(DESTDIR)$(OPENSSLDIR)/openssl.cnf"; \
 	fi
 	@$(ECHO) "install $(SRCDIR)/apps/ct_log_list.cnf -> $(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf.dist"
-	@cp $(SRCDIR)/apps/ct_log_list.cnf $(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf.new
-	@chmod 644 $(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf.new
-	@mv -f  $(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf.new $(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf.dist
+	@cp $(SRCDIR)/apps/ct_log_list.cnf "$(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf.new"
+	@chmod 644 "$(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf.new"
+	@mv -f  "$(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf.new" "$(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf.dist"
 	@if [ ! -f "$(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf" ]; then \
 		$(ECHO) "install $(SRCDIR)/apps/ct_log_list.cnf -> $(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf"; \
-		cp $(SRCDIR)/apps/ct_log_list.cnf $(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf; \
-		chmod 644 $(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf; \
+		cp $(SRCDIR)/apps/ct_log_list.cnf "$(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf"; \
+		chmod 644 "$(DESTDIR)$(OPENSSLDIR)/ct_log_list.cnf"; \
 	fi
 
 install_dev: install_runtime_libs
 	@[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1)
 	@$(ECHO) "*** Installing development files"
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(INSTALLTOP)/include/openssl
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(INSTALLTOP)/include/openssl"
 	@ : {- output_off() if $disabled{uplink}; "" -}
 	@$(ECHO) "install $(SRCDIR)/ms/applink.c -> $(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c"
-	@cp $(SRCDIR)/ms/applink.c $(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c
-	@chmod 644 $(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c
+	@cp $(SRCDIR)/ms/applink.c "$(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c"
+	@chmod 644 "$(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c"
 	@ : {- output_on() if $disabled{uplink}; "" -}
 	@set -e; for i in $(SRCDIR)/include/openssl/*.h \
 			  $(BLDDIR)/include/openssl/*.h; do \
 		fn=`basename $$i`; \
 		$(ECHO) "install $$i -> $(DESTDIR)$(INSTALLTOP)/include/openssl/$$fn"; \
-		cp $$i $(DESTDIR)$(INSTALLTOP)/include/openssl/$$fn; \
-		chmod 644 $(DESTDIR)$(INSTALLTOP)/include/openssl/$$fn; \
+		cp $$i "$(DESTDIR)$(INSTALLTOP)/include/openssl/$$fn"; \
+		chmod 644 "$(DESTDIR)$(INSTALLTOP)/include/openssl/$$fn"; \
 	done
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(libdir)
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(libdir)"
 	@set -e; for l in $(INSTALL_LIBS); do \
 		fn=`basename $$l`; \
 		$(ECHO) "install $$l -> $(DESTDIR)$(libdir)/$$fn"; \
-		cp $$l $(DESTDIR)$(libdir)/$$fn.new; \
-		$(RANLIB) $(DESTDIR)$(libdir)/$$fn.new; \
-		chmod 644 $(DESTDIR)$(libdir)/$$fn.new; \
-		mv -f $(DESTDIR)$(libdir)/$$fn.new \
-		      $(DESTDIR)$(libdir)/$$fn; \
+		cp $$l "$(DESTDIR)$(libdir)/$$fn.new"; \
+		$(RANLIB) "$(DESTDIR)$(libdir)/$$fn.new"; \
+		chmod 644 "$(DESTDIR)$(libdir)/$$fn.new"; \
+		mv -f "$(DESTDIR)$(libdir)/$$fn.new" \
+		      "$(DESTDIR)$(libdir)/$$fn"; \
 	done
 	@ : {- output_off() if $disabled{shared}; "" -}
 	@set -e; for s in $(INSTALL_SHLIB_INFO); do \
@@ -727,18 +727,18 @@ install_dev: install_runtime_libs
 		: {- output_off(); output_on() unless windowsdll() or sharedaix(); "" -}; \
 		if [ "$$fn2" != "" ]; then \
 			$(ECHO) "link $(DESTDIR)$(libdir)/$$fn2 -> $(DESTDIR)$(libdir)/$$fn1"; \
-			ln -sf $$fn1 $(DESTDIR)$(libdir)/$$fn2; \
+			ln -sf $$fn1 "$(DESTDIR)$(libdir)/$$fn2"; \
 		fi; \
 		: {- output_off() unless windowsdll() or sharedaix(); output_on() if windowsdll(); "" -}; \
 		if [ "$$fn3" != "" ]; then \
 			$(ECHO) "install $$s3 -> $(DESTDIR)$(libdir)/$$fn3"; \
-			cp $$s3 $(DESTDIR)$(libdir)/$$fn3.new; \
-			chmod 755 $(DESTDIR)$(libdir)/$$fn3.new; \
-			mv -f $(DESTDIR)$(libdir)/$$fn3.new \
-			      $(DESTDIR)$(libdir)/$$fn3; \
+			cp $$s3 "$(DESTDIR)$(libdir)/$$fn3.new"; \
+			chmod 755 "$(DESTDIR)$(libdir)/$$fn3.new"; \
+			mv -f "$(DESTDIR)$(libdir)/$$fn3.new" \
+			      "$(DESTDIR)$(libdir)/$$fn3"; \
 		fi; \
 		: {- output_off() if windowsdll(); output_on() if sharedaix(); "" -}; \
-		a=$(DESTDIR)$(libdir)/$$fn2; \
+		a="$(DESTDIR)$(libdir)/$$fn2"; \
 		$(ECHO) "install $$s1 -> $$a"; \
 		if [ -f $$a ]; then ( trap "rm -rf /tmp/ar.$$$$" INT 0; \
 			mkdir /tmp/ar.$$$$; ( cd /tmp/ar.$$$$; \
@@ -755,35 +755,35 @@ install_dev: install_runtime_libs
 		: {- output_off() if sharedaix(); output_on(); "" -}; \
 	done
 	@ : {- output_on() if $disabled{shared}; "" -}
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(libdir)/pkgconfig
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(libdir)/pkgconfig"
 	@$(ECHO) "install libcrypto.pc -> $(DESTDIR)$(libdir)/pkgconfig/libcrypto.pc"
-	@cp libcrypto.pc $(DESTDIR)$(libdir)/pkgconfig
-	@chmod 644 $(DESTDIR)$(libdir)/pkgconfig/libcrypto.pc
+	@cp libcrypto.pc "$(DESTDIR)$(libdir)/pkgconfig"
+	@chmod 644 "$(DESTDIR)$(libdir)/pkgconfig/libcrypto.pc"
 	@$(ECHO) "install libssl.pc -> $(DESTDIR)$(libdir)/pkgconfig/libssl.pc"
-	@cp libssl.pc $(DESTDIR)$(libdir)/pkgconfig
-	@chmod 644 $(DESTDIR)$(libdir)/pkgconfig/libssl.pc
+	@cp libssl.pc "$(DESTDIR)$(libdir)/pkgconfig"
+	@chmod 644 "$(DESTDIR)$(libdir)/pkgconfig/libssl.pc"
 	@$(ECHO) "install openssl.pc -> $(DESTDIR)$(libdir)/pkgconfig/openssl.pc"
-	@cp openssl.pc $(DESTDIR)$(libdir)/pkgconfig
-	@chmod 644 $(DESTDIR)$(libdir)/pkgconfig/openssl.pc
+	@cp openssl.pc "$(DESTDIR)$(libdir)/pkgconfig"
+	@chmod 644 "$(DESTDIR)$(libdir)/pkgconfig/openssl.pc"
 
 uninstall_dev: uninstall_runtime_libs
 	@$(ECHO) "*** Uninstalling development files"
 	@ : {- output_off() if $disabled{uplink}; "" -}
 	@$(ECHO) "$(RM) $(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c"
-	@$(RM) $(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c
+	@$(RM) "$(DESTDIR)$(INSTALLTOP)/include/openssl/applink.c"
 	@ : {- output_on() if $disabled{uplink}; "" -}
 	@set -e; for i in $(SRCDIR)/include/openssl/*.h \
 			  $(BLDDIR)/include/openssl/*.h; do \
 		fn=`basename $$i`; \
 		$(ECHO) "$(RM) $(DESTDIR)$(INSTALLTOP)/include/openssl/$$fn"; \
-		$(RM) $(DESTDIR)$(INSTALLTOP)/include/openssl/$$fn; \
+		$(RM) "$(DESTDIR)$(INSTALLTOP)/include/openssl/$$fn"; \
 	done
-	-$(RMDIR) $(DESTDIR)$(INSTALLTOP)/include/openssl
-	-$(RMDIR) $(DESTDIR)$(INSTALLTOP)/include
+	-$(RMDIR) "$(DESTDIR)$(INSTALLTOP)/include/openssl"
+	-$(RMDIR) "$(DESTDIR)$(INSTALLTOP)/include"
 	@set -e; for l in $(INSTALL_LIBS); do \
 		fn=`basename $$l`; \
 		$(ECHO) "$(RM) $(DESTDIR)$(libdir)/$$fn"; \
-		$(RM) $(DESTDIR)$(libdir)/$$fn; \
+		$(RM) "$(DESTDIR)$(libdir)/$$fn"; \
 	done
 	@ : {- output_off() if $disabled{shared}; "" -}
 	@set -e; for s in $(INSTALL_SHLIB_INFO); do \
@@ -795,39 +795,39 @@ uninstall_dev: uninstall_runtime_libs
 		fn3=`basename "$$s3"`; \
 		: {- output_off() if windowsdll(); "" -}; \
 		$(ECHO) "$(RM) $(DESTDIR)$(libdir)/$$fn1"; \
-		$(RM) $(DESTDIR)$(libdir)/$$fn1; \
+		$(RM) "$(DESTDIR)$(libdir)/$$fn1"; \
 		if [ -n "$$fn2" ]; then \
 			$(ECHO) "$(RM) $(DESTDIR)$(libdir)/$$fn2"; \
-			$(RM) $(DESTDIR)$(libdir)/$$fn2; \
+			$(RM) "$(DESTDIR)$(libdir)/$$fn2"; \
 		fi; \
 		: {- output_on() if windowsdll(); "" -}{- output_off() unless windowsdll(); "" -}; \
 		if [ -n "$$fn3" ]; then \
 			$(ECHO) "$(RM) $(DESTDIR)$(libdir)/$$fn3"; \
-			$(RM) $(DESTDIR)$(libdir)/$$fn3; \
+			$(RM) "$(DESTDIR)$(libdir)/$$fn3"; \
 		fi; \
 		: {- output_on() unless windowsdll(); "" -}; \
 	done
 	@ : {- output_on() if $disabled{shared}; "" -}
-	$(RM) $(DESTDIR)$(libdir)/pkgconfig/libcrypto.pc
-	$(RM) $(DESTDIR)$(libdir)/pkgconfig/libssl.pc
-	$(RM) $(DESTDIR)$(libdir)/pkgconfig/openssl.pc
-	-$(RMDIR) $(DESTDIR)$(libdir)/pkgconfig
-	-$(RMDIR) $(DESTDIR)$(libdir)
+	$(RM) "$(DESTDIR)$(libdir)/pkgconfig/libcrypto.pc"
+	$(RM) "$(DESTDIR)$(libdir)/pkgconfig/libssl.pc"
+	$(RM) "$(DESTDIR)$(libdir)/pkgconfig/openssl.pc"
+	-$(RMDIR) "$(DESTDIR)$(libdir)/pkgconfig"
+	-$(RMDIR) "$(DESTDIR)$(libdir)"
 
 _install_modules_deps: install_runtime_libs build_modules
 
 install_engines: _install_modules_deps
 	@[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1)
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(ENGINESDIR)/
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(ENGINESDIR)/"
 	@$(ECHO) "*** Installing engines"
 	@set -e; for e in dummy $(INSTALL_ENGINES); do \
 		if [ "$$e" = "dummy" ]; then continue; fi; \
 		fn=`basename $$e`; \
 		$(ECHO) "install $$e -> $(DESTDIR)$(ENGINESDIR)/$$fn"; \
-		cp $$e $(DESTDIR)$(ENGINESDIR)/$$fn.new; \
-		chmod 755 $(DESTDIR)$(ENGINESDIR)/$$fn.new; \
-		mv -f $(DESTDIR)$(ENGINESDIR)/$$fn.new \
-		      $(DESTDIR)$(ENGINESDIR)/$$fn; \
+		cp $$e "$(DESTDIR)$(ENGINESDIR)/$$fn.new"; \
+		chmod 755 "$(DESTDIR)$(ENGINESDIR)/$$fn.new"; \
+		mv -f "$(DESTDIR)$(ENGINESDIR)/$$fn.new" \
+		      "$(DESTDIR)$(ENGINESDIR)/$$fn"; \
 	done
 
 uninstall_engines:
@@ -836,22 +836,22 @@ uninstall_engines:
 		if [ "$$e" = "dummy" ]; then continue; fi; \
 		fn=`basename $$e`; \
 		$(ECHO) "$(RM) $(DESTDIR)$(ENGINESDIR)/$$fn"; \
-		$(RM) $(DESTDIR)$(ENGINESDIR)/$$fn; \
+		$(RM) "$(DESTDIR)$(ENGINESDIR)/$$fn"; \
 	done
-	-$(RMDIR) $(DESTDIR)$(ENGINESDIR)
+	-$(RMDIR) "$(DESTDIR)$(ENGINESDIR)"
 
 install_modules: _install_modules_deps
 	@[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1)
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(MODULESDIR)/
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(MODULESDIR)/"
 	@$(ECHO) "*** Installing modules"
 	@set -e; for e in dummy $(INSTALL_MODULES); do \
 		if [ "$$e" = "dummy" ]; then continue; fi; \
 		fn=`basename $$e`; \
 		$(ECHO) "install $$e -> $(DESTDIR)$(MODULESDIR)/$$fn"; \
-		cp $$e $(DESTDIR)$(MODULESDIR)/$$fn.new; \
-		chmod 755 $(DESTDIR)$(MODULESDIR)/$$fn.new; \
-		mv -f $(DESTDIR)$(MODULESDIR)/$$fn.new \
-		      $(DESTDIR)$(MODULESDIR)/$$fn; \
+		cp $$e "$(DESTDIR)$(MODULESDIR)/$$fn.new"; \
+		chmod 755 "$(DESTDIR)$(MODULESDIR)/$$fn.new"; \
+		mv -f "$(DESTDIR)$(MODULESDIR)/$$fn.new" \
+		      "$(DESTDIR)$(MODULESDIR)/$$fn"; \
 	done
 
 uninstall_modules:
@@ -860,18 +860,18 @@ uninstall_modules:
 		if [ "$$e" = "dummy" ]; then continue; fi; \
 		fn=`basename $$e`; \
 		$(ECHO) "$(RM) $(DESTDIR)$(MODULESDIR)/$$fn"; \
-		$(RM) $(DESTDIR)$(MODULESDIR)/$$fn; \
+		$(RM) "$(DESTDIR)$(MODULESDIR)/$$fn"; \
 	done
-	-$(RMDIR) $(DESTDIR)$(MODULESDIR)
+	-$(RMDIR) "$(DESTDIR)$(MODULESDIR)"
 
 install_runtime: install_programs
 
 install_runtime_libs: build_libs
 	@[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1)
 	@ : {- output_off() if windowsdll(); "" -}
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(libdir)
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(libdir)"
 	@ : {- output_on() if windowsdll(); output_off() unless windowsdll(); "" -}
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(INSTALLTOP)/bin
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(INSTALLTOP)/bin"
 	@ : {- output_on() unless windowsdll(); "" -}
 	@$(ECHO) "*** Installing runtime libraries"
 	@set -e; for s in dummy $(INSTALL_SHLIBS); do \
@@ -879,40 +879,40 @@ install_runtime_libs: build_libs
 		fn=`basename $$s`; \
 		: {- output_off() unless windowsdll(); "" -}; \
 		$(ECHO) "install $$s -> $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
-		cp $$s $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new; \
-		chmod 755 $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new; \
-		mv -f $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new \
-		      $(DESTDIR)$(INSTALLTOP)/bin/$$fn; \
+		cp $$s "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new"; \
+		chmod 755 "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new"; \
+		mv -f "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new" \
+		      "$(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
 		: {- output_on() unless windowsdll(); "" -}{- output_off() if windowsdll(); "" -}; \
 		$(ECHO) "install $$s -> $(DESTDIR)$(libdir)/$$fn"; \
-		cp $$s $(DESTDIR)$(libdir)/$$fn.new; \
-		chmod 755 $(DESTDIR)$(libdir)/$$fn.new; \
-		mv -f $(DESTDIR)$(libdir)/$$fn.new \
-		      $(DESTDIR)$(libdir)/$$fn; \
+		cp $$s "$(DESTDIR)$(libdir)/$$fn.new"; \
+		chmod 755 "$(DESTDIR)$(libdir)/$$fn.new"; \
+		mv -f "$(DESTDIR)$(libdir)/$$fn.new" \
+		      "$(DESTDIR)$(libdir)/$$fn"; \
 		: {- output_on() if windowsdll(); "" -}; \
 	done
 
 install_programs: install_runtime_libs build_programs
 	@[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1)
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(INSTALLTOP)/bin
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(INSTALLTOP)/bin"
 	@$(ECHO) "*** Installing runtime programs"
 	@set -e; for x in dummy $(INSTALL_PROGRAMS); do \
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "install $$x -> $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
-		cp $$x $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new; \
-		chmod 755 $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new; \
-		mv -f $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new \
-		      $(DESTDIR)$(INSTALLTOP)/bin/$$fn; \
+		cp $$x "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new"; \
+		chmod 755 "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new"; \
+		mv -f "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new" \
+		      "$(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
 	done
 	@set -e; for x in dummy $(BIN_SCRIPTS); do \
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "install $$x -> $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
-		cp $$x $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new; \
-		chmod 755 $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new; \
-		mv -f $(DESTDIR)$(INSTALLTOP)/bin/$$fn.new \
-		      $(DESTDIR)$(INSTALLTOP)/bin/$$fn; \
+		cp $$x "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new"; \
+		chmod 755 "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new"; \
+		mv -f "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new" \
+		      "$(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
 	done
 
 uninstall_runtime: uninstall_programs uninstall_runtime_libs
@@ -924,16 +924,16 @@ uninstall_programs:
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "$(RM) $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
-		$(RM) $(DESTDIR)$(INSTALLTOP)/bin/$$fn; \
+		$(RM) "$(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
 	done;
 	@set -e; for x in dummy $(BIN_SCRIPTS); \
 	do  \
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "$(RM) $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
-		$(RM) $(DESTDIR)$(INSTALLTOP)/bin/$$fn; \
+		$(RM) "$(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
 	done
-	-$(RMDIR) $(DESTDIR)$(INSTALLTOP)/bin
+	-$(RMDIR) "$(DESTDIR)$(INSTALLTOP)/bin"
 
 uninstall_runtime_libs:
 	@$(ECHO) "*** Uninstalling runtime libraries"
@@ -942,49 +942,49 @@ uninstall_runtime_libs:
 		if [ "$$s" = "dummy" ]; then continue; fi; \
 		fn=`basename $$s`; \
 		$(ECHO) "$(RM) $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
-		$(RM) $(DESTDIR)$(INSTALLTOP)/bin/$$fn; \
+		$(RM) "$(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \
 	done
 	@ : {- output_on() unless windowsdll(); "" -}
 
 
 install_man_docs: build_man_docs
 	@[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1)
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(MANDIR)/man1
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(MANDIR)/man3
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(MANDIR)/man5
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(MANDIR)/man7
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(MANDIR)/man1"
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(MANDIR)/man3"
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(MANDIR)/man5"
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(MANDIR)/man7"
 	@$(ECHO) "*** Installing manpages"
 	@set -e; for x in dummy $(MANDOCS1); do \
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "install $$x -> $(DESTDIR)$(MANDIR)/man1/$${fn}$(MANSUFFIX)"; \
-		cp $$x $(DESTDIR)$(MANDIR)/man1/$${fn}$(MANSUFFIX); \
-		chmod 644 $(DESTDIR)$(MANDIR)/man1/$${fn}$(MANSUFFIX); \
-		$(PERL) $(SRCDIR)/util/write-man-symlinks install $(SRCDIR)/doc/man1 $(BLDDIR)/doc/man1 $${fn}$(MANSUFFIX) $(DESTDIR)$(MANDIR)/man1; \
+		cp $$x "$(DESTDIR)$(MANDIR)/man1/$${fn}$(MANSUFFIX)"; \
+		chmod 644 "$(DESTDIR)$(MANDIR)/man1/$${fn}$(MANSUFFIX)"; \
+		$(PERL) $(SRCDIR)/util/write-man-symlinks install $(SRCDIR)/doc/man1 $(BLDDIR)/doc/man1 $${fn}$(MANSUFFIX) "$(DESTDIR)$(MANDIR)/man1"; \
 	done
 	@set -e; for x in dummy $(MANDOCS3); do \
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "install $$x -> $(DESTDIR)$(MANDIR)/man3/$${fn}$(MANSUFFIX)"; \
-		cp $$x $(DESTDIR)$(MANDIR)/man3/$${fn}$(MANSUFFIX); \
-		chmod 644 $(DESTDIR)$(MANDIR)/man3/$${fn}$(MANSUFFIX); \
-		$(PERL) $(SRCDIR)/util/write-man-symlinks install $(SRCDIR)/doc/man3 $(BLDDIR)/doc/man3 $${fn}$(MANSUFFIX) $(DESTDIR)$(MANDIR)/man3; \
+		cp $$x "$(DESTDIR)$(MANDIR)/man3/$${fn}$(MANSUFFIX)"; \
+		chmod 644 "$(DESTDIR)$(MANDIR)/man3/$${fn}$(MANSUFFIX)"; \
+		$(PERL) $(SRCDIR)/util/write-man-symlinks install $(SRCDIR)/doc/man3 $(BLDDIR)/doc/man3 $${fn}$(MANSUFFIX) "$(DESTDIR)$(MANDIR)/man3"; \
 	done
 	@set -e; for x in dummy $(MANDOCS5); do \
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "install $$x -> $(DESTDIR)$(MANDIR)/man5/$${fn}$(MANSUFFIX)"; \
-		cp $$x $(DESTDIR)$(MANDIR)/man5/$${fn}$(MANSUFFIX); \
-		chmod 644 $(DESTDIR)$(MANDIR)/man5/$${fn}$(MANSUFFIX); \
-		$(PERL) $(SRCDIR)/util/write-man-symlinks install $(SRCDIR)/doc/man5 $(BLDDIR)/doc/man5 $${fn}$(MANSUFFIX) $(DESTDIR)$(MANDIR)/man5; \
+		cp $$x "$(DESTDIR)$(MANDIR)/man5/$${fn}$(MANSUFFIX)"; \
+		chmod 644 "$(DESTDIR)$(MANDIR)/man5/$${fn}$(MANSUFFIX)"; \
+		$(PERL) $(SRCDIR)/util/write-man-symlinks install $(SRCDIR)/doc/man5 $(BLDDIR)/doc/man5 $${fn}$(MANSUFFIX) "$(DESTDIR)$(MANDIR)/man5"; \
 	done
 	@set -e; for x in dummy $(MANDOCS7); do \
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "install $$x -> $(DESTDIR)$(MANDIR)/man7/$${fn}$(MANSUFFIX)"; \
-		cp $$x $(DESTDIR)$(MANDIR)/man7/$${fn}$(MANSUFFIX); \
-		chmod 644 $(DESTDIR)$(MANDIR)/man7/$${fn}$(MANSUFFIX); \
-		$(PERL) $(SRCDIR)/util/write-man-symlinks install $(SRCDIR)/doc/man7 $(BLDDIR)/doc/man7 $${fn}$(MANSUFFIX) $(DESTDIR)$(MANDIR)/man7; \
+		cp $$x "$(DESTDIR)$(MANDIR)/man7/$${fn}$(MANSUFFIX)"; \
+		chmod 644 "$(DESTDIR)$(MANDIR)/man7/$${fn}$(MANSUFFIX)"; \
+		$(PERL) $(SRCDIR)/util/write-man-symlinks install $(SRCDIR)/doc/man7 $(BLDDIR)/doc/man7 $${fn}$(MANSUFFIX) "$(DESTDIR)$(MANDIR)/man7"; \
 	done
 
 uninstall_man_docs: build_man_docs
@@ -993,65 +993,65 @@ uninstall_man_docs: build_man_docs
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "$(RM) $(DESTDIR)$(MANDIR)/man1/$${fn}$(MANSUFFIX)"; \
-		$(RM) $(DESTDIR)$(MANDIR)/man1/$${fn}$(MANSUFFIX); \
-		$(PERL) $(SRCDIR)/util/write-man-symlinks uninstall $(SRCDIR)/doc/man1 $(BLDDIR)/doc/man1 $${fn}$(MANSUFFIX) $(DESTDIR)$(MANDIR)/man1; \
+		$(RM) "$(DESTDIR)$(MANDIR)/man1/$${fn}$(MANSUFFIX)"; \
+		$(PERL) $(SRCDIR)/util/write-man-symlinks uninstall $(SRCDIR)/doc/man1 $(BLDDIR)/doc/man1 $${fn}$(MANSUFFIX) "$(DESTDIR)$(MANDIR)/man1"; \
 	done
 	@set -e; for x in dummy $(MANDOCS3); do \
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "$(RM) $(DESTDIR)$(MANDIR)/man3/$${fn}$(MANSUFFIX)"; \
-		$(RM) $(DESTDIR)$(MANDIR)/man3/$${fn}$(MANSUFFIX); \
-		$(PERL) $(SRCDIR)/util/write-man-symlinks uninstall $(SRCDIR)/doc/man3 $(BLDDIR)/doc/man3 $${fn}$(MANSUFFIX) $(DESTDIR)$(MANDIR)/man3; \
+		$(RM) "$(DESTDIR)$(MANDIR)/man3/$${fn}$(MANSUFFIX)"; \
+		$(PERL) $(SRCDIR)/util/write-man-symlinks uninstall $(SRCDIR)/doc/man3 $(BLDDIR)/doc/man3 $${fn}$(MANSUFFIX) "$(DESTDIR)$(MANDIR)/man3"; \
 	done
 	@set -e; for x in dummy $(MANDOCS5); do \
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "$(RM) $(DESTDIR)$(MANDIR)/man5/$${fn}$(MANSUFFIX)"; \
-		$(RM) $(DESTDIR)$(MANDIR)/man5/$${fn}$(MANSUFFIX); \
-		$(PERL) $(SRCDIR)/util/write-man-symlinks uninstall $(SRCDIR)/doc/man5 $(BLDDIR)/doc/man5 $${fn}$(MANSUFFIX) $(DESTDIR)$(MANDIR)/man5; \
+		$(RM) "$(DESTDIR)$(MANDIR)/man5/$${fn}$(MANSUFFIX)"; \
+		$(PERL) $(SRCDIR)/util/write-man-symlinks uninstall $(SRCDIR)/doc/man5 $(BLDDIR)/doc/man5 $${fn}$(MANSUFFIX) "$(DESTDIR)$(MANDIR)/man5"; \
 	done
 	@set -e; for x in dummy $(MANDOCS7); do \
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "$(RM) $(DESTDIR)$(MANDIR)/man7/$${fn}$(MANSUFFIX)"; \
-		$(RM) $(DESTDIR)$(MANDIR)/man7/$${fn}$(MANSUFFIX); \
-		$(PERL) $(SRCDIR)/util/write-man-symlinks uninstall $(SRCDIR)/doc/man7 $(BLDDIR)/doc/man7 $${fn}$(MANSUFFIX) $(DESTDIR)$(MANDIR)/man7; \
+		$(RM) "$(DESTDIR)$(MANDIR)/man7/$${fn}$(MANSUFFIX)"; \
+		$(PERL) $(SRCDIR)/util/write-man-symlinks uninstall $(SRCDIR)/doc/man7 $(BLDDIR)/doc/man7 $${fn}$(MANSUFFIX) "$(DESTDIR)$(MANDIR)/man7"; \
 	done
 
 install_html_docs: install_image_docs build_html_docs
 	@[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1)
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(HTMLDIR)/man1
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(HTMLDIR)/man3
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(HTMLDIR)/man5
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(HTMLDIR)/man7
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(HTMLDIR)/man1"
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(HTMLDIR)/man3"
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(HTMLDIR)/man5"
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(HTMLDIR)/man7"
 	@$(ECHO) "*** Installing HTML manpages"
 	@set -e; for x in dummy $(HTMLDOCS1); do \
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "install $$x -> $(DESTDIR)$(HTMLDIR)/man1/$$fn"; \
-		cp $$x $(DESTDIR)$(HTMLDIR)/man1/$$fn; \
-		chmod 644 $(DESTDIR)$(HTMLDIR)/man1/$$fn; \
+		cp $$x "$(DESTDIR)$(HTMLDIR)/man1/$$fn"; \
+		chmod 644 "$(DESTDIR)$(HTMLDIR)/man1/$$fn"; \
 	done
 	@set -e; for x in dummy $(HTMLDOCS3); do \
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "install $$x -> $(DESTDIR)$(HTMLDIR)/man3/$$fn"; \
-		cp $$x $(DESTDIR)$(HTMLDIR)/man3/$$fn; \
-		chmod 644 $(DESTDIR)$(HTMLDIR)/man3/$$fn; \
+		cp $$x "$(DESTDIR)$(HTMLDIR)/man3/$$fn"; \
+		chmod 644 "$(DESTDIR)$(HTMLDIR)/man3/$$fn"; \
 	done
 	@set -e; for x in dummy $(HTMLDOCS5); do \
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "install $$x -> $(DESTDIR)$(HTMLDIR)/man5/$$fn"; \
-		cp $$x $(DESTDIR)$(HTMLDIR)/man5/$$fn; \
-		chmod 644 $(DESTDIR)$(HTMLDIR)/man5/$$fn; \
+		cp $$x "$(DESTDIR)$(HTMLDIR)/man5/$$fn"; \
+		chmod 644 "$(DESTDIR)$(HTMLDIR)/man5/$$fn"; \
 	done
 	@set -e; for x in dummy $(HTMLDOCS7); do \
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "install $$x -> $(DESTDIR)$(HTMLDIR)/man7/$$fn"; \
-		cp $$x $(DESTDIR)$(HTMLDIR)/man7/$$fn; \
-		chmod 644 $(DESTDIR)$(HTMLDIR)/man7/$$fn; \
+		cp $$x "$(DESTDIR)$(HTMLDIR)/man7/$$fn"; \
+		chmod 644 "$(DESTDIR)$(HTMLDIR)/man7/$$fn"; \
 	done
 
 uninstall_html_docs: uninstall_image_docs
@@ -1060,35 +1060,35 @@ uninstall_html_docs: uninstall_image_docs
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "$(RM) $(DESTDIR)$(HTMLDIR)/man1/$$fn"; \
-		$(RM) $(DESTDIR)$(HTMLDIR)/man1/$$fn; \
+		$(RM) "$(DESTDIR)$(HTMLDIR)/man1/$$fn"; \
 	done
 	@set -e; for x in dummy $(HTMLDOCS3); do \
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "$(RM) $(DESTDIR)$(HTMLDIR)/man3/$$fn"; \
-		$(RM) $(DESTDIR)$(HTMLDIR)/man3/$$fn; \
+		$(RM) "$(DESTDIR)$(HTMLDIR)/man3/$$fn"; \
 	done
 	@set -e; for x in dummy $(HTMLDOCS5); do \
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "$(RM) $(DESTDIR)$(HTMLDIR)/man5/$$fn"; \
-		$(RM) $(DESTDIR)$(HTMLDIR)/man5/$$fn; \
+		$(RM) "$(DESTDIR)$(HTMLDIR)/man5/$$fn"; \
 	done
 	@set -e; for x in dummy $(HTMLDOCS7); do \
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "$(RM) $(DESTDIR)$(HTMLDIR)/man7/$$fn"; \
-		$(RM) $(DESTDIR)$(HTMLDIR)/man7/$$fn; \
+		$(RM) "$(DESTDIR)$(HTMLDIR)/man7/$$fn"; \
 	done
 
 install_image_docs:
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(HTMLDIR)/man7/img
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(HTMLDIR)/man7/img"
 	@set -e; for x in dummy $(IMAGEDOCS7); do \
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "install $$x -> $(DESTDIR)$(HTMLDIR)/man7/img/$$fn"; \
-		cp $(SRCDIR)/$$x $(DESTDIR)$(HTMLDIR)/man7/img/$$fn; \
-		chmod 644 $(DESTDIR)$(HTMLDIR)/man7/img/$$fn; \
+		cp $(SRCDIR)/$$x "$(DESTDIR)$(HTMLDIR)/man7/img/$$fn"; \
+		chmod 644 "$(DESTDIR)$(HTMLDIR)/man7/img/$$fn"; \
 	done
 
 uninstall_image_docs:
@@ -1096,7 +1096,7 @@ uninstall_image_docs:
 		if [ "$$x" = "dummy" ]; then continue; fi; \
 		fn=`basename $$x`; \
 		$(ECHO) "$(RM) $(DESTDIR)$(HTMLDIR)/man7/img/$$fn"; \
-		$(RM) $(DESTDIR)$(HTMLDIR)/man7/img/$$fn; \
+		$(RM) "$(DESTDIR)$(HTMLDIR)/man7/img/$$fn"; \
 	done
 
 # Developer targets (note: these are only available on Unix) #########
diff --git a/deps/openssl/openssl/INSTALL.md b/deps/openssl/openssl/INSTALL.md
index fbcebe17e62c9a..87b1faef90f719 100644
--- a/deps/openssl/openssl/INSTALL.md
+++ b/deps/openssl/openssl/INSTALL.md
@@ -2,8 +2,8 @@ Build and Install
 =================
 
 This document describes installation on all supported operating
-systems (the Unix/Linux family, including macOS), OpenVMS,
-and Windows).
+systems: the Unix/Linux family (including macOS), OpenVMS,
+and Windows.
 
 Table of Contents
 =================
diff --git a/deps/openssl/openssl/NEWS.md b/deps/openssl/openssl/NEWS.md
index feed9026976013..8f0d973e057bb8 100644
--- a/deps/openssl/openssl/NEWS.md
+++ b/deps/openssl/openssl/NEWS.md
@@ -18,6 +18,16 @@ OpenSSL Releases
 OpenSSL 3.0
 -----------
 
+### Major changes between OpenSSL 3.0.11 and OpenSSL 3.0.12 [24 Oct 2023]
+
+  * Mitigate incorrect resize handling for symmetric cipher keys and IVs.
+    ([CVE-2023-5363])
+
+### Major changes between OpenSSL 3.0.10 and OpenSSL 3.0.11 [19 Sep 2023]
+
+  * Fix POLY1305 MAC implementation corrupting XMM registers on Windows
+    ([CVE-2023-4807])
+
 ### Major changes between OpenSSL 3.0.9 and OpenSSL 3.0.10 [1 Aug 2023]
 
   * Fix excessive time spent checking DH q parameter value ([CVE-2023-3817])
@@ -1448,6 +1458,8 @@ OpenSSL 0.9.x
 
 
 
+[CVE-2023-5363]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-5363
+[CVE-2023-4807]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-4807
 [CVE-2023-3817]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-3817
 [CVE-2023-3446]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-3446
 [CVE-2023-2975]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-2975
diff --git a/deps/openssl/openssl/README-OpenSSL.md b/deps/openssl/openssl/README-OpenSSL.md
index f2f4fd39ad05bb..b848d050132aae 100644
--- a/deps/openssl/openssl/README-OpenSSL.md
+++ b/deps/openssl/openssl/README-OpenSSL.md
@@ -166,7 +166,7 @@ attempting to develop or distribute cryptographic code.
 Copyright
 =========
 
-Copyright (c) 1998-2022 The OpenSSL Project
+Copyright (c) 1998-2023 The OpenSSL Project
 
 Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson
 
diff --git a/deps/openssl/openssl/README.md b/deps/openssl/openssl/README.md
index 80090a262c0502..e73b04b378e322 100644
--- a/deps/openssl/openssl/README.md
+++ b/deps/openssl/openssl/README.md
@@ -4,7 +4,7 @@ What This Is
 This is a fork of [OpenSSL](https://www.openssl.org) to enable QUIC. In addition
 to the website, the official source distribution is at
 . The OpenSSL `README` can be found at
-[README-OpenSSL.md](https://github.com/quictls/openssl/blob/openssl-3.0.10%2Bquic/README-OpenSSL.md)
+[README-OpenSSL.md](https://github.com/quictls/openssl/blob/openssl-3.0.12%2Bquic/README-OpenSSL.md)
 
 This fork adds APIs that can be used by QUIC implementations for connection
 handshakes. Quoting the IETF Working group
diff --git a/deps/openssl/openssl/VERSION.dat b/deps/openssl/openssl/VERSION.dat
index 3388a2ac907c8f..d416c3662e5dd1 100644
--- a/deps/openssl/openssl/VERSION.dat
+++ b/deps/openssl/openssl/VERSION.dat
@@ -1,7 +1,7 @@
 MAJOR=3
 MINOR=0
-PATCH=10
+PATCH=12
 PRE_RELEASE_TAG=
 BUILD_METADATA=quic
-RELEASE_DATE="1 Aug 2023"
+RELEASE_DATE="24 Oct 2023"
 SHLIB_VERSION=81.3
diff --git a/deps/openssl/openssl/apps/cmp.c b/deps/openssl/openssl/apps/cmp.c
index a317fdb0bf3ed4..c479b15496607f 100644
--- a/deps/openssl/openssl/apps/cmp.c
+++ b/deps/openssl/openssl/apps/cmp.c
@@ -2512,7 +2512,7 @@ static int get_opts(int argc, char **argv)
             }
             break;
         case OPT_CSR:
-            opt_csr = opt_arg();
+            opt_csr = opt_str();
             break;
         case OPT_OUT_TRUSTED:
             opt_out_trusted = opt_str();
diff --git a/deps/openssl/openssl/apps/dgst.c b/deps/openssl/openssl/apps/dgst.c
index e12389197de4a6..3f02af0d5738ab 100644
--- a/deps/openssl/openssl/apps/dgst.c
+++ b/deps/openssl/openssl/apps/dgst.c
@@ -320,6 +320,8 @@ int dgst_main(int argc, char **argv)
         sigkey = app_keygen(mac_ctx, mac_name, 0, 0 /* not verbose */);
         /* Verbose output would make external-tests gost-engine fail */
         EVP_PKEY_CTX_free(mac_ctx);
+        if (sigkey == NULL)
+            goto end;
     }
 
     if (hmac_key != NULL) {
diff --git a/deps/openssl/openssl/apps/dhparam.c b/deps/openssl/openssl/apps/dhparam.c
index 43906cea56497b..2a54dca9d8b552 100644
--- a/deps/openssl/openssl/apps/dhparam.c
+++ b/deps/openssl/openssl/apps/dhparam.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -222,6 +222,8 @@ int dhparam_main(int argc, char **argv)
         }
 
         tmppkey = app_paramgen(ctx, alg);
+        if (tmppkey == NULL)
+            goto end;
         EVP_PKEY_CTX_free(ctx);
         ctx = NULL;
         if (dsaparam) {
diff --git a/deps/openssl/openssl/apps/dsaparam.c b/deps/openssl/openssl/apps/dsaparam.c
index b5555282be6e18..ca91beb5b893bb 100644
--- a/deps/openssl/openssl/apps/dsaparam.c
+++ b/deps/openssl/openssl/apps/dsaparam.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -218,6 +218,8 @@ int dsaparam_main(int argc, char **argv)
             goto end;
         }
         pkey = app_keygen(ctx, "DSA", numbits, verbose);
+        if (pkey == NULL)
+            goto end;
         assert(private);
         if (outformat == FORMAT_ASN1)
             i = i2d_PrivateKey_bio(out, pkey);
diff --git a/deps/openssl/openssl/apps/enc.c b/deps/openssl/openssl/apps/enc.c
index b3bf4cc2592d01..c275046cf57a64 100644
--- a/deps/openssl/openssl/apps/enc.c
+++ b/deps/openssl/openssl/apps/enc.c
@@ -624,7 +624,10 @@ int enc_main(int argc, char **argv)
         }
     }
     if (!BIO_flush(wbio)) {
-        BIO_printf(bio_err, "bad decrypt\n");
+        if (enc)
+            BIO_printf(bio_err, "bad encrypt\n");
+        else
+            BIO_printf(bio_err, "bad decrypt\n");
         goto end;
     }
 
diff --git a/deps/openssl/openssl/apps/gendsa.c b/deps/openssl/openssl/apps/gendsa.c
index 27feb793fed23c..8aefca65566c59 100644
--- a/deps/openssl/openssl/apps/gendsa.c
+++ b/deps/openssl/openssl/apps/gendsa.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -146,6 +146,8 @@ int gendsa_main(int argc, char **argv)
         goto end;
     }
     pkey = app_keygen(ctx, "DSA", nbits, verbose);
+    if (pkey == NULL)
+        goto end;
 
     assert(private);
     if (!PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, passout)) {
diff --git a/deps/openssl/openssl/apps/genpkey.c b/deps/openssl/openssl/apps/genpkey.c
index d00754eeaca09f..705e5c76b47dc0 100644
--- a/deps/openssl/openssl/apps/genpkey.c
+++ b/deps/openssl/openssl/apps/genpkey.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -183,6 +183,8 @@ int genpkey_main(int argc, char **argv)
 
     pkey = do_param ? app_paramgen(ctx, algname)
                     : app_keygen(ctx, algname, 0, 0 /* not verbose */);
+    if (pkey == NULL)
+        goto end;
 
     if (do_param) {
         rv = PEM_write_bio_Parameters(out, pkey);
diff --git a/deps/openssl/openssl/apps/genrsa.c b/deps/openssl/openssl/apps/genrsa.c
index 4436b7fa1745a9..6a683517a15fc7 100644
--- a/deps/openssl/openssl/apps/genrsa.c
+++ b/deps/openssl/openssl/apps/genrsa.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -203,6 +203,8 @@ int genrsa_main(int argc, char **argv)
         goto end;
     }
     pkey = app_keygen(ctx, "RSA", num, verbose);
+    if (pkey == NULL)
+        goto end;
 
     if (verbose) {
         BIGNUM *e = NULL;
diff --git a/deps/openssl/openssl/apps/lib/apps.c b/deps/openssl/openssl/apps/lib/apps.c
index 4baeb352fedfb3..a632b0cff2bf68 100644
--- a/deps/openssl/openssl/apps/lib/apps.c
+++ b/deps/openssl/openssl/apps/lib/apps.c
@@ -944,7 +944,7 @@ int load_key_certs_crls_suppress(const char *uri, int format, int maybe_stdin,
         BIO *bio;
 
         if (!maybe_stdin) {
-            BIO_printf(bio_err, "No filename or uri specified for loading");
+            BIO_printf(bio_err, "No filename or uri specified for loading\n");
             goto end;
         }
         uri = "";
@@ -964,8 +964,10 @@ int load_key_certs_crls_suppress(const char *uri, int format, int maybe_stdin,
         BIO_printf(bio_err, "Could not open file or uri for loading");
         goto end;
     }
-    if (expect > 0 && !OSSL_STORE_expect(ctx, expect))
+    if (expect > 0 && !OSSL_STORE_expect(ctx, expect)) {
+        BIO_printf(bio_err, "Internal error trying to load");
         goto end;
+    }
 
     failed = NULL;
     while (cnt_expectations > 0 && !OSSL_STORE_eof(ctx)) {
@@ -1948,16 +1950,17 @@ X509_NAME *parse_name(const char *cp, int chtype, int canmulti,
         nid = OBJ_txt2nid(typestr);
         if (nid == NID_undef) {
             BIO_printf(bio_err,
-                       "%s: Skipping unknown %s name attribute \"%s\"\n",
+                       "%s warning: Skipping unknown %s name attribute \"%s\"\n",
                        opt_getprog(), desc, typestr);
             if (ismulti)
                 BIO_printf(bio_err,
-                           "Hint: a '+' in a value string needs be escaped using '\\' else a new member of a multi-valued RDN is expected\n");
+                           "%s hint: a '+' in a value string needs be escaped using '\\' else a new member of a multi-valued RDN is expected\n",
+                           opt_getprog());
             continue;
         }
         if (*valstr == '\0') {
             BIO_printf(bio_err,
-                       "%s: No value provided for %s name attribute \"%s\", skipped\n",
+                       "%s warning: No value provided for %s name attribute \"%s\", skipped\n",
                        opt_getprog(), desc, typestr);
             continue;
         }
@@ -3360,8 +3363,8 @@ EVP_PKEY *app_keygen(EVP_PKEY_CTX *ctx, const char *alg, int bits, int verbose)
         BIO_printf(bio_err, "Warning: generating random key material may take a long time\n"
                    "if the system has a poor entropy source\n");
     if (EVP_PKEY_keygen(ctx, &res) <= 0)
-        app_bail_out("%s: Error generating %s key\n", opt_getprog(),
-                     alg != NULL ? alg : "asymmetric");
+        BIO_printf(bio_err, "%s: Error generating %s key\n", opt_getprog(),
+                   alg != NULL ? alg : "asymmetric");
     return res;
 }
 
@@ -3373,8 +3376,8 @@ EVP_PKEY *app_paramgen(EVP_PKEY_CTX *ctx, const char *alg)
         BIO_printf(bio_err, "Warning: generating random key parameters may take a long time\n"
                    "if the system has a poor entropy source\n");
     if (EVP_PKEY_paramgen(ctx, &res) <= 0)
-        app_bail_out("%s: Generating %s key parameters failed\n",
-                     opt_getprog(), alg != NULL ? alg : "asymmetric");
+        BIO_printf(bio_err, "%s: Generating %s key parameters failed\n",
+                   opt_getprog(), alg != NULL ? alg : "asymmetric");
     return res;
 }
 
diff --git a/deps/openssl/openssl/apps/req.c b/deps/openssl/openssl/apps/req.c
index 73b320a7098cf0..41191803aef417 100644
--- a/deps/openssl/openssl/apps/req.c
+++ b/deps/openssl/openssl/apps/req.c
@@ -685,6 +685,8 @@ int req_main(int argc, char **argv)
         EVP_PKEY_CTX_set_app_data(genctx, bio_err);
 
         pkey = app_keygen(genctx, keyalgstr, newkey_len, verbose);
+        if (pkey == NULL)
+            goto end;
 
         EVP_PKEY_CTX_free(genctx);
         genctx = NULL;
@@ -990,10 +992,10 @@ int req_main(int argc, char **argv)
         else
             tpubkey = X509_REQ_get0_pubkey(req);
         if (tpubkey == NULL) {
-            fprintf(stdout, "Modulus is unavailable\n");
+            BIO_puts(bio_err, "Modulus is unavailable\n");
             goto end;
         }
-        fprintf(stdout, "Modulus=");
+        BIO_puts(out, "Modulus=");
         if (EVP_PKEY_is_a(tpubkey, "RSA") || EVP_PKEY_is_a(tpubkey, "RSA-PSS")) {
             BIGNUM *n = NULL;
 
@@ -1002,9 +1004,9 @@ int req_main(int argc, char **argv)
             BN_print(out, n);
             BN_free(n);
         } else {
-            fprintf(stdout, "Wrong Algorithm type");
+            BIO_puts(out, "Wrong Algorithm type");
         }
-        fprintf(stdout, "\n");
+        BIO_puts(out, "\n");
     }
 
     if (!noout && !gen_x509) {
diff --git a/deps/openssl/openssl/apps/s_server.c b/deps/openssl/openssl/apps/s_server.c
index a203d6a091cac3..c8ccdfd03ca196 100644
--- a/deps/openssl/openssl/apps/s_server.c
+++ b/deps/openssl/openssl/apps/s_server.c
@@ -789,7 +789,7 @@ const OPTIONS s_server_options[] = {
      "second server certificate chain file in PEM format"},
     {"dkey", OPT_DKEY, '<',
      "Second private key file to use (usually for DSA)"},
-    {"dkeyform", OPT_DKEYFORM, 'F',
+    {"dkeyform", OPT_DKEYFORM, 'f',
      "Second key file format (ENGINE, other values ignored)"},
     {"dpass", OPT_DPASS, 's',
      "Second private key and cert file pass phrase source"},
diff --git a/deps/openssl/openssl/apps/speed.c b/deps/openssl/openssl/apps/speed.c
index f30435704d19ce..1113d775b8ab98 100644
--- a/deps/openssl/openssl/apps/speed.c
+++ b/deps/openssl/openssl/apps/speed.c
@@ -3700,7 +3700,8 @@ static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single,
             } else {
                 int pad;
 
-                RAND_bytes(out, 16);
+                if (RAND_bytes(inp, 16) <= 0)
+                    app_bail_out("error setting random bytes\n");
                 len += 16;
                 aad[11] = (unsigned char)(len >> 8);
                 aad[12] = (unsigned char)(len);
diff --git a/deps/openssl/openssl/appveyor.yml b/deps/openssl/openssl/appveyor.yml
deleted file mode 100644
index 9bb6f04e0a44cb..00000000000000
--- a/deps/openssl/openssl/appveyor.yml
+++ /dev/null
@@ -1,82 +0,0 @@
-image:
-    - Visual Studio 2017
-
-platform:
-    - x64
-    - x86
-
-environment:
-    fast_finish: true
-    matrix:
-        - VSVER: 15
-
-configuration:
-    - shared
-    - minimal
-
-for:
-    -
-        branches:
-            only:
-                - master
-        configuration:
-            - shared
-            - plain
-            - minimal
-
-before_build:
-    - ps: >-
-        Install-Module VSSetup -Scope CurrentUser
-    - ps: >-
-        Get-VSSetupInstance -All
-    - ps: >-
-        If ($env:Platform -Match "x86") {
-            $env:VCVARS_PLATFORM="x86"
-            $env:TARGET="VC-WIN32 no-asm --strict-warnings"
-        } Else {
-            $env:VCVARS_PLATFORM="amd64"
-            $env:TARGET="VC-WIN64A-masm"
-        }
-    - ps: >-
-        If ($env:Configuration -Match "shared") {
-            $env:CONFIG_OPTS="enable-fips"
-        } ElseIf ($env:Configuration -Match "minimal") {
-            $env:CONFIG_OPTS="no-bulk no-asm -DOPENSSL_SMALL_FOOTPRINT"
-        } Else {
-            $env:CONFIG_OPTS="no-fips no-shared"
-        }
-    - call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" %VCVARS_PLATFORM%
-    - mkdir _build
-    - cd _build
-    - perl ..\Configure %TARGET% no-makedepend %CONFIG_OPTS%
-    - perl configdata.pm --dump
-    - cd ..
-    - ps: >-
-        If ($env:BUILDONLY -or $env:MAKEVERBOSE) {
-            $env:NMAKE="nmake"
-        } Else {
-            $env:NMAKE="nmake /S"
-        }
-    - ps: >-
-        gci env:* | sort-object name
-
-build_script:
-    - cd _build
-    - "%NMAKE% build_all_generated"
-    - "%NMAKE% PERL=no-perl"
-    - cd ..
-
-test_script:
-    - cd _build
-    - ps: >-
-        if ($env:Configuration -Match "plain") {
-            cmd /c "%NMAKE% test VERBOSE_FAILURE=yes 2>&1"
-        } Else {
-            cmd /c "%NMAKE% test VERBOSE_FAILURE=yes TESTS=-test_fuzz 2>&1"
-        }
-    - ps: >-
-        if ($env:Configuration -Match "shared") {
-            mkdir ..\_install
-            cmd /c "%NMAKE% install DESTDIR=..\_install 2>&1"
-        }
-    - cd ..
diff --git a/deps/openssl/openssl/crypto/aes/asm/aesv8-armx.pl b/deps/openssl/openssl/crypto/aes/asm/aesv8-armx.pl
index 544dc7e8effe66..d0e0be6187bd2e 100755
--- a/deps/openssl/openssl/crypto/aes/asm/aesv8-armx.pl
+++ b/deps/openssl/openssl/crypto/aes/asm/aesv8-armx.pl
@@ -3661,6 +3661,9 @@ ()
 	s/\.[ui]?64//o and s/\.16b/\.2d/go;
 	s/\.[42]([sd])\[([0-3])\]/\.$1\[$2\]/o;
 
+	# Switch preprocessor checks to aarch64 versions.
+	s/__ARME([BL])__/__AARCH64E$1__/go;
+
 	print $_,"\n";
     }
 } else {				######## 32-bit code
diff --git a/deps/openssl/openssl/crypto/arm_arch.h b/deps/openssl/openssl/crypto/arm_arch.h
index 45d7e155647540..ec4a087fede2fc 100644
--- a/deps/openssl/openssl/crypto/arm_arch.h
+++ b/deps/openssl/openssl/crypto/arm_arch.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -21,11 +21,6 @@
 #  elif defined(__GNUC__)
 #   if   defined(__aarch64__)
 #    define __ARM_ARCH__ 8
-#    if __BYTE_ORDER__==__ORDER_BIG_ENDIAN__
-#     define __ARMEB__
-#    else
-#     define __ARMEL__
-#    endif
   /*
    * Why doesn't gcc define __ARM_ARCH__? Instead it defines
    * bunch of below macros. See all_architectures[] table in
diff --git a/deps/openssl/openssl/crypto/asn1/a_strnid.c b/deps/openssl/openssl/crypto/asn1/a_strnid.c
index 9e54db929282c5..d052935661d362 100644
--- a/deps/openssl/openssl/crypto/asn1/a_strnid.c
+++ b/deps/openssl/openssl/crypto/asn1/a_strnid.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -129,8 +129,10 @@ ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid)
     int idx;
     ASN1_STRING_TABLE fnd;
 
+#ifndef OPENSSL_NO_AUTOLOAD_CONFIG
     /* "stable" can be impacted by config, so load the config file first */
     OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
+#endif
 
     fnd.nid = nid;
     if (stable) {
diff --git a/deps/openssl/openssl/crypto/asn1/asn1_gen.c b/deps/openssl/openssl/crypto/asn1/asn1_gen.c
index 64620a4f28a7f6..402ab34e6a46f7 100644
--- a/deps/openssl/openssl/crypto/asn1/asn1_gen.c
+++ b/deps/openssl/openssl/crypto/asn1/asn1_gen.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -698,9 +698,12 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
             atmp->value.asn1_string->data = rdata;
             atmp->value.asn1_string->length = rdlen;
             atmp->value.asn1_string->type = utype;
-        } else if (format == ASN1_GEN_FORMAT_ASCII)
-            ASN1_STRING_set(atmp->value.asn1_string, str, -1);
-        else if ((format == ASN1_GEN_FORMAT_BITLIST)
+        } else if (format == ASN1_GEN_FORMAT_ASCII) {
+            if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) {
+                ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
+                goto bad_str;
+            }
+        } else if ((format == ASN1_GEN_FORMAT_BITLIST)
                  && (utype == V_ASN1_BIT_STRING)) {
             if (!CONF_parse_list
                 (str, ',', 1, bitstr_cb, atmp->value.bit_string)) {
diff --git a/deps/openssl/openssl/crypto/bn/bn_gcd.c b/deps/openssl/openssl/crypto/bn/bn_gcd.c
index 59d024f674ebd5..cd0b0151ec7ed6 100644
--- a/deps/openssl/openssl/crypto/bn/bn_gcd.c
+++ b/deps/openssl/openssl/crypto/bn/bn_gcd.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -611,9 +611,9 @@ int BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx)
 
     for (i = 0; i < m; i++) {
         /* conditionally flip signs if delta is positive and g is odd */
-        cond = (-delta >> (8 * sizeof(delta) - 1)) & g->d[0] & 1
+        cond = ((unsigned int)-delta >> (8 * sizeof(delta) - 1)) & g->d[0] & 1
             /* make sure g->top > 0 (i.e. if top == 0 then g == 0 always) */
-            & (~((g->top - 1) >> (sizeof(g->top) * 8 - 1)));
+            & (~((unsigned int)(g->top - 1) >> (sizeof(g->top) * 8 - 1)));
         delta = (-cond & -delta) | ((cond - 1) & delta);
         r->neg ^= cond;
         /* swap */
@@ -625,7 +625,7 @@ int BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx)
             goto err;
         BN_consttime_swap(g->d[0] & 1 /* g is odd */
                 /* make sure g->top > 0 (i.e. if top == 0 then g == 0 always) */
-                & (~((g->top - 1) >> (sizeof(g->top) * 8 - 1))),
+                & (~((unsigned int)(g->top - 1) >> (sizeof(g->top) * 8 - 1))),
                 g, temp, top);
         if (!BN_rshift1(g, g))
             goto err;
diff --git a/deps/openssl/openssl/crypto/build.info b/deps/openssl/openssl/crypto/build.info
index b90390ae864c40..c04db5591120df 100644
--- a/deps/openssl/openssl/crypto/build.info
+++ b/deps/openssl/openssl/crypto/build.info
@@ -97,8 +97,6 @@ $UTIL_COMMON=\
         context.c sparse_array.c asn1_dsa.c packet.c param_build.c \
         param_build_set.c der_writer.c threads_lib.c params_dup.c
 
-SHARED_SOURCE[../libssl]=sparse_array.c
-
 SOURCE[../libcrypto]=$UTIL_COMMON \
         mem.c mem_sec.c \
         cversion.c info.c cpt_err.c ebcdic.c uid.c o_time.c o_dir.c \
diff --git a/deps/openssl/openssl/crypto/chacha/asm/chacha-ia64.pl b/deps/openssl/openssl/crypto/chacha/asm/chacha-ia64.pl
index b13d972855754d..78201649d55029 100644
--- a/deps/openssl/openssl/crypto/chacha/asm/chacha-ia64.pl
+++ b/deps/openssl/openssl/crypto/chacha/asm/chacha-ia64.pl
@@ -46,6 +46,8 @@
 	ADDP		@k[11]=4,$key
 	.save		ar.lc,r3
 	mov		r3=ar.lc		}
+{ .mmi;	ADDP		$out=0,$out
+	ADDP		$inp=0,$inp		}
 { .mmi;	ADDP		$key=0,$key
 	ADDP		$counter=0,$counter
 	.save		pr,r14
diff --git a/deps/openssl/openssl/crypto/cmp/cmp_asn.c b/deps/openssl/openssl/crypto/cmp/cmp_asn.c
index 0ca107554c96dd..a8de73ad979b67 100644
--- a/deps/openssl/openssl/crypto/cmp/cmp_asn.c
+++ b/deps/openssl/openssl/crypto/cmp/cmp_asn.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright Nokia 2007-2019
  * Copyright Siemens AG 2015-2019
  *
@@ -188,22 +188,22 @@ int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **itav_sk_p,
     return 0;
 }
 
-/* get ASN.1 encoded integer, return -1 on error */
+/* get ASN.1 encoded integer, return -2 on error; -1 is valid for certReqId */
 int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a)
 {
     int64_t res;
 
     if (!ASN1_INTEGER_get_int64(&res, a)) {
         ERR_raise(ERR_LIB_CMP, ASN1_R_INVALID_NUMBER);
-        return -1;
+        return -2;
     }
     if (res < INT_MIN) {
         ERR_raise(ERR_LIB_CMP, ASN1_R_TOO_SMALL);
-        return -1;
+        return -2;
     }
     if (res > INT_MAX) {
         ERR_raise(ERR_LIB_CMP, ASN1_R_TOO_LARGE);
-        return -1;
+        return -2;
     }
     return (int)res;
 }
diff --git a/deps/openssl/openssl/crypto/cmp/cmp_client.c b/deps/openssl/openssl/crypto/cmp/cmp_client.c
index dc41f4c3b7d9e2..df334cc0019822 100644
--- a/deps/openssl/openssl/crypto/cmp/cmp_client.c
+++ b/deps/openssl/openssl/crypto/cmp/cmp_client.c
@@ -584,7 +584,7 @@ static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
         return 0;
     if (rid == OSSL_CMP_CERTREQID_NONE) { /* used for OSSL_CMP_PKIBODY_P10CR */
         rid = ossl_cmp_asn1_get_int(crep->certReqId);
-        if (rid != OSSL_CMP_CERTREQID_NONE) {
+        if (rid < OSSL_CMP_CERTREQID_NONE) {
             ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
             return 0;
         }
diff --git a/deps/openssl/openssl/crypto/cmp/cmp_status.c b/deps/openssl/openssl/crypto/cmp/cmp_status.c
index bfe6cd9906b82a..68144aa4fed878 100644
--- a/deps/openssl/openssl/crypto/cmp/cmp_status.c
+++ b/deps/openssl/openssl/crypto/cmp/cmp_status.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright Nokia 2007-2019
  * Copyright Siemens AG 2015-2019
  *
@@ -30,9 +30,12 @@
 
 int ossl_cmp_pkisi_get_status(const OSSL_CMP_PKISI *si)
 {
+    int res ;
+
     if (!ossl_assert(si != NULL && si->status != NULL))
         return -1;
-    return ossl_cmp_asn1_get_int(si->status);
+    res = ossl_cmp_asn1_get_int(si->status);
+    return res == -2 ? -1 : res;
 }
 
 const char *ossl_cmp_PKIStatus_to_string(int status)
diff --git a/deps/openssl/openssl/crypto/cms/cms_enc.c b/deps/openssl/openssl/crypto/cms/cms_enc.c
index f7007c12319e66..ae88df33a7f0bf 100644
--- a/deps/openssl/openssl/crypto/cms/cms_enc.c
+++ b/deps/openssl/openssl/crypto/cms/cms_enc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include "crypto/evp.h"
+#include "crypto/asn1.h"
 #include "cms_local.h"
 
 /* CMS EncryptedData Utilities */
@@ -81,7 +82,7 @@ BIO *ossl_cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec,
 
     if (enc) {
         calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_get_type(ctx));
-        if (calg->algorithm == NULL) {
+        if (calg->algorithm == NULL || calg->algorithm->nid == NID_undef) {
             ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM);
             goto err;
         }
diff --git a/deps/openssl/openssl/crypto/cms/cms_env.c b/deps/openssl/openssl/crypto/cms/cms_env.c
index bd1f3e7345d400..99cf1dcb396ca5 100644
--- a/deps/openssl/openssl/crypto/cms/cms_env.c
+++ b/deps/openssl/openssl/crypto/cms/cms_env.c
@@ -26,7 +26,7 @@ static void cms_env_set_version(CMS_EnvelopedData *env);
 #define CMS_ENVELOPED_STANDARD 1
 #define CMS_ENVELOPED_AUTH     2
 
-static int cms_get_enveloped_type(const CMS_ContentInfo *cms)
+static int cms_get_enveloped_type_simple(const CMS_ContentInfo *cms)
 {
     int nid = OBJ_obj2nid(cms->contentType);
 
@@ -38,11 +38,28 @@ static int cms_get_enveloped_type(const CMS_ContentInfo *cms)
         return CMS_ENVELOPED_AUTH;
 
     default:
-        ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA);
         return 0;
     }
 }
 
+static int cms_get_enveloped_type(const CMS_ContentInfo *cms)
+{
+    int ret = cms_get_enveloped_type_simple(cms);
+
+    if (ret == 0)
+        ERR_raise(ERR_LIB_CMS, CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA);
+    return ret;
+}
+
+void ossl_cms_env_enc_content_free(const CMS_ContentInfo *cinf)
+{
+    if (cms_get_enveloped_type_simple(cinf) != 0) {
+        CMS_EncryptedContentInfo *ec = ossl_cms_get0_env_enc_content(cinf);
+        if (ec != NULL)
+            OPENSSL_clear_free(ec->key, ec->keylen);
+    }
+}
+
 CMS_EnvelopedData *ossl_cms_get0_enveloped(CMS_ContentInfo *cms)
 {
     if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped) {
diff --git a/deps/openssl/openssl/crypto/cms/cms_err.c b/deps/openssl/openssl/crypto/cms/cms_err.c
index dcbea201c8e5f4..4bd6a0dc1bf101 100644
--- a/deps/openssl/openssl/crypto/cms/cms_err.c
+++ b/deps/openssl/openssl/crypto/cms/cms_err.c
@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -154,6 +154,8 @@ static const ERR_STRING_DATA CMS_str_reasons[] = {
     "unsupported recipientinfo type"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_RECIPIENT_TYPE),
     "unsupported recipient type"},
+    {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_SIGNATURE_ALGORITHM),
+    "unsupported signature algorithm"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_TYPE), "unsupported type"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNWRAP_ERROR), "unwrap error"},
     {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNWRAP_FAILURE), "unwrap failure"},
diff --git a/deps/openssl/openssl/crypto/cms/cms_lib.c b/deps/openssl/openssl/crypto/cms/cms_lib.c
index 1d2c5bc42288a0..8b135e95aacc81 100644
--- a/deps/openssl/openssl/crypto/cms/cms_lib.c
+++ b/deps/openssl/openssl/crypto/cms/cms_lib.c
@@ -76,10 +76,7 @@ CMS_ContentInfo *CMS_ContentInfo_new(void)
 void CMS_ContentInfo_free(CMS_ContentInfo *cms)
 {
     if (cms != NULL) {
-        CMS_EncryptedContentInfo *ec = ossl_cms_get0_env_enc_content(cms);
-
-        if (ec != NULL)
-            OPENSSL_clear_free(ec->key, ec->keylen);
+        ossl_cms_env_enc_content_free(cms);
         OPENSSL_free(cms->ctx.propq);
         ASN1_item_free((ASN1_VALUE *)cms, ASN1_ITEM_rptr(CMS_ContentInfo));
     }
diff --git a/deps/openssl/openssl/crypto/cms/cms_local.h b/deps/openssl/openssl/crypto/cms/cms_local.h
index 15b4a29ce03dce..253f6819e43542 100644
--- a/deps/openssl/openssl/crypto/cms/cms_local.h
+++ b/deps/openssl/openssl/crypto/cms/cms_local.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -444,6 +444,7 @@ BIO *ossl_cms_EnvelopedData_init_bio(CMS_ContentInfo *cms);
 int ossl_cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain);
 BIO *ossl_cms_AuthEnvelopedData_init_bio(CMS_ContentInfo *cms);
 int ossl_cms_AuthEnvelopedData_final(CMS_ContentInfo *cms, BIO *cmsbio);
+void ossl_cms_env_enc_content_free(const CMS_ContentInfo *cinf);
 CMS_EnvelopedData *ossl_cms_get0_enveloped(CMS_ContentInfo *cms);
 CMS_AuthEnvelopedData *ossl_cms_get0_auth_enveloped(CMS_ContentInfo *cms);
 CMS_EncryptedContentInfo *ossl_cms_get0_env_enc_content(const CMS_ContentInfo *cms);
diff --git a/deps/openssl/openssl/crypto/cms/cms_sd.c b/deps/openssl/openssl/crypto/cms/cms_sd.c
index 34c021bba64af7..2093657a2a4a69 100644
--- a/deps/openssl/openssl/crypto/cms/cms_sd.c
+++ b/deps/openssl/openssl/crypto/cms/cms_sd.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -233,9 +233,9 @@ static int cms_sd_asn1_ctrl(CMS_SignerInfo *si, int cmd)
     int i;
 
     if (EVP_PKEY_is_a(pkey, "DSA") || EVP_PKEY_is_a(pkey, "EC"))
-        return ossl_cms_ecdsa_dsa_sign(si, cmd);
+        return ossl_cms_ecdsa_dsa_sign(si, cmd) > 0;
     else if (EVP_PKEY_is_a(pkey, "RSA") || EVP_PKEY_is_a(pkey, "RSA-PSS"))
-        return ossl_cms_rsa_sign(si, cmd);
+        return ossl_cms_rsa_sign(si, cmd) > 0;
 
     /* Something else? We'll give engines etc a chance to handle this */
     if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL)
@@ -354,11 +354,16 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
 
     if (md == NULL) {
         int def_nid;
-        if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0)
+
+        if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0) {
+            ERR_raise_data(ERR_LIB_CMS, CMS_R_NO_DEFAULT_DIGEST,
+                           "pkey nid=%d", EVP_PKEY_get_id(pk));
             goto err;
+        }
         md = EVP_get_digestbynid(def_nid);
         if (md == NULL) {
-            ERR_raise(ERR_LIB_CMS, CMS_R_NO_DEFAULT_DIGEST);
+            ERR_raise_data(ERR_LIB_CMS, CMS_R_NO_DEFAULT_DIGEST,
+                           "default md nid=%d", def_nid);
             goto err;
         }
     }
@@ -398,8 +403,11 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
         }
     }
 
-    if (!(flags & CMS_KEY_PARAM) && !cms_sd_asn1_ctrl(si, 0))
+    if (!(flags & CMS_KEY_PARAM) && !cms_sd_asn1_ctrl(si, 0)) {
+        ERR_raise_data(ERR_LIB_CMS, CMS_R_UNSUPPORTED_SIGNATURE_ALGORITHM,
+                       "pkey nid=%d", EVP_PKEY_get_id(pk));
         goto err;
+    }
     if (!(flags & CMS_NOATTR)) {
         /*
          * Initialize signed attributes structure so other attributes
diff --git a/deps/openssl/openssl/crypto/conf/conf_sap.c b/deps/openssl/openssl/crypto/conf/conf_sap.c
index 513f8bfc1fb94c..3019bcf31af81a 100644
--- a/deps/openssl/openssl/crypto/conf/conf_sap.c
+++ b/deps/openssl/openssl/crypto/conf/conf_sap.c
@@ -65,7 +65,8 @@ int ossl_config_int(const OPENSSL_INIT_SETTINGS *settings)
 #endif
 
 #ifndef OPENSSL_SYS_UEFI
-    ret = CONF_modules_load_file(filename, appname, flags);
+    ret = CONF_modules_load_file_ex(OSSL_LIB_CTX_get0_global_default(),
+                                    filename, appname, flags);
 #else
     ret = 1;
 #endif
diff --git a/deps/openssl/openssl/crypto/dh/dh_check.c b/deps/openssl/openssl/crypto/dh/dh_check.c
index f4173e21371e01..7ba2beae7fd6b9 100644
--- a/deps/openssl/openssl/crypto/dh/dh_check.c
+++ b/deps/openssl/openssl/crypto/dh/dh_check.c
@@ -259,7 +259,8 @@ int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret)
  */
 int ossl_dh_check_pub_key_partial(const DH *dh, const BIGNUM *pub_key, int *ret)
 {
-    return ossl_ffc_validate_public_key_partial(&dh->params, pub_key, ret);
+    return ossl_ffc_validate_public_key_partial(&dh->params, pub_key, ret)
+           && *ret == 0;
 }
 
 int ossl_dh_check_priv_key(const DH *dh, const BIGNUM *priv_key, int *ret)
diff --git a/deps/openssl/openssl/crypto/dh/dh_key.c b/deps/openssl/openssl/crypto/dh/dh_key.c
index 4e9705beef733b..d84ea99241b9e8 100644
--- a/deps/openssl/openssl/crypto/dh/dh_key.c
+++ b/deps/openssl/openssl/crypto/dh/dh_key.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -190,7 +190,6 @@ static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
 static int dh_init(DH *dh)
 {
     dh->flags |= DH_FLAG_CACHE_MONT_P;
-    ossl_ffc_params_init(&dh->params);
     dh->dirty_cnt++;
     return 1;
 }
diff --git a/deps/openssl/openssl/crypto/dh/dh_lib.c b/deps/openssl/openssl/crypto/dh/dh_lib.c
index 29cda5d7bfa845..5577413e1e0c07 100644
--- a/deps/openssl/openssl/crypto/dh/dh_lib.c
+++ b/deps/openssl/openssl/crypto/dh/dh_lib.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -116,6 +116,8 @@ static DH *dh_new_intern(ENGINE *engine, OSSL_LIB_CTX *libctx)
         goto err;
 #endif /* FIPS_MODULE */
 
+    ossl_ffc_params_init(&ret->params);
+
     if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
         ERR_raise(ERR_LIB_DH, ERR_R_INIT_FAIL);
         goto err;
diff --git a/deps/openssl/openssl/crypto/dsa/dsa_check.c b/deps/openssl/openssl/crypto/dsa/dsa_check.c
index 7ee914a477ecea..fb0e9129a2956b 100644
--- a/deps/openssl/openssl/crypto/dsa/dsa_check.c
+++ b/deps/openssl/openssl/crypto/dsa/dsa_check.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -39,7 +39,8 @@ int ossl_dsa_check_params(const DSA *dsa, int checktype, int *ret)
  */
 int ossl_dsa_check_pub_key(const DSA *dsa, const BIGNUM *pub_key, int *ret)
 {
-    return ossl_ffc_validate_public_key(&dsa->params, pub_key, ret);
+    return ossl_ffc_validate_public_key(&dsa->params, pub_key, ret)
+           && *ret == 0;
 }
 
 /*
@@ -49,7 +50,8 @@ int ossl_dsa_check_pub_key(const DSA *dsa, const BIGNUM *pub_key, int *ret)
  */
 int ossl_dsa_check_pub_key_partial(const DSA *dsa, const BIGNUM *pub_key, int *ret)
 {
-    return ossl_ffc_validate_public_key_partial(&dsa->params, pub_key, ret);
+    return ossl_ffc_validate_public_key_partial(&dsa->params, pub_key, ret)
+           && *ret == 0;
 }
 
 int ossl_dsa_check_priv_key(const DSA *dsa, const BIGNUM *priv_key, int *ret)
diff --git a/deps/openssl/openssl/crypto/dsa/dsa_lib.c b/deps/openssl/openssl/crypto/dsa/dsa_lib.c
index ccc70165921764..2ae3f8e36b265f 100644
--- a/deps/openssl/openssl/crypto/dsa/dsa_lib.c
+++ b/deps/openssl/openssl/crypto/dsa/dsa_lib.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -176,6 +176,8 @@ static DSA *dsa_new_intern(ENGINE *engine, OSSL_LIB_CTX *libctx)
         goto err;
 #endif
 
+    ossl_ffc_params_init(&ret->params);
+
     if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
         ERR_raise(ERR_LIB_DSA, ERR_R_INIT_FAIL);
         goto err;
diff --git a/deps/openssl/openssl/crypto/dsa/dsa_ossl.c b/deps/openssl/openssl/crypto/dsa/dsa_ossl.c
index 62f7c70149f4fb..8fd66a950e3739 100644
--- a/deps/openssl/openssl/crypto/dsa/dsa_ossl.c
+++ b/deps/openssl/openssl/crypto/dsa/dsa_ossl.c
@@ -441,7 +441,6 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len,
 static int dsa_init(DSA *dsa)
 {
     dsa->flags |= DSA_FLAG_CACHE_MONT_P;
-    ossl_ffc_params_init(&dsa->params);
     dsa->dirty_cnt++;
     return 1;
 }
diff --git a/deps/openssl/openssl/crypto/encode_decode/decoder_lib.c b/deps/openssl/openssl/crypto/encode_decode/decoder_lib.c
index e24d2c6cd588be..2e4b7ed60b9c1c 100644
--- a/deps/openssl/openssl/crypto/encode_decode/decoder_lib.c
+++ b/deps/openssl/openssl/crypto/encode_decode/decoder_lib.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -743,10 +743,11 @@ static int decoder_process(const OSSL_PARAM params[], void *arg)
                            (void *)new_data.ctx, LEVEL, rv);
             } OSSL_TRACE_END(DECODER);
 
-            data->flag_construct_called = 1;
             ok = (rv > 0);
-            if (ok)
+            if (ok) {
+                data->flag_construct_called = 1;
                 goto end;
+            }
         }
 
         /* The constructor didn't return success */
diff --git a/deps/openssl/openssl/crypto/encode_decode/decoder_pkey.c b/deps/openssl/openssl/crypto/encode_decode/decoder_pkey.c
index ed10bb1cee035a..ad5e2805319b57 100644
--- a/deps/openssl/openssl/crypto/encode_decode/decoder_pkey.c
+++ b/deps/openssl/openssl/crypto/encode_decode/decoder_pkey.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -150,7 +150,11 @@ static int decoder_construct_pkey(OSSL_DECODER_INSTANCE *decoder_inst,
 
             import_data.keymgmt = keymgmt;
             import_data.keydata = NULL;
-            import_data.selection = data->selection;
+            if (data->selection == 0)
+                /* import/export functions do not tolerate 0 selection */
+                import_data.selection = OSSL_KEYMGMT_SELECT_ALL;
+            else
+                import_data.selection = data->selection;
 
             /*
              * No need to check for errors here, the value of
diff --git a/deps/openssl/openssl/crypto/engine/eng_lib.c b/deps/openssl/openssl/crypto/engine/eng_lib.c
index dfd53a43319559..cfdb5a50f481da 100644
--- a/deps/openssl/openssl/crypto/engine/eng_lib.c
+++ b/deps/openssl/openssl/crypto/engine/eng_lib.c
@@ -133,28 +133,34 @@ static ENGINE_CLEANUP_ITEM *int_cleanup_item(ENGINE_CLEANUP_CB *cb)
     return item;
 }
 
-void engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb)
+int engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb)
 {
     ENGINE_CLEANUP_ITEM *item;
 
     if (!int_cleanup_check(1))
-        return;
+        return 0;
     item = int_cleanup_item(cb);
-    if (item != NULL)
-        if (sk_ENGINE_CLEANUP_ITEM_insert(cleanup_stack, item, 0) <= 0)
-            OPENSSL_free(item);
+    if (item != NULL) {
+        if (sk_ENGINE_CLEANUP_ITEM_insert(cleanup_stack, item, 0))
+            return 1;
+        OPENSSL_free(item);
+    }
+    return 0;
 }
 
-void engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb)
+int engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb)
 {
     ENGINE_CLEANUP_ITEM *item;
+
     if (!int_cleanup_check(1))
-        return;
+        return 0;
     item = int_cleanup_item(cb);
     if (item != NULL) {
-        if (sk_ENGINE_CLEANUP_ITEM_push(cleanup_stack, item) <= 0)
-            OPENSSL_free(item);
+        if (sk_ENGINE_CLEANUP_ITEM_push(cleanup_stack, item) > 0)
+            return 1;
+        OPENSSL_free(item);
     }
+    return 0;
 }
 
 /* The API function that performs all cleanup */
diff --git a/deps/openssl/openssl/crypto/engine/eng_list.c b/deps/openssl/openssl/crypto/engine/eng_list.c
index 04c73c76286486..f2eed3b071746b 100644
--- a/deps/openssl/openssl/crypto/engine/eng_list.c
+++ b/deps/openssl/openssl/crypto/engine/eng_list.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2023 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
@@ -78,12 +78,15 @@ static int engine_list_add(ENGINE *e)
             ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
             return 0;
         }
-        engine_list_head = e;
-        e->prev = NULL;
         /*
          * The first time the list allocates, we should register the cleanup.
          */
-        engine_cleanup_add_last(engine_list_cleanup);
+        if (!engine_cleanup_add_last(engine_list_cleanup)) {
+            ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
+            return 0;
+        }
+        engine_list_head = e;
+        e->prev = NULL;
     } else {
         /* We are adding to the tail of an existing list. */
         if ((engine_list_tail == NULL) || (engine_list_tail->next != NULL)) {
diff --git a/deps/openssl/openssl/crypto/engine/eng_local.h b/deps/openssl/openssl/crypto/engine/eng_local.h
index 03a86299cf88b8..75bc9e6f1675b9 100644
--- a/deps/openssl/openssl/crypto/engine/eng_local.h
+++ b/deps/openssl/openssl/crypto/engine/eng_local.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2023 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
@@ -46,8 +46,8 @@ typedef struct st_engine_cleanup_item {
     ENGINE_CLEANUP_CB *cb;
 } ENGINE_CLEANUP_ITEM;
 DEFINE_STACK_OF(ENGINE_CLEANUP_ITEM)
-void engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb);
-void engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb);
+int engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb);
+int engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb);
 
 /* We need stacks of ENGINEs for use in eng_table.c */
 DEFINE_STACK_OF(ENGINE)
diff --git a/deps/openssl/openssl/crypto/engine/eng_pkey.c b/deps/openssl/openssl/crypto/engine/eng_pkey.c
index 6e6d6df35b2b9a..f84fcde4601629 100644
--- a/deps/openssl/openssl/crypto/engine/eng_pkey.c
+++ b/deps/openssl/openssl/crypto/engine/eng_pkey.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -79,6 +79,48 @@ EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id,
         ERR_raise(ERR_LIB_ENGINE, ENGINE_R_FAILED_LOADING_PRIVATE_KEY);
         return NULL;
     }
+    /* We enforce check for legacy key */
+    switch (EVP_PKEY_get_id(pkey)) {
+    case EVP_PKEY_RSA:
+        {
+        RSA *rsa = EVP_PKEY_get1_RSA(pkey);
+        EVP_PKEY_set1_RSA(pkey, rsa);
+        RSA_free(rsa);
+        }
+        break;
+#  ifndef OPENSSL_NO_EC
+    case EVP_PKEY_SM2:
+    case EVP_PKEY_EC:
+        {
+        EC_KEY *ec = EVP_PKEY_get1_EC_KEY(pkey);
+        EVP_PKEY_set1_EC_KEY(pkey, ec);
+        EC_KEY_free(ec);
+        }
+        break;
+#  endif
+#  ifndef OPENSSL_NO_DSA
+    case EVP_PKEY_DSA:
+        {
+        DSA *dsa = EVP_PKEY_get1_DSA(pkey);
+        EVP_PKEY_set1_DSA(pkey, dsa);
+        DSA_free(dsa);
+        }
+        break;
+#endif
+#  ifndef OPENSSL_NO_DH
+    case EVP_PKEY_DH:
+        {
+        DH *dh = EVP_PKEY_get1_DH(pkey);
+        EVP_PKEY_set1_DH(pkey, dh);
+        DH_free(dh);
+        }
+        break;
+#endif
+    default:
+        /*Do nothing */
+        break;
+    }
+
     return pkey;
 }
 
diff --git a/deps/openssl/openssl/crypto/engine/eng_table.c b/deps/openssl/openssl/crypto/engine/eng_table.c
index a8209d9e71760b..9dc3144bbfd7b6 100644
--- a/deps/openssl/openssl/crypto/engine/eng_table.c
+++ b/deps/openssl/openssl/crypto/engine/eng_table.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -93,9 +93,12 @@ int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup,
         added = 1;
     if (!int_table_check(table, 1))
         goto end;
-    if (added)
-        /* The cleanup callback needs to be added */
-        engine_cleanup_add_first(cleanup);
+    /* The cleanup callback needs to be added */
+    if (added && !engine_cleanup_add_first(cleanup)) {
+        lh_ENGINE_PILE_free(&(*table)->piles);
+        *table = NULL;
+        goto end;
+    }
     while (num_nids--) {
         tmplate.nid = *nids;
         fnd = lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate);
@@ -201,8 +204,10 @@ ENGINE *ossl_engine_table_select(ENGINE_TABLE **table, int nid,
     ENGINE_PILE tmplate, *fnd = NULL;
     int initres, loop = 0;
 
+#ifndef OPENSSL_NO_AUTOLOAD_CONFIG
     /* Load the config before trying to check if engines are available */
     OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
+#endif
 
     if (!(*table)) {
         OSSL_TRACE3(ENGINE_TABLE,
diff --git a/deps/openssl/openssl/crypto/err/openssl.txt b/deps/openssl/openssl/crypto/err/openssl.txt
index d3ac1b19063272..d62ee33ecc77fe 100644
--- a/deps/openssl/openssl/crypto/err/openssl.txt
+++ b/deps/openssl/openssl/crypto/err/openssl.txt
@@ -375,6 +375,7 @@ CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM:179:\
 CMS_R_UNSUPPORTED_LABEL_SOURCE:193:unsupported label source
 CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE:155:unsupported recipientinfo type
 CMS_R_UNSUPPORTED_RECIPIENT_TYPE:154:unsupported recipient type
+CMS_R_UNSUPPORTED_SIGNATURE_ALGORITHM:195:unsupported signature algorithm
 CMS_R_UNSUPPORTED_TYPE:156:unsupported type
 CMS_R_UNWRAP_ERROR:157:unwrap error
 CMS_R_UNWRAP_FAILURE:180:unwrap failure
diff --git a/deps/openssl/openssl/crypto/evp/ctrl_params_translate.c b/deps/openssl/openssl/crypto/evp/ctrl_params_translate.c
index b28875037c7281..dcd53b43f92b9c 100644
--- a/deps/openssl/openssl/crypto/evp/ctrl_params_translate.c
+++ b/deps/openssl/openssl/crypto/evp/ctrl_params_translate.c
@@ -1786,7 +1786,8 @@ static int get_rsa_payload_n(enum state state,
 {
     const BIGNUM *bn = NULL;
 
-    if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA)
+    if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA
+        && EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA_PSS)
         return 0;
     bn = RSA_get0_n(EVP_PKEY_get0_RSA(ctx->p2));
 
@@ -1799,7 +1800,8 @@ static int get_rsa_payload_e(enum state state,
 {
     const BIGNUM *bn = NULL;
 
-    if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA)
+    if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA
+        && EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA_PSS)
         return 0;
     bn = RSA_get0_e(EVP_PKEY_get0_RSA(ctx->p2));
 
@@ -1812,7 +1814,8 @@ static int get_rsa_payload_d(enum state state,
 {
     const BIGNUM *bn = NULL;
 
-    if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA)
+    if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA
+        && EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA_PSS)
         return 0;
     bn = RSA_get0_d(EVP_PKEY_get0_RSA(ctx->p2));
 
@@ -1912,7 +1915,8 @@ static int get_rsa_payload_coefficient(enum state state,
                          const struct translation_st *translation,      \
                          struct translation_ctx_st *ctx)                \
     {                                                                   \
-        if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA)              \
+        if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA               \
+            && EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA_PSS)       \
             return 0;                                                   \
         return get_rsa_payload_factor(state, translation, ctx, n - 1);  \
     }
@@ -1923,7 +1927,8 @@ static int get_rsa_payload_coefficient(enum state state,
                          const struct translation_st *translation,      \
                          struct translation_ctx_st *ctx)                \
     {                                                                   \
-        if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA)              \
+        if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA               \
+            && EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA_PSS)       \
             return 0;                                                   \
         return get_rsa_payload_exponent(state, translation, ctx,        \
                                         n - 1);                         \
@@ -1935,7 +1940,8 @@ static int get_rsa_payload_coefficient(enum state state,
                          const struct translation_st *translation,      \
                          struct translation_ctx_st *ctx)                \
     {                                                                   \
-        if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA)              \
+        if (EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA               \
+            && EVP_PKEY_get_base_id(ctx->p2) != EVP_PKEY_RSA_PSS)       \
             return 0;                                                   \
         return get_rsa_payload_coefficient(state, translation, ctx,     \
                                            n - 1);                      \
@@ -2271,10 +2277,10 @@ static const struct translation_st evp_pkey_ctx_translations[] = {
     { SET, EVP_PKEY_RSA, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN,
       EVP_PKEY_CTRL_RSA_KEYGEN_BITS, "rsa_keygen_bits", NULL,
       OSSL_PKEY_PARAM_RSA_BITS, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
-    { SET, EVP_PKEY_RSA, 0, EVP_PKEY_OP_KEYGEN,
+    { SET, EVP_PKEY_RSA, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN,
       EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, "rsa_keygen_pubexp", NULL,
       OSSL_PKEY_PARAM_RSA_E, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
-    { SET, EVP_PKEY_RSA, 0, EVP_PKEY_OP_KEYGEN,
+    { SET, EVP_PKEY_RSA, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN,
       EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES, "rsa_keygen_primes", NULL,
       OSSL_PKEY_PARAM_RSA_PRIMES, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
 
diff --git a/deps/openssl/openssl/crypto/evp/evp_enc.c b/deps/openssl/openssl/crypto/evp/evp_enc.c
index b178d1086473f1..4e6f83e3d0a94a 100644
--- a/deps/openssl/openssl/crypto/evp/evp_enc.c
+++ b/deps/openssl/openssl/crypto/evp/evp_enc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -192,7 +192,12 @@ static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx,
 #endif
     }
 
-    if (cipher->prov != NULL) {
+    if (!ossl_assert(cipher->prov != NULL)) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+        return 0;
+    }
+
+    if (cipher != ctx->fetched_cipher) {
         if (!EVP_CIPHER_up_ref((EVP_CIPHER *)cipher)) {
             ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
             return 0;
@@ -218,6 +223,42 @@ static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx,
             return 0;
     }
 
+#ifndef FIPS_MODULE
+    /*
+     * Fix for CVE-2023-5363
+     * Passing in a size as part of the init call takes effect late
+     * so, force such to occur before the initialisation.
+     *
+     * The FIPS provider's internal library context is used in a manner
+     * such that this is not an issue.
+     */
+    if (params != NULL) {
+        OSSL_PARAM param_lens[3] = { OSSL_PARAM_END, OSSL_PARAM_END,
+                                     OSSL_PARAM_END };
+        OSSL_PARAM *q = param_lens;
+        const OSSL_PARAM *p;
+
+        p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN); 
+        if (p != NULL)
+            memcpy(q++, p, sizeof(*q));
+
+        /*
+         * Note that OSSL_CIPHER_PARAM_AEAD_IVLEN is a synomym for
+         * OSSL_CIPHER_PARAM_IVLEN so both are covered here.
+         */
+        p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_IVLEN);
+        if (p != NULL)
+            memcpy(q++, p, sizeof(*q));
+
+        if (q != param_lens) {
+            if (!EVP_CIPHER_CTX_set_params(ctx, param_lens)) {
+                ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_LENGTH);
+                return 0;
+            }
+        }
+    }
+#endif
+
     if (enc) {
         if (ctx->cipher->einit == NULL) {
             ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
diff --git a/deps/openssl/openssl/crypto/evp/legacy_sha.c b/deps/openssl/openssl/crypto/evp/legacy_sha.c
index 3859286eeb2046..ca9a3264978abe 100644
--- a/deps/openssl/openssl/crypto/evp/legacy_sha.c
+++ b/deps/openssl/openssl/crypto/evp/legacy_sha.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -71,7 +71,11 @@ static int sha1_int_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2)
 
 static int shake_ctrl(EVP_MD_CTX *evp_ctx, int cmd, int p1, void *p2)
 {
-    KECCAK1600_CTX *ctx = evp_ctx->md_data;
+    KECCAK1600_CTX *ctx;
+
+    if (evp_ctx == NULL)
+        return 0;
+    ctx = evp_ctx->md_data;
 
     switch (cmd) {
     case EVP_MD_CTRL_XOF_LEN:
diff --git a/deps/openssl/openssl/crypto/evp/p_lib.c b/deps/openssl/openssl/crypto/evp/p_lib.c
index aa6ec31dab6e9e..04b148a912187e 100644
--- a/deps/openssl/openssl/crypto/evp/p_lib.c
+++ b/deps/openssl/openssl/crypto/evp/p_lib.c
@@ -717,6 +717,7 @@ static void detect_foreign_key(EVP_PKEY *pkey)
 {
     switch (pkey->type) {
     case EVP_PKEY_RSA:
+    case EVP_PKEY_RSA_PSS:
         pkey->foreign = pkey->pkey.rsa != NULL
                         && ossl_rsa_is_foreign(pkey->pkey.rsa);
         break;
@@ -1075,6 +1076,7 @@ int EVP_PKEY_can_sign(const EVP_PKEY *pkey)
     if (pkey->keymgmt == NULL) {
         switch (EVP_PKEY_get_base_id(pkey)) {
         case EVP_PKEY_RSA:
+        case EVP_PKEY_RSA_PSS:
             return 1;
 # ifndef OPENSSL_NO_DSA
         case EVP_PKEY_DSA:
@@ -1199,7 +1201,7 @@ int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey,
 int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey,
                            int indent, ASN1_PCTX *pctx)
 {
-    return print_pkey(pkey, out, indent, EVP_PKEY_KEYPAIR, NULL,
+    return print_pkey(pkey, out, indent, EVP_PKEY_PRIVATE_KEY, NULL,
                       (pkey->ameth != NULL ? pkey->ameth->priv_print : NULL),
                       pctx);
 }
diff --git a/deps/openssl/openssl/crypto/evp/pmeth_lib.c b/deps/openssl/openssl/crypto/evp/pmeth_lib.c
index ce6e1a1ccbd577..ba1971ce461d57 100644
--- a/deps/openssl/openssl/crypto/evp/pmeth_lib.c
+++ b/deps/openssl/openssl/crypto/evp/pmeth_lib.c
@@ -251,10 +251,11 @@ static EVP_PKEY_CTX *int_ctx_new(OSSL_LIB_CTX *libctx,
      */
     if (e != NULL)
         pmeth = ENGINE_get_pkey_meth(e, id);
-    else if (pkey != NULL && pkey->foreign)
+    else
+# endif /* OPENSSL_NO_ENGINE */
+    if (pkey != NULL && pkey->foreign)
         pmeth = EVP_PKEY_meth_find(id);
     else
-# endif
         app_pmeth = pmeth = evp_pkey_meth_find_added_by_application(id);
 
     /* END legacy */
diff --git a/deps/openssl/openssl/crypto/ex_data.c b/deps/openssl/openssl/crypto/ex_data.c
index 40223f06e4ecb6..13b9288994569c 100644
--- a/deps/openssl/openssl/crypto/ex_data.c
+++ b/deps/openssl/openssl/crypto/ex_data.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -163,6 +163,8 @@ int ossl_crypto_get_ex_new_index_ex(OSSL_LIB_CTX *ctx, int class_index,
          * "app_data" routines use ex_data index zero.  See RT 3710. */
         if (ip->meth == NULL
             || !sk_EX_CALLBACK_push(ip->meth, NULL)) {
+            sk_EX_CALLBACK_free(ip->meth);
+            ip->meth = NULL;
             ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
             goto err;
         }
diff --git a/deps/openssl/openssl/crypto/ffc/ffc_key_validate.c b/deps/openssl/openssl/crypto/ffc/ffc_key_validate.c
index 342789621d6df1..a4a2a58e9a7fd9 100644
--- a/deps/openssl/openssl/crypto/ffc/ffc_key_validate.c
+++ b/deps/openssl/openssl/crypto/ffc/ffc_key_validate.c
@@ -26,7 +26,7 @@ int ossl_ffc_validate_public_key_partial(const FFC_PARAMS *params,
     *ret = 0;
     if (params == NULL || pub_key == NULL || params->p == NULL) {
         *ret = FFC_ERROR_PASSED_NULL_PARAM;
-        return 0;
+        return 1;
     }
 
     ctx = BN_CTX_new_ex(NULL);
@@ -39,18 +39,14 @@ int ossl_ffc_validate_public_key_partial(const FFC_PARAMS *params,
     if (tmp == NULL
         || !BN_set_word(tmp, 1))
         goto err;
-    if (BN_cmp(pub_key, tmp) <= 0) {
+    if (BN_cmp(pub_key, tmp) <= 0)
         *ret |= FFC_ERROR_PUBKEY_TOO_SMALL;
-        goto err;
-    }
     /* Step(1): Verify pub_key <=  p-2 */
     if (BN_copy(tmp, params->p) == NULL
         || !BN_sub_word(tmp, 1))
         goto err;
-    if (BN_cmp(pub_key, tmp) >= 0) {
+    if (BN_cmp(pub_key, tmp) >= 0)
         *ret |= FFC_ERROR_PUBKEY_TOO_LARGE;
-        goto err;
-    }
     ok = 1;
  err:
     if (ctx != NULL) {
@@ -73,7 +69,7 @@ int ossl_ffc_validate_public_key(const FFC_PARAMS *params,
     if (!ossl_ffc_validate_public_key_partial(params, pub_key, ret))
         return 0;
 
-    if (params->q != NULL) {
+    if (*ret == 0 && params->q != NULL) {
         ctx = BN_CTX_new_ex(NULL);
         if (ctx == NULL)
             goto err;
@@ -84,10 +80,8 @@ int ossl_ffc_validate_public_key(const FFC_PARAMS *params,
         if (tmp == NULL
             || !BN_mod_exp(tmp, pub_key, params->q, params->p, ctx))
             goto err;
-        if (!BN_is_one(tmp)) {
+        if (!BN_is_one(tmp))
             *ret |= FFC_ERROR_PUBKEY_INVALID;
-            goto err;
-        }
     }
 
     ok = 1;
diff --git a/deps/openssl/openssl/crypto/http/http_client.c b/deps/openssl/openssl/crypto/http/http_client.c
index ee41c03103e5fc..e3ccc6c4cc2fdd 100644
--- a/deps/openssl/openssl/crypto/http/http_client.c
+++ b/deps/openssl/openssl/crypto/http/http_client.c
@@ -164,7 +164,8 @@ void OSSL_HTTP_REQ_CTX_set_max_response_length(OSSL_HTTP_REQ_CTX *rctx,
 
 /*
  * Create request line using |rctx| and |path| (or "/" in case |path| is NULL).
- * Server name (and port) must be given if and only if plain HTTP proxy is used.
+ * Server name (and optional port) must be given if and only if
+ * a plain HTTP proxy is used and |path| does not begin with 'http://'.
  */
 int OSSL_HTTP_REQ_CTX_set_request_line(OSSL_HTTP_REQ_CTX *rctx, int method_POST,
                                        const char *server, const char *port,
@@ -193,11 +194,17 @@ int OSSL_HTTP_REQ_CTX_set_request_line(OSSL_HTTP_REQ_CTX *rctx, int method_POST,
             return 0;
     }
 
-    /* Make sure path includes a forward slash */
-    if (path == NULL)
+    /* Make sure path includes a forward slash (abs_path) */
+    if (path == NULL)  {
         path = "/";
-    if (path[0] != '/' && BIO_printf(rctx->mem, "/") <= 0)
+    } else if (HAS_PREFIX(path, "http://")) { /* absoluteURI for proxy use */
+        if (server != NULL) {
+            ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_INVALID_ARGUMENT);
+            return 0;
+        }
+    } else if (path[0] != '/' && BIO_printf(rctx->mem, "/") <= 0) {
         return 0;
+    }
     /*
      * Add (the rest of) the path and the HTTP version,
      * which is fixed to 1.0 for straightforward implementation of keep-alive
diff --git a/deps/openssl/openssl/crypto/lhash/lhash.c b/deps/openssl/openssl/crypto/lhash/lhash.c
index 1cd988f01fc76a..a01cfa725e38c7 100644
--- a/deps/openssl/openssl/crypto/lhash/lhash.c
+++ b/deps/openssl/openssl/crypto/lhash/lhash.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -266,12 +266,12 @@ static void contract(OPENSSL_LHASH *lh)
         if (n == NULL) {
             /* fputs("realloc error in lhash",stderr); */
             lh->error++;
-            return;
+        } else {
+            lh->b = n;
         }
         lh->num_alloc_nodes /= 2;
         lh->pmax /= 2;
         lh->p = lh->pmax - 1;
-        lh->b = n;
     } else
         lh->p--;
 
diff --git a/deps/openssl/openssl/crypto/mem.c b/deps/openssl/openssl/crypto/mem.c
index f6cdcf5a423ec7..34128616e2700e 100644
--- a/deps/openssl/openssl/crypto/mem.c
+++ b/deps/openssl/openssl/crypto/mem.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -100,6 +100,9 @@ void CRYPTO_get_alloc_counts(int *mcount, int *rcount, int *fcount)
  *    or    100;100@25;0
  * This means 100 mallocs succeed, then next 100 fail 25% of the time, and
  * all remaining (count is zero) succeed.
+ * The failure percentge can have 2 digits after the comma.  For example:
+ *          0@0.01
+ * This means 0.01% of all allocations will fail.
  */
 static void parseit(void)
 {
@@ -112,26 +115,27 @@ static void parseit(void)
     /* Get the count (atol will stop at the @ if there), and percentage */
     md_count = atol(md_failstring);
     atsign = strchr(md_failstring, '@');
-    md_fail_percent = atsign == NULL ? 0 : atoi(atsign + 1);
+    md_fail_percent = atsign == NULL ? 0 : (int)(atof(atsign + 1) * 100 + 0.5);
 
     if (semi != NULL)
         md_failstring = semi;
 }
 
 /*
- * Windows doesn't have random(), but it has rand()
+ * Windows doesn't have random() and srandom(), but it has rand() and srand().
  * Some rand() implementations aren't good, but we're not
  * dealing with secure randomness here.
  */
 # ifdef _WIN32
 #  define random() rand()
+#  define srandom(seed) srand(seed)
 # endif
 /*
  * See if the current malloc should fail.
  */
 static int shouldfail(void)
 {
-    int roll = (int)(random() % 100);
+    int roll = (int)(random() % 10000);
     int shoulditfail = roll < md_fail_percent;
 # ifndef _WIN32
 /* suppressed on Windows as POSIX-like file descriptors are non-inheritable */
@@ -165,6 +169,8 @@ void ossl_malloc_setup_failures(void)
         parseit();
     if ((cp = getenv("OPENSSL_MALLOC_FD")) != NULL)
         md_tracefd = atoi(cp);
+    if ((cp = getenv("OPENSSL_MALLOC_SEED")) != NULL)
+        srandom(atoi(cp));
 }
 #endif
 
@@ -195,7 +201,6 @@ void *CRYPTO_zalloc(size_t num, const char *file, int line)
     void *ret;
 
     ret = CRYPTO_malloc(num, file, line);
-    FAILTEST();
     if (ret != NULL)
         memset(ret, 0, num);
 
@@ -208,7 +213,6 @@ void *CRYPTO_realloc(void *str, size_t num, const char *file, int line)
     if (realloc_impl != CRYPTO_realloc)
         return realloc_impl(str, num, file, line);
 
-    FAILTEST();
     if (str == NULL)
         return CRYPTO_malloc(num, file, line);
 
@@ -217,6 +221,7 @@ void *CRYPTO_realloc(void *str, size_t num, const char *file, int line)
         return NULL;
     }
 
+    FAILTEST();
     return realloc(str, num);
 }
 
diff --git a/deps/openssl/openssl/crypto/modes/asm/ghashv8-armx.pl b/deps/openssl/openssl/crypto/modes/asm/ghashv8-armx.pl
index b1d35d25b5b19f..b3d94041729e6f 100644
--- a/deps/openssl/openssl/crypto/modes/asm/ghashv8-armx.pl
+++ b/deps/openssl/openssl/crypto/modes/asm/ghashv8-armx.pl
@@ -1,5 +1,5 @@
 #! /usr/bin/env perl
-# Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2014-2023 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the Apache License 2.0 (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
@@ -744,6 +744,9 @@
 	s/\.[uisp]?64//o and s/\.16b/\.2d/go;
 	s/\.[42]([sd])\[([0-3])\]/\.$1\[$2\]/o;
 
+	# Switch preprocessor checks to aarch64 versions.
+	s/__ARME([BL])__/__AARCH64E$1__/go;
+
 	print $_,"\n";
     }
 } else {				######## 32-bit code
diff --git a/deps/openssl/openssl/crypto/objects/obj_dat.c b/deps/openssl/openssl/crypto/objects/obj_dat.c
index 1a52000e6e9d64..85d30eb58ae013 100644
--- a/deps/openssl/openssl/crypto/objects/obj_dat.c
+++ b/deps/openssl/openssl/crypto/objects/obj_dat.c
@@ -642,13 +642,14 @@ const void *OBJ_bsearch_ex_(const void *key, const void *base, int num,
     if (p == NULL) {
         const char *base_ = base;
         int l, h, i = 0, c = 0;
+        char *p1;
 
         for (i = 0; i < num; ++i) {
-            p = &(base_[i * size]);
-            c = (*cmp) (key, p);
+            p1 = &(base_[i * size]);
+            c = (*cmp) (key, p1);
             if (c == 0
                 || (c < 0 && (flags & OBJ_BSEARCH_VALUE_ON_NOMATCH)))
-                return p;
+                return p1;
         }
     }
 #endif
diff --git a/deps/openssl/openssl/crypto/param_build_set.c b/deps/openssl/openssl/crypto/param_build_set.c
index 8b570ded96ebb4..5de06cc7ed685c 100644
--- a/deps/openssl/openssl/crypto/param_build_set.c
+++ b/deps/openssl/openssl/crypto/param_build_set.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -99,21 +99,22 @@ int ossl_param_build_set_multi_key_bn(OSSL_PARAM_BLD *bld, OSSL_PARAM *params,
 {
     int i, sz = sk_BIGNUM_const_num(stk);
     OSSL_PARAM *p;
-
+    const BIGNUM *bn;
 
     if (bld != NULL) {
         for (i = 0; i < sz && names[i] != NULL; ++i) {
-            if (!OSSL_PARAM_BLD_push_BN(bld, names[i],
-                                        sk_BIGNUM_const_value(stk, i)))
+            bn = sk_BIGNUM_const_value(stk, i);
+            if (bn != NULL && !OSSL_PARAM_BLD_push_BN(bld, names[i], bn))
                 return 0;
         }
         return 1;
     }
 
     for (i = 0; i < sz && names[i] != NULL; ++i) {
+        bn = sk_BIGNUM_const_value(stk, i);
         p = OSSL_PARAM_locate(params, names[i]);
-        if (p != NULL) {
-            if (!OSSL_PARAM_set_BN(p, sk_BIGNUM_const_value(stk, i)))
+        if (p != NULL && bn != NULL) {
+            if (!OSSL_PARAM_set_BN(p, bn))
                 return 0;
         }
     }
diff --git a/deps/openssl/openssl/crypto/pem/pem_pkey.c b/deps/openssl/openssl/crypto/pem/pem_pkey.c
index 3e76852c67a44a..4deee46ce5506f 100644
--- a/deps/openssl/openssl/crypto/pem/pem_pkey.c
+++ b/deps/openssl/openssl/crypto/pem/pem_pkey.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -366,10 +366,19 @@ int PEM_write_bio_PrivateKey_traditional(BIO *bp, const EVP_PKEY *x,
     return ret;
 }
 
+static int no_password_cb(char *buf, int num, int rwflag, void *userdata)
+{
+    return -1;
+}
+
 EVP_PKEY *PEM_read_bio_Parameters_ex(BIO *bp, EVP_PKEY **x,
                                      OSSL_LIB_CTX *libctx, const char *propq)
 {
-    return pem_read_bio_key(bp, x, NULL, NULL, libctx, propq,
+    /*
+     * PEM_read_bio_Parameters(_ex) should never ask for a password. Any attempt
+     * to get a password just fails.
+     */
+    return pem_read_bio_key(bp, x, no_password_cb, NULL, libctx, propq,
                             EVP_PKEY_KEY_PARAMETERS);
 }
 
diff --git a/deps/openssl/openssl/crypto/perlasm/arm-xlate.pl b/deps/openssl/openssl/crypto/perlasm/arm-xlate.pl
index a90885905c0fdb..38d570c79017c2 100755
--- a/deps/openssl/openssl/crypto/perlasm/arm-xlate.pl
+++ b/deps/openssl/openssl/crypto/perlasm/arm-xlate.pl
@@ -1,5 +1,5 @@
 #! /usr/bin/env perl
-# Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the Apache License 2.0 (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
@@ -159,9 +159,8 @@ sub expand_line {
     }
 
     {
-	$line =~ s|(^[\.\w]+)\:\s*||;
-	my $label = $1;
-	if ($label) {
+	if ($line =~ s|(^[\.\w]+)\:\s*||) {
+	    my $label = $1;
 	    printf "%s:",($GLOBALS{$label} or $label);
 	}
     }
diff --git a/deps/openssl/openssl/crypto/pkcs12/p12_crt.c b/deps/openssl/openssl/crypto/pkcs12/p12_crt.c
index 00c71297463d9e..26a444f868b028 100644
--- a/deps/openssl/openssl/crypto/pkcs12/p12_crt.c
+++ b/deps/openssl/openssl/crypto/pkcs12/p12_crt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -14,6 +14,12 @@
 
 static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
                           PKCS12_SAFEBAG *bag);
+static PKCS12_SAFEBAG *pkcs12_add_cert_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
+                                           X509 *cert,
+                                           const char *name,
+                                           int namelen,
+                                           unsigned char *keyid,
+                                           int keyidlen);
 
 static int copy_bag_attr(PKCS12_SAFEBAG *bag, EVP_PKEY *pkey, int nid)
 {
@@ -40,6 +46,9 @@ PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey,
     int i;
     unsigned char keyid[EVP_MAX_MD_SIZE];
     unsigned int keyidlen = 0;
+    int namelen = -1;
+    unsigned char *pkeyid = NULL;
+    int pkeyidlen = -1;
 
     /* Set defaults */
     if (nid_cert == NID_undef)
@@ -64,11 +73,16 @@ PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey,
     }
 
     if (cert) {
-        bag = PKCS12_add_cert(&bags, cert);
-        if (name && !PKCS12_add_friendlyname(bag, name, -1))
-            goto err;
-        if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
-            goto err;
+        if (name == NULL)
+            name = (char *)X509_alias_get0(cert, &namelen);
+        if (keyidlen > 0) {
+            pkeyid = keyid;
+            pkeyidlen = keyidlen;
+        } else {
+            pkeyid = X509_keyid_get0(cert, &pkeyidlen);
+        }
+
+        bag = pkcs12_add_cert_bag(&bags, cert, name, namelen, pkeyid, pkeyidlen);
     }
 
     /* Add all other certificates */
@@ -139,30 +153,23 @@ PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *
                             iter, mac_iter, keytype, NULL, NULL);
 }
 
-PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert)
+static PKCS12_SAFEBAG *pkcs12_add_cert_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
+                                           X509 *cert,
+                                           const char *name,
+                                           int namelen,
+                                           unsigned char *keyid,
+                                           int keyidlen)
 {
     PKCS12_SAFEBAG *bag = NULL;
-    char *name;
-    int namelen = -1;
-    unsigned char *keyid;
-    int keyidlen = -1;
 
     /* Add user certificate */
     if ((bag = PKCS12_SAFEBAG_create_cert(cert)) == NULL)
         goto err;
 
-    /*
-     * Use friendlyName and localKeyID in certificate. (if present)
-     */
-
-    name = (char *)X509_alias_get0(cert, &namelen);
-
-    if (name && !PKCS12_add_friendlyname(bag, name, namelen))
+    if (name != NULL && !PKCS12_add_friendlyname(bag, name, namelen))
         goto err;
 
-    keyid = X509_keyid_get0(cert, &keyidlen);
-
-    if (keyid && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
+    if (keyid != NULL && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
         goto err;
 
     if (!pkcs12_add_bag(pbags, bag))
@@ -173,7 +180,22 @@ PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert)
  err:
     PKCS12_SAFEBAG_free(bag);
     return NULL;
+}
+
+PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert)
+{
+    char *name = NULL;
+    int namelen = -1;
+    unsigned char *keyid = NULL;
+    int keyidlen = -1;
+
+    /*
+     * Use friendlyName and localKeyID in certificate. (if present)
+     */
+    name = (char *)X509_alias_get0(cert, &namelen);
+    keyid = X509_keyid_get0(cert, &keyidlen);
 
+    return pkcs12_add_cert_bag(pbags, cert, name, namelen, keyid, keyidlen);
 }
 
 PKCS12_SAFEBAG *PKCS12_add_key_ex(STACK_OF(PKCS12_SAFEBAG) **pbags,
diff --git a/deps/openssl/openssl/crypto/poly1305/asm/poly1305-armv8.pl b/deps/openssl/openssl/crypto/poly1305/asm/poly1305-armv8.pl
index 113a2151b6fa14..dc39f4053fe6a9 100755
--- a/deps/openssl/openssl/crypto/poly1305/asm/poly1305-armv8.pl
+++ b/deps/openssl/openssl/crypto/poly1305/asm/poly1305-armv8.pl
@@ -1,5 +1,5 @@
 #! /usr/bin/env perl
-# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the Apache License 2.0 (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
@@ -85,7 +85,7 @@
 	ldp	$r0,$r1,[$inp]		// load key
 	mov	$s1,#0xfffffffc0fffffff
 	movk	$s1,#0x0fff,lsl#48
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	$r0,$r0			// flip bytes
 	rev	$r1,$r1
 #endif
@@ -132,7 +132,7 @@
 .Loop:
 	ldp	$t0,$t1,[$inp],#16	// load input
 	sub	$len,$len,#16
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	$t0,$t0
 	rev	$t1,$t1
 #endif
@@ -197,13 +197,13 @@
 	csel	$h0,$h0,$d0,eq
 	csel	$h1,$h1,$d1,eq
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	ror	$t0,$t0,#32		// flip nonce words
 	ror	$t1,$t1,#32
 #endif
 	adds	$h0,$h0,$t0		// accumulate nonce
 	adc	$h1,$h1,$t1
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	$h0,$h0			// flip output bytes
 	rev	$h1,$h1
 #endif
@@ -335,7 +335,7 @@
 	adcs	$h1,$h1,xzr
 	adc	$h2,$h2,xzr
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	$d0,$d0
 	rev	$d1,$d1
 #endif
@@ -381,7 +381,7 @@
 	ldp	$d0,$d1,[$inp],#16	// load input
 	sub	$len,$len,#16
 	add	$s1,$r1,$r1,lsr#2	// s1 = r1 + (r1 >> 2)
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	$d0,$d0
 	rev	$d1,$d1
 #endif
@@ -466,7 +466,7 @@
 	lsl	$padbit,$padbit,#24
 	add	x15,$ctx,#48
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x8,x8
 	rev	x12,x12
 	rev	x9,x9
@@ -502,7 +502,7 @@
 	ld1	{$S2,$R3,$S3,$R4},[x15],#64
 	ld1	{$S4},[x15]
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	x8,x8
 	rev	x12,x12
 	rev	x9,x9
@@ -563,7 +563,7 @@
 	umull	$ACC1,$IN23_0,${R1}[2]
 	 ldp	x9,x13,[$in2],#48
 	umull	$ACC0,$IN23_0,${R0}[2]
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	 rev	x8,x8
 	 rev	x12,x12
 	 rev	x9,x9
@@ -628,7 +628,7 @@
 	umlal	$ACC4,$IN01_2,${R2}[0]
 	umlal	$ACC1,$IN01_2,${S4}[0]
 	umlal	$ACC2,$IN01_2,${R0}[0]
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	 rev	x8,x8
 	 rev	x12,x12
 	 rev	x9,x9
@@ -909,13 +909,13 @@
 	csel	$h0,$h0,$d0,eq
 	csel	$h1,$h1,$d1,eq
 
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	ror	$t0,$t0,#32		// flip nonce words
 	ror	$t1,$t1,#32
 #endif
 	adds	$h0,$h0,$t0		// accumulate nonce
 	adc	$h1,$h1,$t1
-#ifdef	__ARMEB__
+#ifdef	__AARCH64EB__
 	rev	$h0,$h0			// flip output bytes
 	rev	$h1,$h1
 #endif
diff --git a/deps/openssl/openssl/crypto/poly1305/asm/poly1305-x86_64.pl b/deps/openssl/openssl/crypto/poly1305/asm/poly1305-x86_64.pl
index fa9bfb7a7b814c..4cddca1c514c04 100755
--- a/deps/openssl/openssl/crypto/poly1305/asm/poly1305-x86_64.pl
+++ b/deps/openssl/openssl/crypto/poly1305/asm/poly1305-x86_64.pl
@@ -1,5 +1,5 @@
 #! /usr/bin/env perl
-# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the Apache License 2.0 (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
@@ -195,7 +195,7 @@ sub poly1305_iteration {
 	bt	\$`5+32`,%r9		# AVX2?
 	cmovc	%rax,%r10
 ___
-$code.=<<___	if ($avx>3);
+$code.=<<___	if ($avx>3 && !$win64);
 	mov	\$`(1<<31|1<<21|1<<16)`,%rax
 	shr	\$32,%r9
 	and	%rax,%r9
@@ -2724,7 +2724,7 @@ sub poly1305_iteration {
 .cfi_endproc
 .size	poly1305_blocks_avx512,.-poly1305_blocks_avx512
 ___
-if ($avx>3) {
+if ($avx>3 && !$win64) {
 ########################################################################
 # VPMADD52 version using 2^44 radix.
 #
diff --git a/deps/openssl/openssl/crypto/property/property.c b/deps/openssl/openssl/crypto/property/property.c
index b97861d4862fa8..602db0f3ff54e9 100644
--- a/deps/openssl/openssl/crypto/property/property.c
+++ b/deps/openssl/openssl/crypto/property/property.c
@@ -129,11 +129,11 @@ static const OSSL_LIB_CTX_METHOD ossl_ctx_global_properties_method = {
 };
 
 OSSL_PROPERTY_LIST **ossl_ctx_global_properties(OSSL_LIB_CTX *libctx,
-                                                int loadconfig)
+                                                ossl_unused int loadconfig)
 {
     OSSL_GLOBAL_PROPERTIES *globp;
 
-#ifndef FIPS_MODULE
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_AUTOLOAD_CONFIG)
     if (loadconfig && !OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL))
         return NULL;
 #endif
@@ -513,7 +513,7 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store,
     if (nid <= 0 || method == NULL || store == NULL)
         return 0;
 
-#ifndef FIPS_MODULE
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_AUTOLOAD_CONFIG)
     if (ossl_lib_ctx_is_default(store->ctx)
             && !OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL))
         return 0;
diff --git a/deps/openssl/openssl/crypto/property/property_parse.c b/deps/openssl/openssl/crypto/property/property_parse.c
index ca2bd33381bfdd..e3a4998df11fcb 100644
--- a/deps/openssl/openssl/crypto/property/property_parse.c
+++ b/deps/openssl/openssl/crypto/property/property_parse.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright (c) 2019, Oracle and/or its affiliates.  All rights reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
@@ -588,15 +588,38 @@ static void put_char(char ch, char **buf, size_t *remain, size_t *needed)
 
 static void put_str(const char *str, char **buf, size_t *remain, size_t *needed)
 {
-    size_t olen, len;
+    size_t olen, len, i;
+    char quote = '\0';
+    int quotes;
 
     len = olen = strlen(str);
     *needed += len;
 
-    if (*remain == 0)
+    /*
+     * Check to see if we need quotes or not.
+     * Characters that are legal in a PropertyName don't need quoting.
+     * We simply assume all others require quotes.
+     */
+    for (i = 0; i < len; i++)
+        if (!ossl_isalnum(str[i]) && str[i] != '.' && str[i] != '_') {
+            /* Default to single quotes ... */
+            if (quote == '\0')
+                quote = '\'';
+            /* ... but use double quotes if a single is present */
+            if (str[i] == '\'')
+                quote = '"';
+        }
+
+    quotes = quote != '\0';
+    if (*remain == 0) {
+        *needed += 2 * quotes;
         return;
+    }
 
-    if (*remain < len + 1)
+    if (quotes)
+        put_char(quote, buf, remain, needed);
+
+    if (*remain < len + 1 + quotes)
         len = *remain - 1;
 
     if (len > 0) {
@@ -605,6 +628,9 @@ static void put_str(const char *str, char **buf, size_t *remain, size_t *needed)
         *remain -= len;
     }
 
+    if (quotes)
+        put_char(quote, buf, remain, needed);
+
     if (len < olen && *remain == 1) {
         **buf = '\0';
         ++*buf;
diff --git a/deps/openssl/openssl/crypto/provider_core.c b/deps/openssl/openssl/crypto/provider_core.c
index 7a12328121623e..92cce32c5bbf88 100644
--- a/deps/openssl/openssl/crypto/provider_core.c
+++ b/deps/openssl/openssl/crypto/provider_core.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -408,7 +408,7 @@ int ossl_provider_info_add_to_store(OSSL_LIB_CTX *libctx,
 }
 
 OSSL_PROVIDER *ossl_provider_find(OSSL_LIB_CTX *libctx, const char *name,
-                                  int noconfig)
+                                  ossl_unused int noconfig)
 {
     struct provider_store_st *store = NULL;
     OSSL_PROVIDER *prov = NULL;
@@ -417,7 +417,7 @@ OSSL_PROVIDER *ossl_provider_find(OSSL_LIB_CTX *libctx, const char *name,
         OSSL_PROVIDER tmpl = { 0, };
         int i;
 
-#ifndef FIPS_MODULE
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_AUTOLOAD_CONFIG)
         /*
          * Make sure any providers are loaded from config before we try to find
          * them.
@@ -1356,7 +1356,7 @@ int ossl_provider_doall_activated(OSSL_LIB_CTX *ctx,
     struct provider_store_st *store = get_provider_store(ctx);
     STACK_OF(OSSL_PROVIDER) *provs = NULL;
 
-#ifndef FIPS_MODULE
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_AUTOLOAD_CONFIG)
     /*
      * Make sure any providers are loaded from config before we try to use
      * them.
diff --git a/deps/openssl/openssl/crypto/rsa/rsa_ameth.c b/deps/openssl/openssl/crypto/rsa/rsa_ameth.c
index e819780e7d9439..07734077e3228a 100644
--- a/deps/openssl/openssl/crypto/rsa/rsa_ameth.c
+++ b/deps/openssl/openssl/crypto/rsa/rsa_ameth.c
@@ -60,13 +60,16 @@ static int rsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
     if (!rsa_param_encode(pkey, &str, &strtype))
         return 0;
     penclen = i2d_RSAPublicKey(pkey->pkey.rsa, &penc);
-    if (penclen <= 0)
+    if (penclen <= 0) {
+        ASN1_STRING_free(str);
         return 0;
+    }
     if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id),
                                strtype, str, penc, penclen))
         return 1;
 
     OPENSSL_free(penc);
+    ASN1_STRING_free(str);
     return 0;
 }
 
diff --git a/deps/openssl/openssl/crypto/rsa/rsa_backend.c b/deps/openssl/openssl/crypto/rsa/rsa_backend.c
index 58187fa2ef59df..f9d1cb361d7704 100644
--- a/deps/openssl/openssl/crypto/rsa/rsa_backend.c
+++ b/deps/openssl/openssl/crypto/rsa/rsa_backend.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -141,18 +141,6 @@ int ossl_rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[],
 
     /* Check private key data integrity */
     if (include_private && rsa_d != NULL) {
-        int numprimes = sk_BIGNUM_const_num(factors);
-        int numexps = sk_BIGNUM_const_num(exps);
-        int numcoeffs = sk_BIGNUM_const_num(coeffs);
-
-        /*
-         * It's permissible to have zero primes, i.e. no CRT params.
-         * Otherwise, there must be at least two, as many exponents,
-         * and one coefficient less.
-         */
-        if (numprimes != 0
-            && (numprimes < 2 || numexps < 2 || numcoeffs < 1))
-            goto err;
 
         if (!ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_RSA_D,
                                      rsa_d)
diff --git a/deps/openssl/openssl/crypto/rsa/rsa_lib.c b/deps/openssl/openssl/crypto/rsa/rsa_lib.c
index 449097b8b27afc..71a17a92349d3b 100644
--- a/deps/openssl/openssl/crypto/rsa/rsa_lib.c
+++ b/deps/openssl/openssl/crypto/rsa/rsa_lib.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -753,18 +753,22 @@ int ossl_rsa_set0_all_params(RSA *r, const STACK_OF(BIGNUM) *primes,
         return 0;
 
     pnum = sk_BIGNUM_num(primes);
-    if (pnum < 2
-        || pnum != sk_BIGNUM_num(exps)
-        || pnum != sk_BIGNUM_num(coeffs) + 1)
+    if (pnum < 2)
         return 0;
 
     if (!RSA_set0_factors(r, sk_BIGNUM_value(primes, 0),
-                          sk_BIGNUM_value(primes, 1))
-        || !RSA_set0_crt_params(r, sk_BIGNUM_value(exps, 0),
-                                sk_BIGNUM_value(exps, 1),
-                                sk_BIGNUM_value(coeffs, 0)))
+                          sk_BIGNUM_value(primes, 1)))
         return 0;
 
+    if (pnum == sk_BIGNUM_num(exps)
+        && pnum == sk_BIGNUM_num(coeffs) + 1) {
+
+        if (!RSA_set0_crt_params(r, sk_BIGNUM_value(exps, 0),
+                                 sk_BIGNUM_value(exps, 1),
+                                 sk_BIGNUM_value(coeffs, 0)))
+        return 0;
+    }
+
 #ifndef FIPS_MODULE
     old_infos = r->prime_infos;
 #endif
@@ -1084,6 +1088,12 @@ int EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD **md)
 int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, void *label, int llen)
 {
     OSSL_PARAM rsa_params[2], *p = rsa_params;
+    const char *empty = "";
+    /*
+     * Needed as we swap label with empty if it is NULL, and label is
+     * freed at the end of this function.
+     */
+    void *plabel = label;
     int ret;
 
     if (ctx == NULL || !EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)) {
@@ -1096,9 +1106,13 @@ int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, void *label, int llen)
     if (!EVP_PKEY_CTX_is_a(ctx, "RSA"))
         return -1;
 
+    /* Accept NULL for backward compatibility */
+    if (label == NULL && llen == 0)
+        plabel = (void *)empty;
+
     /* Cast away the const. This is read only so should be safe */
     *p++ = OSSL_PARAM_construct_octet_string(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL,
-                                             (void *)label, (size_t)llen);
+                                             (void *)plabel, (size_t)llen);
     *p++ = OSSL_PARAM_construct_end();
 
     ret = evp_pkey_ctx_set_params_strict(ctx, rsa_params);
diff --git a/deps/openssl/openssl/crypto/srp/srp_vfy.c b/deps/openssl/openssl/crypto/srp/srp_vfy.c
index e8beb60d278a08..96d511ffe6368e 100644
--- a/deps/openssl/openssl/crypto/srp/srp_vfy.c
+++ b/deps/openssl/openssl/crypto/srp/srp_vfy.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-2023 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright (c) 2004, EdelKey Project. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
@@ -283,6 +283,7 @@ SRP_VBASE *SRP_VBASE_new(char *seed_key)
         return NULL;
     if ((vb->users_pwd = sk_SRP_user_pwd_new_null()) == NULL
         || (vb->gN_cache = sk_SRP_gN_cache_new_null()) == NULL) {
+        sk_SRP_user_pwd_free(vb->users_pwd);
         OPENSSL_free(vb);
         return NULL;
     }
diff --git a/deps/openssl/openssl/crypto/store/store_lib.c b/deps/openssl/openssl/crypto/store/store_lib.c
index 5ff927862916e5..bc12d8dd13a28e 100644
--- a/deps/openssl/openssl/crypto/store/store_lib.c
+++ b/deps/openssl/openssl/crypto/store/store_lib.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -424,14 +424,14 @@ OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx)
 
             load_data.v = NULL;
             load_data.ctx = ctx;
+            ctx->error_flag = 0;
 
             if (!ctx->fetched_loader->p_load(ctx->loader_ctx,
                                              ossl_store_handle_load_result,
                                              &load_data,
                                              ossl_pw_passphrase_callback_dec,
                                              &ctx->pwdata)) {
-                if (!OSSL_STORE_eof(ctx))
-                    ctx->error_flag = 1;
+                ctx->error_flag = 1;
                 return NULL;
             }
             v = load_data.v;
diff --git a/deps/openssl/openssl/crypto/threads_pthread.c b/deps/openssl/openssl/crypto/threads_pthread.c
index bfc05a4e878c25..801855c9306e20 100644
--- a/deps/openssl/openssl/crypto/threads_pthread.c
+++ b/deps/openssl/openssl/crypto/threads_pthread.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -72,8 +72,6 @@ CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void)
 #  if !defined (__TANDEM) && !defined (_SPT_MODEL_)
 #   if !defined(NDEBUG) && !defined(OPENSSL_NO_MUTEX_ERRORCHECK)
     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
-#   else
-    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
 #   endif
 #  else
     /* The SPT Thread Library does not define MUTEX attributes. */
diff --git a/deps/openssl/openssl/crypto/x509/v3_ist.c b/deps/openssl/openssl/crypto/x509/v3_ist.c
index e6fef0153c8eb2..4a3cfa12a471b6 100644
--- a/deps/openssl/openssl/crypto/x509/v3_ist.c
+++ b/deps/openssl/openssl/crypto/x509/v3_ist.c
@@ -51,25 +51,25 @@ static ISSUER_SIGN_TOOL *v2i_issuer_sign_tool(X509V3_EXT_METHOD *method, X509V3_
         if (strcmp(cnf->name, "signTool") == 0) {
             ist->signTool = ASN1_UTF8STRING_new();
             if (ist->signTool == NULL || !ASN1_STRING_set(ist->signTool, cnf->value, strlen(cnf->value))) {
-                ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB);
+                ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
                 goto err;
             }
         } else if (strcmp(cnf->name, "cATool") == 0) {
             ist->cATool = ASN1_UTF8STRING_new();
             if (ist->cATool == NULL || !ASN1_STRING_set(ist->cATool, cnf->value, strlen(cnf->value))) {
-                ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB);
+                ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
                 goto err;
             }
         } else if (strcmp(cnf->name, "signToolCert") == 0) {
             ist->signToolCert = ASN1_UTF8STRING_new();
             if (ist->signToolCert == NULL || !ASN1_STRING_set(ist->signToolCert, cnf->value, strlen(cnf->value))) {
-                ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB);
+                ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
                 goto err;
             }
         } else if (strcmp(cnf->name, "cAToolCert") == 0) {
             ist->cAToolCert = ASN1_UTF8STRING_new();
             if (ist->cAToolCert == NULL || !ASN1_STRING_set(ist->cAToolCert, cnf->value, strlen(cnf->value))) {
-                ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB);
+                ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
                 goto err;
             }
         } else {
diff --git a/deps/openssl/openssl/crypto/x509/x509_cmp.c b/deps/openssl/openssl/crypto/x509/x509_cmp.c
index 1027bed82e69da..989fb8faa9f465 100644
--- a/deps/openssl/openssl/crypto/x509/x509_cmp.c
+++ b/deps/openssl/openssl/crypto/x509/x509_cmp.c
@@ -292,12 +292,13 @@ unsigned long X509_NAME_hash_ex(const X509_NAME *x, OSSL_LIB_CTX *libctx,
     unsigned long ret = 0;
     unsigned char md[SHA_DIGEST_LENGTH];
     EVP_MD *sha1 = EVP_MD_fetch(libctx, "SHA1", propq);
+    int i2d_ret;
 
     /* Make sure X509_NAME structure contains valid cached encoding */
-    i2d_X509_NAME(x, NULL);
+    i2d_ret = i2d_X509_NAME(x, NULL);
     if (ok != NULL)
         *ok = 0;
-    if (sha1 != NULL
+    if (i2d_ret >= 0 && sha1 != NULL
         && EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, sha1, NULL)) {
         ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
                ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
@@ -325,7 +326,9 @@ unsigned long X509_NAME_hash_old(const X509_NAME *x)
         goto end;
 
     /* Make sure X509_NAME structure contains valid cached encoding */
-    i2d_X509_NAME(x, NULL);
+    if (i2d_X509_NAME(x, NULL) < 0)
+        goto end;
+
     if (EVP_DigestInit_ex(md_ctx, md5, NULL)
         && EVP_DigestUpdate(md_ctx, x->bytes->data, x->bytes->length)
         && EVP_DigestFinal_ex(md_ctx, md, NULL))
diff --git a/deps/openssl/openssl/doc/man1/openssl-cmp.pod.in b/deps/openssl/openssl/doc/man1/openssl-cmp.pod.in
index 4250deb426fc15..9240916fce40fe 100644
--- a/deps/openssl/openssl/doc/man1/openssl-cmp.pod.in
+++ b/deps/openssl/openssl/doc/man1/openssl-cmp.pod.in
@@ -659,11 +659,12 @@ is typically used when authenticating with pre-shared key (password-based MAC).
 
 =item B<-secret> I
 
-Prefer PBM-based message protection with given source of a secret value.
-The secret is used for creating PBM-based protection of outgoing messages
-and (as far as needed) for validating PBM-based protection of incoming messages.
-PBM stands for Password-Based Message Authentication Code.
+Provides the source of a secret value to use with MAC-based message protection.
 This takes precedence over the B<-cert> and B<-key> options.
+The secret is used for creating MAC-based protection of outgoing messages
+and for validating incoming messages that have MAC-based protection.
+The algorithm used by default is Password-Based Message Authentication Code (PBM)
+as defined in RFC 4210 section 5.1.3.1.
 
 For more information about the format of I see
 L.
@@ -682,7 +683,8 @@ while the subject of B<-oldcert> or B<-subjectName> may provide fallback values.
 The issuer of this certificate is used as one of the recipient fallback values
 and as fallback issuer entry in the certificate template of IR/CR/KUR messages.
 
-When using signature-based message protection, this "protection certificate"
+When performing signature-based message protection,
+this "protection certificate", also called "signer certificate",
 will be included first in the extraCerts field of outgoing messages
 and the signature is done with the corresponding key.
 In Initialization Request (IR) messages this can be used for authenticating
@@ -713,8 +715,8 @@ have no effect on the certificate verification enabled via this option.
 
 The corresponding private key file for the client's current certificate given in
 the B<-cert> option.
-This will be used for signature-based message protection unless
-the B<-secret> option indicating PBM or B<-unprotected_requests> is given.
+This will be used for signature-based message protection unless the B<-secret>
+option indicating MAC-based protection or B<-unprotected_requests> is given.
 
 It is also used as a fallback for the B<-newkey> option with IR/CR/KUR messages.
 
@@ -730,7 +732,7 @@ L.
 =item B<-digest> I
 
 Specifies name of supported digest to use in RFC 4210's MSG_SIG_ALG
-and as the one-way function (OWF) in MSG_MAC_ALG.
+and as the one-way function (OWF) in C.
 If applicable, this is used for message protection and
 proof-of-possession (POPO) signatures.
 To see the list of supported digests, use C.
@@ -738,7 +740,7 @@ Defaults to C.
 
 =item B<-mac> I
 
-Specifies the name of the MAC algorithm in MSG_MAC_ALG.
+Specifies the name of the MAC algorithm in C.
 To get the names of supported MAC algorithms use C
 and possibly combine such a name with the name of a supported digest algorithm,
 e.g., hmacWithSHA256.
@@ -1097,6 +1099,13 @@ only affect the certificate verification enabled via the B<-out_trusted> option.
 
 =head1 NOTES
 
+When a client obtains from a CMP server CA certificates that it is going to
+trust, for instance via the C field of a certificate response,
+authentication of the CMP server is particularly critical.
+So special care must be taken setting up server authentication
+using B<-trusted> and related options for certificate-based authentication
+or B<-secret> for MAC-based protection.
+
 When setting up CMP configurations and experimenting with enrollment options
 typically various errors occur until the configuration is correct and complete.
 When the CMP server reports an error the client will by default
@@ -1166,7 +1175,7 @@ In order to update the enrolled certificate one may call
 
   openssl cmp -section insta,kur
 
-using with PBM-based protection or
+using MAC-based protection with PBM or
 
   openssl cmp -section insta,kur,signature
 
@@ -1225,7 +1234,7 @@ Then it can start using the new cert and key.
     -newkey cl_key_new.pem -certout cl_cert.pem
   cp cl_key_new.pem cl_key.pem
 
-This command sequence can be repated as often as needed.
+This command sequence can be repeated as often as needed.
 
 =head2 Requesting information from CMP server
 
diff --git a/deps/openssl/openssl/doc/man1/openssl-cms.pod.in b/deps/openssl/openssl/doc/man1/openssl-cms.pod.in
index c63a7f330ba636..65a61ee97f1d6a 100644
--- a/deps/openssl/openssl/doc/man1/openssl-cms.pod.in
+++ b/deps/openssl/openssl/doc/man1/openssl-cms.pod.in
@@ -391,7 +391,7 @@ option.
 =item I ...
 
 This is an alternative to using the B<-recip> option when encrypting a message.
-One or more certificate filennames may be given.
+One or more certificate filenames may be given.
 
 =item B<-I>
 
@@ -902,7 +902,7 @@ The B<-engine> option was deprecated in OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
-Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/deps/openssl/openssl/doc/man1/openssl-ts.pod.in b/deps/openssl/openssl/doc/man1/openssl-ts.pod.in
index 6f718202024757..3e7f7c4be94b2d 100644
--- a/deps/openssl/openssl/doc/man1/openssl-ts.pod.in
+++ b/deps/openssl/openssl/doc/man1/openssl-ts.pod.in
@@ -490,7 +490,7 @@ Default is no.  (Optional)
 =item B
 
 This option specifies the hash function to be used to calculate the TSA's
-public key certificate identifier. Default is sha256. (Optional)
+public key certificate identifier. Default is sha1. (Optional)
 
 =back
 
@@ -652,7 +652,7 @@ L
 
 =head1 COPYRIGHT
 
-Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/deps/openssl/openssl/doc/man3/BIO_s_mem.pod b/deps/openssl/openssl/doc/man3/BIO_s_mem.pod
index 6b3cc6a2dae943..3bbc3e7fcf02c9 100644
--- a/deps/openssl/openssl/doc/man3/BIO_s_mem.pod
+++ b/deps/openssl/openssl/doc/man3/BIO_s_mem.pod
@@ -59,6 +59,8 @@ positive return value B should be set to a negative value, typically -1.
 
 BIO_get_mem_data() sets *B to a pointer to the start of the memory BIOs data
 and returns the total amount of data available. It is implemented as a macro.
+Note the pointer returned by this call is informative, no transfer of ownership
+of this memory is implied.  See notes on BIO_set_close().
 
 BIO_set_mem_buf() sets the internal BUF_MEM structure to B and sets the
 close flag to B, that is B should be either BIO_CLOSE or BIO_NOCLOSE.
@@ -114,6 +116,10 @@ preceding that write operation cannot be undone.
 Calling BIO_get_mem_ptr() prior to a BIO_reset() call with
 BIO_FLAGS_NONCLEAR_RST set has the same effect as a write operation.
 
+Calling BIO_set_close() with BIO_NOCLOSE orphans the BUF_MEM internal to the
+BIO, _not_ its actual data buffer. See the examples section for the proper
+method for claiming ownership of the data pointer for a deferred free operation.
+
 =head1 BUGS
 
 There should be an option to set the maximum size of a memory BIO.
@@ -151,10 +157,24 @@ Extract the BUF_MEM structure from a memory BIO and then free up the BIO:
  BIO_set_close(mem, BIO_NOCLOSE); /* So BIO_free() leaves BUF_MEM alone */
  BIO_free(mem);
 
+Extract the BUF_MEM ptr, claim ownership of the internal data and free the BIO
+and BUF_MEM structure:
+
+ BUF_MEM *bptr;
+ char *data;
+
+ BIO_get_mem_data(bio, &data);
+ BIO_get_mem_ptr(bio, &bptr);
+ BIO_set_close(mem, BIO_NOCLOSE); /* So BIO_free orphans BUF_MEM */
+ BIO_free(bio);
+ bptr->data = NULL; /* Tell BUF_MEM to orphan data */
+ BUF_MEM_free(bptr);
+ ...
+ free(data);
 
 =head1 COPYRIGHT
 
-Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/deps/openssl/openssl/doc/man3/CMS_add1_signer.pod b/deps/openssl/openssl/doc/man3/CMS_add1_signer.pod
index 800085b7b86a9b..d606a02cc1fd81 100644
--- a/deps/openssl/openssl/doc/man3/CMS_add1_signer.pod
+++ b/deps/openssl/openssl/doc/man3/CMS_add1_signer.pod
@@ -31,8 +31,8 @@ Unless the B flag is set the returned CMS_ContentInfo
 structure is not complete and must be finalized either by streaming (if
 applicable) or a call to CMS_final().
 
-The CMS_SignerInfo_sign() function will explicitly sign a CMS_SignerInfo
-structure, its main use is when B and B flags
+The CMS_SignerInfo_sign() function explicitly signs a CMS_SignerInfo
+structure, its main use is when the B and B flags
 are both set.
 
 =head1 NOTES
@@ -90,6 +90,8 @@ before it is finalized.
 CMS_add1_signer() returns an internal pointer to the CMS_SignerInfo
 structure just added or NULL if an error occurs.
 
+CMS_SignerInfo_sign() returns 1 on success, 0 on failure.
+
 =head1 SEE ALSO
 
 L, L,
@@ -97,7 +99,7 @@ L,
 
 =head1 COPYRIGHT
 
-Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2014-2023 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/deps/openssl/openssl/doc/man3/CMS_sign.pod b/deps/openssl/openssl/doc/man3/CMS_sign.pod
index 0d812756aef551..03bfc6fce16a74 100644
--- a/deps/openssl/openssl/doc/man3/CMS_sign.pod
+++ b/deps/openssl/openssl/doc/man3/CMS_sign.pod
@@ -105,7 +105,7 @@ The function CMS_sign() is a basic CMS signing function whose output will be
 suitable for many purposes. For finer control of the output format the
 B, B and B parameters can all be B and the
 B flag set. Then one or more signers can be added using the
-function CMS_sign_add1_signer(), non default digests can be used and custom
+function CMS_add1_signer(), non default digests can be used and custom
 attributes added. CMS_final() must then be called to finalize the
 structure if streaming is not enabled.
 
@@ -132,7 +132,7 @@ The CMS_sign_ex() method was added in OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
-Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/deps/openssl/openssl/doc/man3/DH_generate_parameters.pod b/deps/openssl/openssl/doc/man3/DH_generate_parameters.pod
index 1098a161ea63f2..9c1dff7aedd9ab 100644
--- a/deps/openssl/openssl/doc/man3/DH_generate_parameters.pod
+++ b/deps/openssl/openssl/doc/man3/DH_generate_parameters.pod
@@ -128,6 +128,10 @@ The parameter B is invalid.
 
 =back
 
+If 0 is returned or B<*codes> is set to a nonzero value the supplied
+parameters should not be used for Diffie-Hellman operations otherwise
+the security properties of the key exchange are not guaranteed.
+
 DH_check_ex(), DH_check_params() and DH_check_pub_key_ex() are similar to
 DH_check() and DH_check_params() respectively, but the error reasons are added
 to the thread's error queue instead of provided as return values from the
@@ -160,7 +164,7 @@ DH_generate_parameters_ex() instead.
 
 =head1 COPYRIGHT
 
-Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/deps/openssl/openssl/doc/man3/DSA_generate_parameters.pod b/deps/openssl/openssl/doc/man3/DSA_generate_parameters.pod
index 415c4c8b82ce74..a10dc9ba275940 100644
--- a/deps/openssl/openssl/doc/man3/DSA_generate_parameters.pod
+++ b/deps/openssl/openssl/doc/man3/DSA_generate_parameters.pod
@@ -51,7 +51,7 @@ called as shown below. For information on the BN_GENCB structure and the
 BN_GENCB_call function discussed below, refer to
 L.
 
-DSA_generate_prime() is similar to DSA_generate_prime_ex() but
+DSA_generate_parameters() is similar to DSA_generate_parameters_ex() but
 expects an old-style callback function; see
 L for information on the old-style callback.
 
@@ -126,7 +126,7 @@ DSA_generate_parameters_ex() instead.
 
 =head1 COPYRIGHT
 
-Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/deps/openssl/openssl/doc/man3/EVP_MAC.pod b/deps/openssl/openssl/doc/man3/EVP_MAC.pod
index 13482ac5e188e7..56ac92a486728e 100644
--- a/deps/openssl/openssl/doc/man3/EVP_MAC.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_MAC.pod
@@ -181,7 +181,7 @@ EVP_MAC_CTX_set_params() passes chosen parameters to the underlying
 context, given a context I.
 The set of parameters given with I determine exactly what
 parameters are passed down.
-If I are NULL, the unterlying context should do nothing and return 1.
+If I are NULL, the underlying context should do nothing and return 1.
 Note that a parameter that is unknown in the underlying context is
 simply ignored.
 Also, what happens when a needed parameter isn't passed down is
@@ -481,7 +481,7 @@ These functions were added in OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
-Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2018-2023 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/deps/openssl/openssl/doc/man3/EVP_SIGNATURE.pod b/deps/openssl/openssl/doc/man3/EVP_SIGNATURE.pod
index 600522085398c2..1f534ef33810eb 100644
--- a/deps/openssl/openssl/doc/man3/EVP_SIGNATURE.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_SIGNATURE.pod
@@ -61,7 +61,7 @@ EVP_SIGNATURE_get0_provider() returns the provider that I was
 fetched from.
 
 EVP_SIGNATURE_do_all_provided() traverses all SIGNATURE implemented by all
-activated roviders in the given library context I, and for each of the
+activated providers in the given library context I, and for each of the
 implementations, calls the given function I with the implementation method
 and the given I as argument.
 
@@ -106,7 +106,7 @@ The functions described here were added in OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
-Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/deps/openssl/openssl/doc/man3/EVP_aes_128_gcm.pod b/deps/openssl/openssl/doc/man3/EVP_aes_128_gcm.pod
index 09cae991295049..485705ea788907 100644
--- a/deps/openssl/openssl/doc/man3/EVP_aes_128_gcm.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_aes_128_gcm.pod
@@ -134,13 +134,7 @@ section for details.
 EVP_aes_192_wrap(),
 EVP_aes_256_wrap(),
 EVP_aes_128_wrap_pad(),
-EVP_aes_128_wrap(),
-EVP_aes_192_wrap(),
-EVP_aes_256_wrap(),
 EVP_aes_192_wrap_pad(),
-EVP_aes_128_wrap(),
-EVP_aes_192_wrap(),
-EVP_aes_256_wrap(),
 EVP_aes_256_wrap_pad()
 
 AES key wrap with 128, 192 and 256 bit keys, as according to RFC 3394 section
@@ -173,7 +167,7 @@ the XTS "tweak" value.
 
 Developers should be aware of the negative performance implications of
 calling these functions multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_aria_128_gcm.pod b/deps/openssl/openssl/doc/man3/EVP_aria_128_gcm.pod
index 92913652630d52..91aa75ec387172 100644
--- a/deps/openssl/openssl/doc/man3/EVP_aria_128_gcm.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_aria_128_gcm.pod
@@ -96,7 +96,7 @@ correctly, see the L section for details.
 
 Developers should be aware of the negative performance implications of
 calling these functions multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_bf_cbc.pod b/deps/openssl/openssl/doc/man3/EVP_bf_cbc.pod
index 4df98f4bdf47ec..11a909207ac954 100644
--- a/deps/openssl/openssl/doc/man3/EVP_bf_cbc.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_bf_cbc.pod
@@ -41,7 +41,7 @@ Blowfish encryption algorithm in CBC, CFB, ECB and OFB modes respectively.
 
 Developers should be aware of the negative performance implications of
 calling these functions multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_blake2b512.pod b/deps/openssl/openssl/doc/man3/EVP_blake2b512.pod
index 98e1899f6a935d..55bd9f3bce77db 100644
--- a/deps/openssl/openssl/doc/man3/EVP_blake2b512.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_blake2b512.pod
@@ -35,7 +35,7 @@ The BLAKE2b algorithm that produces a 512-bit output from a given input.
 
 Developers should be aware of the negative performance implications of
 calling these functions multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 While the BLAKE2b and BLAKE2s algorithms supports a variable length digest,
diff --git a/deps/openssl/openssl/doc/man3/EVP_camellia_128_ecb.pod b/deps/openssl/openssl/doc/man3/EVP_camellia_128_ecb.pod
index a6b597156a77a9..cb6e12e2122b76 100644
--- a/deps/openssl/openssl/doc/man3/EVP_camellia_128_ecb.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_camellia_128_ecb.pod
@@ -79,7 +79,7 @@ Camellia for 128, 192 and 256 bit keys in the following modes: CBC, CFB with
 
 Developers should be aware of the negative performance implications of
 calling these functions multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_cast5_cbc.pod b/deps/openssl/openssl/doc/man3/EVP_cast5_cbc.pod
index 85ff2ad014888f..7fef0598151d85 100644
--- a/deps/openssl/openssl/doc/man3/EVP_cast5_cbc.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_cast5_cbc.pod
@@ -41,7 +41,7 @@ CAST encryption algorithm in CBC, ECB, CFB and OFB modes respectively.
 
 Developers should be aware of the negative performance implications of
 calling these functions multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_chacha20.pod b/deps/openssl/openssl/doc/man3/EVP_chacha20.pod
index 683faa326e1453..7e80c8de40c9ec 100644
--- a/deps/openssl/openssl/doc/man3/EVP_chacha20.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_chacha20.pod
@@ -44,7 +44,7 @@ L section for more information.
 
 Developers should be aware of the negative performance implications of
 calling these functions multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 L
diff --git a/deps/openssl/openssl/doc/man3/EVP_des_cbc.pod b/deps/openssl/openssl/doc/man3/EVP_des_cbc.pod
index 501216cd6d77b3..442be8993a29f7 100644
--- a/deps/openssl/openssl/doc/man3/EVP_des_cbc.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_des_cbc.pod
@@ -89,7 +89,7 @@ Triple-DES key wrap according to RFC 3217 Section 3.
 
 Developers should be aware of the negative performance implications of
 calling these functions multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_desx_cbc.pod b/deps/openssl/openssl/doc/man3/EVP_desx_cbc.pod
index fae827192ee995..c22c0de47900c8 100644
--- a/deps/openssl/openssl/doc/man3/EVP_desx_cbc.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_desx_cbc.pod
@@ -31,7 +31,7 @@ implementation.
 
 Developers should be aware of the negative performance implications of
 calling this function multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_idea_cbc.pod b/deps/openssl/openssl/doc/man3/EVP_idea_cbc.pod
index 5a9adaedc4462c..a36aae0bc999e3 100644
--- a/deps/openssl/openssl/doc/man3/EVP_idea_cbc.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_idea_cbc.pod
@@ -39,7 +39,7 @@ The IDEA encryption algorithm in CBC, CFB, ECB and OFB modes respectively.
 
 Developers should be aware of the negative performance implications of
 calling these functions multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_md2.pod b/deps/openssl/openssl/doc/man3/EVP_md2.pod
index 0b473887e01b97..a6f3a010deb5aa 100644
--- a/deps/openssl/openssl/doc/man3/EVP_md2.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_md2.pod
@@ -28,7 +28,7 @@ The MD2 algorithm which produces a 128-bit output from a given input.
 
 Developers should be aware of the negative performance implications of
 calling this function multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_md4.pod b/deps/openssl/openssl/doc/man3/EVP_md4.pod
index baaff9e4eaa2ac..a4e1a7d0a6e910 100644
--- a/deps/openssl/openssl/doc/man3/EVP_md4.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_md4.pod
@@ -29,7 +29,7 @@ The MD4 algorithm which produces a 128-bit output from a given input.
 
 Developers should be aware of the negative performance implications of
 calling this function multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_md5.pod b/deps/openssl/openssl/doc/man3/EVP_md5.pod
index 752fdd1f6c37b3..42370fb3d0a329 100644
--- a/deps/openssl/openssl/doc/man3/EVP_md5.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_md5.pod
@@ -40,7 +40,7 @@ WARNING: this algorithm is not intended for non-SSL usage.
 
 Developers should be aware of the negative performance implications of
 calling these functions multiple times and should consider using
-L instead.
+L with L or L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_mdc2.pod b/deps/openssl/openssl/doc/man3/EVP_mdc2.pod
index e9de6f3c560a61..3681bd06a63cd9 100644
--- a/deps/openssl/openssl/doc/man3/EVP_mdc2.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_mdc2.pod
@@ -30,7 +30,7 @@ The MDC-2DES algorithm of using MDC-2 with the DES block cipher. It produces a
 
 Developers should be aware of the negative performance implications of
 calling this function multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_rc2_cbc.pod b/deps/openssl/openssl/doc/man3/EVP_rc2_cbc.pod
index bf4a13ba45c19c..17f6f4b3e254da 100644
--- a/deps/openssl/openssl/doc/man3/EVP_rc2_cbc.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_rc2_cbc.pod
@@ -55,7 +55,7 @@ functions to set the key length and effective key length.
 
 Developers should be aware of the negative performance implications of
 calling these functions multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_rc4.pod b/deps/openssl/openssl/doc/man3/EVP_rc4.pod
index f22e88a6521477..0311ef278ca12d 100644
--- a/deps/openssl/openssl/doc/man3/EVP_rc4.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_rc4.pod
@@ -47,7 +47,7 @@ interface.
 
 Developers should be aware of the negative performance implications of
 calling these functions multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_rc5_32_12_16_cbc.pod b/deps/openssl/openssl/doc/man3/EVP_rc5_32_12_16_cbc.pod
index c177b1845196f2..69fc2f2cc656b9 100644
--- a/deps/openssl/openssl/doc/man3/EVP_rc5_32_12_16_cbc.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_rc5_32_12_16_cbc.pod
@@ -60,7 +60,7 @@ is an int.
 
 Developers should be aware of the negative performance implications of
 calling these functions multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_ripemd160.pod b/deps/openssl/openssl/doc/man3/EVP_ripemd160.pod
index 6ad2d3e0186968..5b96fd09f85037 100644
--- a/deps/openssl/openssl/doc/man3/EVP_ripemd160.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_ripemd160.pod
@@ -29,7 +29,7 @@ The RIPEMD-160 algorithm which produces a 160-bit output from a given input.
 
 Developers should be aware of the negative performance implications of
 calling this function multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_seed_cbc.pod b/deps/openssl/openssl/doc/man3/EVP_seed_cbc.pod
index 010607e5740590..2c821d07c3993a 100644
--- a/deps/openssl/openssl/doc/man3/EVP_seed_cbc.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_seed_cbc.pod
@@ -41,7 +41,7 @@ The SEED encryption algorithm in CBC, CFB, ECB and OFB modes respectively.
 
 Developers should be aware of the negative performance implications of
 calling these functions multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_sha1.pod b/deps/openssl/openssl/doc/man3/EVP_sha1.pod
index 264ddd1addb717..6fc8f07b066a6f 100644
--- a/deps/openssl/openssl/doc/man3/EVP_sha1.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_sha1.pod
@@ -29,7 +29,7 @@ The SHA-1 algorithm which produces a 160-bit output from a given input.
 
 Developers should be aware of the negative performance implications of
 calling this function multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_sha224.pod b/deps/openssl/openssl/doc/man3/EVP_sha224.pod
index 7a50cf9b6c3f15..be09e49ee39325 100644
--- a/deps/openssl/openssl/doc/man3/EVP_sha224.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_sha224.pod
@@ -49,7 +49,7 @@ their outputs are of the same size.
 
 Developers should be aware of the negative performance implications of
 calling these functions multiple times and should consider using
-L instead.
+L with Linstead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_sha3_224.pod b/deps/openssl/openssl/doc/man3/EVP_sha3_224.pod
index 5bb9ae1b89e550..93c0d0b9fb1e0f 100644
--- a/deps/openssl/openssl/doc/man3/EVP_sha3_224.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_sha3_224.pod
@@ -54,7 +54,7 @@ B provides that of 256 bits.
 
 Developers should be aware of the negative performance implications of
 calling these functions multiple times and should consider using
-L instead.
+L with L or L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_sm3.pod b/deps/openssl/openssl/doc/man3/EVP_sm3.pod
index 4e8112dc0afee2..65be55e88dba8d 100644
--- a/deps/openssl/openssl/doc/man3/EVP_sm3.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_sm3.pod
@@ -28,7 +28,7 @@ The SM3 hash function.
 
 Developers should be aware of the negative performance implications of
 calling this function multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_sm4_cbc.pod b/deps/openssl/openssl/doc/man3/EVP_sm4_cbc.pod
index b67ade549968c5..48be7a31ad756d 100644
--- a/deps/openssl/openssl/doc/man3/EVP_sm4_cbc.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_sm4_cbc.pod
@@ -45,7 +45,7 @@ respectively.
 
 Developers should be aware of the negative performance implications of
 calling these functions multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/EVP_whirlpool.pod b/deps/openssl/openssl/doc/man3/EVP_whirlpool.pod
index a9826e290a4279..c5d465b16f0c3c 100644
--- a/deps/openssl/openssl/doc/man3/EVP_whirlpool.pod
+++ b/deps/openssl/openssl/doc/man3/EVP_whirlpool.pod
@@ -30,7 +30,7 @@ input.
 
 Developers should be aware of the negative performance implications of
 calling this function multiple times and should consider using
-L instead.
+L with L instead.
 See L for further information.
 
 =head1 RETURN VALUES
diff --git a/deps/openssl/openssl/doc/man3/OSSL_CMP_CTX_new.pod b/deps/openssl/openssl/doc/man3/OSSL_CMP_CTX_new.pod
index e81fb08b00d613..ce7db8f2f08628 100644
--- a/deps/openssl/openssl/doc/man3/OSSL_CMP_CTX_new.pod
+++ b/deps/openssl/openssl/doc/man3/OSSL_CMP_CTX_new.pod
@@ -182,7 +182,7 @@ clearing the internal CMP transaction (aka session) status, PKIStatusInfo,
 and any previous results (newCert, newChain, caPubs, and extraCertsIn)
 from the last executed transaction.
 It also clears any ITAVs that were added by OSSL_CMP_CTX_push0_genm_ITAV().
-All other field values (i.e., CMP options) are retained for potential re-use.
+All other field values (i.e., CMP options) are retained for potential reuse.
 
 OSSL_CMP_CTX_set_option() sets the given value for the given option
 (e.g., OSSL_CMP_OPT_IMPLICIT_CONFIRM) in the given OSSL_CMP_CTX structure.
@@ -260,12 +260,12 @@ The following options can be set:
 
 =item B
         The NID of the digest algorithm to be used as one-way function (OWF)
-        in RFC 4210's MSG_MAC_ALG for PBM-based message protection.
+        for MAC-based message protection with password-based MAC (PBM).
+        See RFC 4210 section 5.1.3.1 for details.
         Default is SHA256.
 
 =item B
-        The NID of the MAC algorithm to be used in RFC 4210's MSG_MAC_ALG
-        for PBM-based message protection.
+        The NID of the MAC algorithm to be used for message protection with PBM.
         Default is HMAC-SHA1 as per RFC 4210.
 
 =item B
@@ -450,8 +450,8 @@ The reference counts of those certificates handled successfully are increased.
 OSSL_CMP_CTX_get0_untrusted(OSSL_CMP_CTX *ctx) returns a pointer to the
 list of untrusted certs, which may be empty if unset.
 
-OSSL_CMP_CTX_set1_cert() sets the CMP signer certificate
-related to the private key used for CMP message protection.
+OSSL_CMP_CTX_set1_cert() sets the CMP signer certificate, also called protection
+certificate, related to the private key for signature-based message protection.
 Therefore the public key of this I must correspond to
 the private key set before or thereafter via OSSL_CMP_CTX_set1_pkey().
 When using signature-based protection of CMP request messages
@@ -481,15 +481,15 @@ OSSL_CMP_CTX_set1_pkey() sets the client's private key corresponding to the
 CMP signer certificate set via OSSL_CMP_CTX_set1_cert().
 This key is used create signature-based protection (protectionAlg = MSG_SIG_ALG)
 of outgoing messages
-unless a PBM secret has been set via OSSL_CMP_CTX_set1_secretValue().
+unless a symmetric secret has been set via OSSL_CMP_CTX_set1_secretValue().
 The I argument may be NULL to clear the entry.
 
-OSSL_CMP_CTX_set1_secretValue() sets the byte string I with length I
-as PBM secret in the given I or clears it if the I argument is NULL.
-If present, this secret is used to create PBM-based protection of outgoing
-messages and to verify any PBM-based protection of incoming messages
-(protectionAlg = MSG_MAC_ALG). PBM stands for Password-Based MAC.
-PBM-based protection takes precedence over signature-based protection.
+OSSL_CMP_CTX_set1_secretValue() sets in I the byte string I of length
+I to use as pre-shared secret, or clears it if the I argument is NULL.
+If present, this secret is used to create MAC-based authentication and integrity
+protection (rather than applying signature-based protection)
+of outgoing messages and to verify authenticity and integrity of incoming
+messages that have MAC-based protection (protectionAlg = C).
 
 OSSL_CMP_CTX_set1_referenceValue() sets the given referenceValue I with
 length I in the given I or clears it if the I argument is NULL.
@@ -500,7 +500,7 @@ then the sender field will contain the NULL-DN
 and the senderKID field of the CMP message header must be set.
 When signature-based protection is used the senderKID will be set to
 the subjectKeyIdentifier of the CMP signer certificate as far as present.
-If not present or when PBM-based protection is used
+If not present or when MAC-based protection is used
 the I value is taken as the fallback value for the senderKID.
 
 OSSL_CMP_CTX_set1_recipient() sets the recipient name that will be used in the
@@ -731,7 +731,7 @@ Set up a CMP client context for sending requests and verifying responses:
     OSSL_CMP_CTX_set1_serverPath(cmp_ctx, path_or_alias);
     OSSL_CMP_CTX_set0_trustedStore(cmp_ctx, ts);
 
-Set up client credentials for password-based protection (PBM):
+Set up symmetric credentials for MAC-based message protection such as PBM:
 
     OSSL_CMP_CTX_set1_referenceValue(cmp_ctx, ref, ref_len);
     OSSL_CMP_CTX_set1_secretValue(cmp_ctx, sec, sec_len);
diff --git a/deps/openssl/openssl/doc/man3/OSSL_CMP_exec_certreq.pod b/deps/openssl/openssl/doc/man3/OSSL_CMP_exec_certreq.pod
index b0d81c7c41a968..0cabc3bad5ac96 100644
--- a/deps/openssl/openssl/doc/man3/OSSL_CMP_exec_certreq.pod
+++ b/deps/openssl/openssl/doc/man3/OSSL_CMP_exec_certreq.pod
@@ -42,7 +42,7 @@ client-server transactions, i.e., sequences of CMP requests and responses.
 
 All functions take a populated OSSL_CMP_CTX structure as their first argument.
 Usually the server name, port, and path ("CMP alias") need to be set, as well as
-credentials the client can use for authenticating itself to the client.
+credentials the client can use for authenticating itself to the server.
 In order to authenticate the server the client typically needs a trust store.
 The functions return their respective main results directly, while there are
 also accessor functions for retrieving various results and status information
@@ -72,7 +72,7 @@ and need to be filled in using L,
 L, L, etc.
 For P10CR, L needs to be used instead.
 The enrollment session may be blocked by sleeping until the addressed
-CA (or an intermedate PKI component) can fully process and answer the request.
+CA (or an intermediate PKI component) can fully process and answer the request.
 
 OSSL_CMP_try_certreq() is an alternative to the above functions that is
 more flexible regarding what to do after receiving a checkAfter value.
@@ -119,9 +119,17 @@ See RFC 4210 section 5.3.19 and appendix E.5 for details.
 
 CMP is defined in RFC 4210 (and CRMF in RFC 4211).
 
-So far the CMP client implementation is limited to one request per CMP message
+The CMP client implementation is limited to one request per CMP message
 (and consequently to at most one response component per CMP message).
 
+When a client obtains from a CMP server CA certificates that it is going to
+trust, for instance via the caPubs field of a certificate response,
+authentication of the CMP server is particularly critical.
+So special care must be taken setting up server authentication in I
+using functions such as
+L (for certificate-based authentication) or
+L (for MAC-based protection).
+
 =head1 RETURN VALUES
 
 OSSL_CMP_exec_certreq(), OSSL_CMP_exec_IR_ses(), OSSL_CMP_exec_CR_ses(),
@@ -163,7 +171,7 @@ The OpenSSL CMP support was added in OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
-Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/deps/openssl/openssl/doc/man3/OSSL_HTTP_REQ_CTX.pod b/deps/openssl/openssl/doc/man3/OSSL_HTTP_REQ_CTX.pod
index ee61034aa731a7..6216420e4ffe92 100644
--- a/deps/openssl/openssl/doc/man3/OSSL_HTTP_REQ_CTX.pod
+++ b/deps/openssl/openssl/doc/man3/OSSL_HTTP_REQ_CTX.pod
@@ -72,12 +72,16 @@ which collects the HTTP request header lines.
 OSSL_HTTP_REQ_CTX_free() frees up the HTTP request context I.
 The I is not free'd, I will be free'd if I is set.
 
-OSSL_HTTP_REQ_CTX_set_request_line() adds the HTTP request line to the context.
+OSSL_HTTP_REQ_CTX_set_request_line() adds the 1st HTTP request line to I.
 The HTTP method is determined by I,
 which should be 1 to indicate C or 0 to indicate C.
-I and I may be set to indicate a proxy server and port
-that the request should go through, otherwise they should be left NULL.
-I is the HTTP request path; if left NULL, C is used.
+I and I may be set to give the server and the optional port that
+an HTTP proxy shall forward the request to, otherwise they must be left NULL.
+I provides the HTTP request path; if left NULL, C is used.
+For backward compatibility, I may begin with C and thus convey
+an absoluteURI. In this case it indicates HTTP proxy use and provides also the
+server (and optionally the port) that the proxy shall forward the request to.
+In this case the I and I arguments must be NULL.
 
 OSSL_HTTP_REQ_CTX_add1_header() adds header I with value I to the
 context I. It can be called more than once to add multiple header lines.
diff --git a/deps/openssl/openssl/doc/man3/OSSL_HTTP_transfer.pod b/deps/openssl/openssl/doc/man3/OSSL_HTTP_transfer.pod
index 3337f6d4a35e51..716e365ef50db0 100644
--- a/deps/openssl/openssl/doc/man3/OSSL_HTTP_transfer.pod
+++ b/deps/openssl/openssl/doc/man3/OSSL_HTTP_transfer.pod
@@ -161,8 +161,11 @@ NULL) to print additional diagnostic information in a user-oriented way.
 
 OSSL_HTTP_set1_request() sets up in I the request header and content data
 and expectations on the response using the following parameters.
-If  indicates using a proxy for HTTP (but not HTTPS), the server hostname
-(and optionally port) needs to be placed in the header and thus must be present.
+If  indicates using a proxy for HTTP (but not HTTPS), the server host
+(and optionally port) needs to be placed in the header; thus it must be present
+in I.
+For backward compatibility, the server (and optional port) may also be given in
+the I argument beginning with C (thus giving an absoluteURI).
 If I is NULL it defaults to "/".
 If I is NULL the HTTP GET method will be used to send the request
 else HTTP POST with the contents of I and optional I, where
@@ -274,7 +277,7 @@ All the functions described here were added in OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
-Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/deps/openssl/openssl/doc/man3/PKCS12_create.pod b/deps/openssl/openssl/doc/man3/PKCS12_create.pod
index dc0f06d9d323c7..92e588062a36ed 100644
--- a/deps/openssl/openssl/doc/man3/PKCS12_create.pod
+++ b/deps/openssl/openssl/doc/man3/PKCS12_create.pod
@@ -42,7 +42,8 @@ can all be set to zero and sensible defaults will be used.
 These defaults are: AES password based encryption (PBES2 with PBKDF2 and
 AES-256-CBC) for private keys and certificates, the PBKDF2 and MAC key
 derivation iteration count of B (currently 2048), and
-MAC algorithm HMAC with SHA2-256.
+MAC algorithm HMAC with SHA2-256. The MAC key derivation algorithm used
+for the outer PKCS#12 structure is PKCS12KDF.
 
 The default MAC iteration count is 1 in order to retain compatibility with
 old software which did not interpret MAC iteration counts. If such compatibility
@@ -68,6 +69,8 @@ I or I can be set to -1 indicating that no encryption
 should be used.
 
 I can be set to -1 and the MAC will then be omitted entirely.
+This can be useful when running with the FIPS provider as the PKCS12KDF
+is not a FIPS approvable algorithm.
 
 PKCS12_create() makes assumptions regarding the encoding of the given pass
 phrase.
@@ -83,7 +86,9 @@ IETF RFC 7292 (L)
 
 =head1 SEE ALSO
 
+L,
 L,
+L,
 L
 
 =head1 HISTORY
@@ -96,7 +101,7 @@ standards.
 
 =head1 COPYRIGHT
 
-Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2023 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/deps/openssl/openssl/doc/man3/PKCS12_gen_mac.pod b/deps/openssl/openssl/doc/man3/PKCS12_gen_mac.pod
index 37bcd572d841ce..a72df145fedd70 100644
--- a/deps/openssl/openssl/doc/man3/PKCS12_gen_mac.pod
+++ b/deps/openssl/openssl/doc/man3/PKCS12_gen_mac.pod
@@ -22,6 +22,7 @@ PKCS12_verify_mac - Functions to create and manipulate a PKCS#12 structure
 
 PKCS12_gen_mac() generates an HMAC over the entire PKCS#12 object using the
 supplied password along with a set of already configured parameters.
+The default key generation mechanism used is PKCS12KDF.
 
 PKCS12_verify_mac() verifies the PKCS#12 object's HMAC using the supplied
 password.
@@ -57,6 +58,7 @@ IETF RFC 7292 (L)
 =head1 SEE ALSO
 
 L,
+L,
 L,
 L
 
diff --git a/deps/openssl/openssl/doc/man3/PKCS5_PBKDF2_HMAC.pod b/deps/openssl/openssl/doc/man3/PKCS5_PBKDF2_HMAC.pod
index 0984e993daefa5..8b5feff9192c02 100644
--- a/deps/openssl/openssl/doc/man3/PKCS5_PBKDF2_HMAC.pod
+++ b/deps/openssl/openssl/doc/man3/PKCS5_PBKDF2_HMAC.pod
@@ -33,7 +33,8 @@ be NULL terminated.
 
 B is the iteration count and its value should be greater than or
 equal to 1. RFC 2898 suggests an iteration count of at least 1000. Any
-B less than 1 is treated as a single iteration.
+B value less than 1 is invalid; such values will result in failure
+and raise the PROV_R_INVALID_ITERATION_COUNT error.
 
 B is the message digest function used in the derivation.
 PKCS5_PBKDF2_HMAC_SHA1() calls PKCS5_PBKDF2_HMAC() with EVP_sha1().
@@ -66,7 +67,7 @@ L
 
 =head1 COPYRIGHT
 
-Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2014-2023 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/deps/openssl/openssl/doc/man3/SSL_CONF_CTX_set_ssl_ctx.pod b/deps/openssl/openssl/doc/man3/SSL_CONF_CTX_set_ssl_ctx.pod
index 06cc1e4ec539d2..3913ea9390079d 100644
--- a/deps/openssl/openssl/doc/man3/SSL_CONF_CTX_set_ssl_ctx.pod
+++ b/deps/openssl/openssl/doc/man3/SSL_CONF_CTX_set_ssl_ctx.pod
@@ -2,6 +2,7 @@
 
 =head1 NAME
 
+SSL_CONF_CTX_finish,
 SSL_CONF_CTX_set_ssl_ctx, SSL_CONF_CTX_set_ssl - set context to configure
 
 =head1 SYNOPSIS
@@ -10,6 +11,7 @@ SSL_CONF_CTX_set_ssl_ctx, SSL_CONF_CTX_set_ssl - set context to configure
 
  void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx);
  void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl);
+ int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx);
 
 =head1 DESCRIPTION
 
@@ -23,6 +25,10 @@ B structure B. Any previous B or B associated with
 B is cleared. Subsequent calls to SSL_CONF_cmd() will be sent to
 B.
 
+The function SSL_CONF_CTX_finish() must be called after all configuration
+operations have been completed. It is used to finalise any operations
+or to process defaults.
+
 =head1 NOTES
 
 The context need not be set or it can be set to B in which case only
@@ -32,6 +38,8 @@ syntax checking of commands is performed, where possible.
 
 SSL_CONF_CTX_set_ssl_ctx() and SSL_CTX_set_ssl() do not return a value.
 
+SSL_CONF_CTX_finish() returns 1 for success and 0 for failure.
+
 =head1 SEE ALSO
 
 L,
@@ -47,7 +55,7 @@ These functions were added in OpenSSL 1.0.2.
 
 =head1 COPYRIGHT
 
-Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2012-2023 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/deps/openssl/openssl/doc/man3/SSL_CTX_set_info_callback.pod b/deps/openssl/openssl/doc/man3/SSL_CTX_set_info_callback.pod
index 9cee6420738486..c1c6a67f85a7d7 100644
--- a/deps/openssl/openssl/doc/man3/SSL_CTX_set_info_callback.pod
+++ b/deps/openssl/openssl/doc/man3/SSL_CTX_set_info_callback.pod
@@ -12,11 +12,15 @@ SSL_get_info_callback
 
  #include 
 
- void SSL_CTX_set_info_callback(SSL_CTX *ctx, void (*callback)());
- void (*SSL_CTX_get_info_callback(const SSL_CTX *ctx))();
+ void SSL_CTX_set_info_callback(SSL_CTX *ctx,
+                                void (*callback) (const SSL *ssl, int type, int val));
 
- void SSL_set_info_callback(SSL *ssl, void (*callback)());
- void (*SSL_get_info_callback(const SSL *ssl))();
+ void (*SSL_CTX_get_info_callback(SSL_CTX *ctx)) (const SSL *ssl, int type, int val);
+
+ void SSL_set_info_callback(SSL *ssl,
+                            void (*callback) (const SSL *ssl, int type, int val));
+
+ void (*SSL_get_info_callback(const SSL *ssl)) (const SSL *ssl, int type, int val);
 
 =head1 DESCRIPTION
 
@@ -119,7 +123,7 @@ SSL_get_info_callback() returns the current setting.
 The following example callback function prints state strings, information
 about alerts being handled and error messages to the B BIO.
 
- void apps_ssl_info_callback(SSL *s, int where, int ret)
+ void apps_ssl_info_callback(const SSL *s, int where, int ret)
  {
      const char *str;
      int w = where & ~SSL_ST_MASK;
@@ -156,7 +160,7 @@ L
 
 =head1 COPYRIGHT
 
-Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2001-2023 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/deps/openssl/openssl/doc/man3/SSL_new.pod b/deps/openssl/openssl/doc/man3/SSL_new.pod
index 59d275523f98e7..2b522769169b77 100644
--- a/deps/openssl/openssl/doc/man3/SSL_new.pod
+++ b/deps/openssl/openssl/doc/man3/SSL_new.pod
@@ -35,7 +35,7 @@ MUST NOT have yet started the SSL handshake.  For connections that are not in
 their initial state SSL_dup() just increments an internal
 reference count and returns the I handle.  It may be possible to
 use L to recycle an SSL handle that is not in its initial
-state for re-use, but this is best avoided.  Instead, save and restore
+state for reuse, but this is best avoided.  Instead, save and restore
 the session, if desired, and construct a fresh handle for each connection.
 
 The subset of settings in I that are duplicated are:
@@ -124,7 +124,7 @@ L
 
 =head1 COPYRIGHT
 
-Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/deps/openssl/openssl/doc/man3/d2i_PKCS8PrivateKey_bio.pod b/deps/openssl/openssl/doc/man3/d2i_PKCS8PrivateKey_bio.pod
index 5b5371b70f19cd..51d8aa8cfb474d 100644
--- a/deps/openssl/openssl/doc/man3/d2i_PKCS8PrivateKey_bio.pod
+++ b/deps/openssl/openssl/doc/man3/d2i_PKCS8PrivateKey_bio.pod
@@ -8,7 +8,7 @@ i2d_PKCS8PrivateKey_nid_bio, i2d_PKCS8PrivateKey_nid_fp - PKCS#8 format private
 
 =head1 SYNOPSIS
 
- #include 
+ #include 
 
  EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u);
  EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u);
@@ -64,7 +64,7 @@ L
 
 =head1 COPYRIGHT
 
-Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2023 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/deps/openssl/openssl/doc/man3/d2i_RSAPrivateKey.pod b/deps/openssl/openssl/doc/man3/d2i_RSAPrivateKey.pod
index b4f5b466090004..08cd2c85e5bd79 100644
--- a/deps/openssl/openssl/doc/man3/d2i_RSAPrivateKey.pod
+++ b/deps/openssl/openssl/doc/man3/d2i_RSAPrivateKey.pod
@@ -28,7 +28,6 @@ d2i_RSA_PUBKEY_fp,
 d2i_DHparams,
 d2i_DHparams_bio,
 d2i_DHparams_fp,
-d2i_ECPKParameters,
 d2i_ECParameters,
 d2i_ECPrivateKey,
 d2i_ECPrivateKey_bio,
@@ -56,7 +55,6 @@ i2d_DSA_PUBKEY,
 i2d_DSA_PUBKEY_bio,
 i2d_DSA_PUBKEY_fp,
 i2d_DSAparams,
-i2d_ECPKParameters,
 i2d_ECParameters,
 i2d_ECPrivateKey,
 i2d_ECPrivateKey_bio,
@@ -205,7 +203,7 @@ I and I as follows:
 
 =item BPrivateKey>() translates into:
 
- int selection = EVP_PKEY_PRIVATE_KEY;
+ int selection = EVP_PKEY_KEYPAIR;
  const char *structure = "type-specific";
 
 =item BPublicKey>() translates into:
@@ -309,7 +307,7 @@ L
 
 =head1 COPYRIGHT
 
-Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/deps/openssl/openssl/doc/man3/d2i_X509.pod b/deps/openssl/openssl/doc/man3/d2i_X509.pod
index c79a964e6d7f98..00efb603581661 100644
--- a/deps/openssl/openssl/doc/man3/d2i_X509.pod
+++ b/deps/openssl/openssl/doc/man3/d2i_X509.pod
@@ -53,6 +53,7 @@ d2i_DIST_POINT,
 d2i_DIST_POINT_NAME,
 d2i_DSA_SIG,
 d2i_ECDSA_SIG,
+d2i_ECPKParameters,
 d2i_EDIPARTYNAME,
 d2i_ESS_CERT_ID,
 d2i_ESS_CERT_ID_V2,
@@ -223,6 +224,7 @@ i2d_DIST_POINT,
 i2d_DIST_POINT_NAME,
 i2d_DSA_SIG,
 i2d_ECDSA_SIG,
+i2d_ECPKParameters,
 i2d_EDIPARTYNAME,
 i2d_ESS_CERT_ID,
 i2d_ESS_CERT_ID_V2,
@@ -388,10 +390,12 @@ to the returned structure is also written to I<*a>.  If an error occurred
 then NULL is returned.
 
 On a successful return, if I<*a> is not NULL then it is assumed that I<*a>
-contains a valid B> structure and an attempt is made to reuse it. This
-"reuse" capability is present for historical compatibility but its use is
-B (see BUGS below, and the discussion in the RETURN
-VALUES section).
+contains a valid B> structure and an attempt is made to reuse it.
+For B> structures where it matters it is possible to set up a library
+context on the decoded structure this way (see the B section).
+However using the "reuse" capability for other purposes is B (see B below, and the discussion in the B
+section).
 
 B_bio>() is similar to B>() except it attempts
 to parse data from BIO I.
@@ -536,6 +540,22 @@ Alternative technique:
  if (d2i_X509(&x, &p, len) == NULL)
      /* error */
 
+Setting up a library context and property query:
+
+ X509 *x;
+ unsigned char *buf;
+ const unsigned char *p;
+ int len;
+ OSSL_LIB_CTX *libctx = ....;
+ const char *propq = ....;
+
+ /* Set up buf and len to point to the input buffer. */
+ p = buf;
+ x = X509_new_ex(libctx, propq);
+
+ if (d2i_X509(&x, &p, len) == NULL)
+     /* error, x was freed and NULL assigned to it (see RETURN VALUES) */
+
 =head1 WARNINGS
 
 Using a temporary variable is mandatory. A common
diff --git a/deps/openssl/openssl/doc/man5/x509v3_config.pod b/deps/openssl/openssl/doc/man5/x509v3_config.pod
index 1830092394bc90..044904022d894e 100644
--- a/deps/openssl/openssl/doc/man5/x509v3_config.pod
+++ b/deps/openssl/openssl/doc/man5/x509v3_config.pod
@@ -93,7 +93,7 @@ numeric identifier, as shown here:
  email.2 = steve@example.org
 
 The syntax of raw extensions is defined by the source code that parses
-the extension but should be documened.
+the extension but should be documented.
 See L for an example of a raw extension.
 
 If an extension type is unsupported, then the I extension syntax
@@ -590,7 +590,7 @@ L
 
 =head1 COPYRIGHT
 
-Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2004-2023 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/deps/openssl/openssl/doc/man7/EVP_KDF-PKCS12KDF.pod b/deps/openssl/openssl/doc/man7/EVP_KDF-PKCS12KDF.pod
index 7edde1dc9bf7f0..98653656986427 100644
--- a/deps/openssl/openssl/doc/man7/EVP_KDF-PKCS12KDF.pod
+++ b/deps/openssl/openssl/doc/man7/EVP_KDF-PKCS12KDF.pod
@@ -46,6 +46,9 @@ RFC 7292 section B.3.
 
 =head1 NOTES
 
+This algorithm is not available in the FIPS provider as it is not FIPS
+approvable.
+
 A typical application of this algorithm is to derive keying material for an
 encryption algorithm from a password in the "pass", a salt in "salt",
 and an iteration count.
@@ -68,7 +71,8 @@ L,
 L,
 L,
 L,
-L
+L,
+L
 
 =head1 HISTORY
 
@@ -76,7 +80,7 @@ This functionality was added in OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
-Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/deps/openssl/openssl/doc/man7/migration_guide.pod b/deps/openssl/openssl/doc/man7/migration_guide.pod
index 1847e9813cbbaf..61641324a7fc9d 100644
--- a/deps/openssl/openssl/doc/man7/migration_guide.pod
+++ b/deps/openssl/openssl/doc/man7/migration_guide.pod
@@ -306,6 +306,15 @@ context and property query and will call an extended version of the key/IV
 derivation function which supports these parameters. This includes
 L, L and L.
 
+=head4 PKCS#12 KDF versus FIPS
+
+Unlike in 1.x.y, the PKCS12KDF algorithm used when a PKCS#12 structure
+is created with a MAC that does not work with the FIPS provider as the PKCS12KDF
+is not a FIPS approvable mechanism.
+
+See L, L, L,
+L.
+
 =head4 Windows thread synchronization changes
 
 Windows thread synchronization uses read/write primitives (SRWLock) when
diff --git a/deps/openssl/openssl/fuzz/build.info b/deps/openssl/openssl/fuzz/build.info
index 7b26b8c15228f8..dc976b70f06796 100644
--- a/deps/openssl/openssl/fuzz/build.info
+++ b/deps/openssl/openssl/fuzz/build.info
@@ -9,7 +9,7 @@
 -}
 
 IF[{- !$disabled{"fuzz-afl"} || !$disabled{"fuzz-libfuzzer"} -}]
-  PROGRAMS{noinst}=asn1 asn1parse bignum bndiv client conf crl server x509
+  PROGRAMS{noinst}=asn1 asn1parse bignum bndiv client conf crl server
 
   IF[{- !$disabled{"cmp"} -}]
     PROGRAMS{noinst}=cmp
@@ -23,6 +23,10 @@ IF[{- !$disabled{"fuzz-afl"} || !$disabled{"fuzz-libfuzzer"} -}]
     PROGRAMS{noinst}=ct
   ENDIF
 
+  IF[{- !$disabled{"ocsp"} -}]
+    PROGRAMS{noinst}=x509
+  ENDIF
+
   SOURCE[asn1]=asn1.c driver.c fuzz_rand.c
   INCLUDE[asn1]=../include {- $ex_inc -}
   DEPEND[asn1]=../libcrypto ../libssl {- $ex_lib -}
@@ -73,7 +77,7 @@ IF[{- !$disabled{"fuzz-afl"} || !$disabled{"fuzz-libfuzzer"} -}]
 ENDIF
 
 IF[{- !$disabled{tests} -}]
-  PROGRAMS{noinst}=asn1-test asn1parse-test bignum-test bndiv-test client-test conf-test crl-test server-test x509-test
+  PROGRAMS{noinst}=asn1-test asn1parse-test bignum-test bndiv-test client-test conf-test crl-test server-test
 
   IF[{- !$disabled{"cmp"} -}]
     PROGRAMS{noinst}=cmp-test
@@ -87,6 +91,10 @@ IF[{- !$disabled{tests} -}]
     PROGRAMS{noinst}=ct-test
   ENDIF
 
+  IF[{- !$disabled{"ocsp"} -}]
+    PROGRAMS{noinst}=x509-test
+  ENDIF
+
   SOURCE[asn1-test]=asn1.c test-corpus.c fuzz_rand.c
   INCLUDE[asn1-test]=../include
   DEPEND[asn1-test]=../libcrypto ../libssl
diff --git a/deps/openssl/openssl/fuzz/x509.c b/deps/openssl/openssl/fuzz/x509.c
index 78061d176af792..e2d2639164c01d 100644
--- a/deps/openssl/openssl/fuzz/x509.c
+++ b/deps/openssl/openssl/fuzz/x509.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -9,6 +9,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -17,31 +18,131 @@
 int FuzzerInitialize(int *argc, char ***argv)
 {
     FuzzerSetRand();
-    OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
+    OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS
+       | OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
     ERR_clear_error();
     CRYPTO_free_ex_index(0, -1);
     return 1;
 }
 
+static int cb(int ok, X509_STORE_CTX *ctx)
+{
+    return 1;
+}
+
 int FuzzerTestOneInput(const uint8_t *buf, size_t len)
 {
     const unsigned char *p = buf;
+    size_t orig_len = len;
     unsigned char *der = NULL;
+    BIO *bio = NULL;
+    X509 *x509_1 = NULL, *x509_2 = NULL;
+    X509_STORE *store = NULL;
+    X509_VERIFY_PARAM *param = NULL;
+    X509_STORE_CTX *ctx = NULL;
+    X509_CRL *crl = NULL;
+    STACK_OF(X509_CRL) *crls = NULL;
+    STACK_OF(X509) *certs = NULL;
+    OCSP_RESPONSE *resp = NULL;
+    OCSP_BASICRESP *bs = NULL;
+    OCSP_CERTID *id = NULL;
+
+    x509_1 = d2i_X509(NULL, &p, len);
+    if (x509_1 == NULL)
+        goto err;
+
+    bio = BIO_new(BIO_s_null());
+    if (bio == NULL)
+        goto err;
+
+    /* This will load and print the public key as well as extensions */
+    X509_print(bio, x509_1);
+    BIO_free(bio);
+
+    X509_issuer_and_serial_hash(x509_1);
+
+    i2d_X509(x509_1, &der);
+    OPENSSL_free(der);
+
+    len = orig_len - (p - buf);
+    x509_2 = d2i_X509(NULL, &p, len);
+    if (x509_2 == NULL)
+        goto err;
+
+    len = orig_len - (p - buf);
+    crl = d2i_X509_CRL(NULL, &p, len);
+    if (crl == NULL)
+        goto err;
+
+    len = orig_len - (p - buf);
+    resp = d2i_OCSP_RESPONSE(NULL, &p, len);
+
+    store = X509_STORE_new();
+    X509_STORE_add_cert(store, x509_2);
 
-    X509 *x509 = d2i_X509(NULL, &p, len);
-    if (x509 != NULL) {
-        BIO *bio = BIO_new(BIO_s_null());
-        /* This will load and print the public key as well as extensions */
-        X509_print(bio, x509);
-        BIO_free(bio);
+    param = X509_VERIFY_PARAM_new();
+    X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_NO_CHECK_TIME);
+    X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_X509_STRICT);
+    X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_PARTIAL_CHAIN);
+    X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
 
-        X509_issuer_and_serial_hash(x509);
+    X509_STORE_set1_param(store, param);
 
-        i2d_X509(x509, &der);
-        OPENSSL_free(der);
+    X509_STORE_set_verify_cb(store, cb);
 
-        X509_free(x509);
+    ctx = X509_STORE_CTX_new();
+    if (ctx == NULL)
+        goto err;
+
+    X509_STORE_CTX_init(ctx, store, x509_1, NULL);
+
+    if (crl != NULL) {
+        crls = sk_X509_CRL_new_null();
+        if (crls == NULL)
+            goto err;
+
+        sk_X509_CRL_push(crls, crl);
+        X509_STORE_CTX_set0_crls(ctx, crls);
     }
+
+    X509_verify_cert(ctx);
+
+    if (resp != NULL)
+        bs = OCSP_response_get1_basic(resp);
+
+    if (bs != NULL) {
+        int status, reason;
+        ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd;
+
+        certs = sk_X509_new_null();
+        if (certs == NULL)
+            goto err;
+
+        sk_X509_push(certs, x509_1);
+        sk_X509_push(certs, x509_2);
+
+        OCSP_basic_verify(bs, certs, store, OCSP_PARTIAL_CHAIN);
+
+        id = OCSP_cert_to_id(NULL, x509_1, x509_2);
+        if (id == NULL)
+            goto err;
+        OCSP_resp_find_status(bs, id, &status, &reason, &revtime, &thisupd,
+                              &nextupd);
+    }
+
+err:
+    X509_STORE_CTX_free(ctx);
+    X509_VERIFY_PARAM_free(param);
+    X509_STORE_free(store);
+    X509_free(x509_1);
+    X509_free(x509_2);
+    X509_CRL_free(crl);
+    OCSP_CERTID_free(id);
+    OCSP_BASICRESP_free(bs);
+    OCSP_RESPONSE_free(resp);
+    sk_X509_CRL_free(crls);
+    sk_X509_free(certs);
+
     ERR_clear_error();
     return 0;
 }
diff --git a/deps/openssl/openssl/include/openssl/cmserr.h b/deps/openssl/openssl/include/openssl/cmserr.h
index d48c2a4ab89f03..f2d7708f10c8d6 100644
--- a/deps/openssl/openssl/include/openssl/cmserr.h
+++ b/deps/openssl/openssl/include/openssl/cmserr.h
@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -113,6 +113,7 @@
 #  define CMS_R_UNSUPPORTED_LABEL_SOURCE                   193
 #  define CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE             155
 #  define CMS_R_UNSUPPORTED_RECIPIENT_TYPE                 154
+#  define CMS_R_UNSUPPORTED_SIGNATURE_ALGORITHM            195
 #  define CMS_R_UNSUPPORTED_TYPE                           156
 #  define CMS_R_UNWRAP_ERROR                               157
 #  define CMS_R_UNWRAP_FAILURE                             180
diff --git a/deps/openssl/openssl/include/openssl/evp.h b/deps/openssl/openssl/include/openssl/evp.h
index 49e8e1df786516..e64072f9656263 100644
--- a/deps/openssl/openssl/include/openssl/evp.h
+++ b/deps/openssl/openssl/include/openssl/evp.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -85,6 +85,8 @@
 /* Easy to use macros for EVP_PKEY related selections */
 # define EVP_PKEY_KEY_PARAMETERS                                            \
     ( OSSL_KEYMGMT_SELECT_ALL_PARAMETERS )
+# define EVP_PKEY_PRIVATE_KEY                                               \
+    ( EVP_PKEY_KEY_PARAMETERS | OSSL_KEYMGMT_SELECT_PRIVATE_KEY )
 # define EVP_PKEY_PUBLIC_KEY                                                \
     ( EVP_PKEY_KEY_PARAMETERS | OSSL_KEYMGMT_SELECT_PUBLIC_KEY )
 # define EVP_PKEY_KEYPAIR                                                   \
diff --git a/deps/openssl/openssl/include/openssl/pkcs7.h.in b/deps/openssl/openssl/include/openssl/pkcs7.h.in
index f5c55a3fbe5761..006b38b604110b 100644
--- a/deps/openssl/openssl/include/openssl/pkcs7.h.in
+++ b/deps/openssl/openssl/include/openssl/pkcs7.h.in
@@ -1,7 +1,7 @@
 /*
  * {- join("\n * ", @autowarntext) -}
  *
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -57,8 +57,8 @@ typedef struct pkcs7_signer_info_st {
     PKCS7_ISSUER_AND_SERIAL *issuer_and_serial;
     X509_ALGOR *digest_alg;
     STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */
-    X509_ALGOR *digest_enc_alg;
-    ASN1_OCTET_STRING *enc_digest;
+    X509_ALGOR *digest_enc_alg; /* confusing name, actually used for signing */
+    ASN1_OCTET_STRING *enc_digest; /* confusing name, actually signature */
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
diff --git a/deps/openssl/openssl/providers/fips-sources.checksums b/deps/openssl/openssl/providers/fips-sources.checksums
index 42785c33a0d2e0..fa977f5a983829 100644
--- a/deps/openssl/openssl/providers/fips-sources.checksums
+++ b/deps/openssl/openssl/providers/fips-sources.checksums
@@ -21,7 +21,7 @@ c56c324667b67d726e040d70379efba5b270e2937f403c1b5979018b836903c7  crypto/aes/asm
 c7c6694480bb5319690f94826139a93f5c460ebea6dba101b520a76cb956ec93  crypto/aes/asm/aesni-x86_64.pl
 f3a8f3c960c0f47aaa8fc2633d18b14e7c7feeccc536b0115a08bc58333122b6  crypto/aes/asm/aesp8-ppc.pl
 e397a5781893e97dd90a5a52049633be12a43f379ec5751bca2a6350c39444c8  crypto/aes/asm/aest4-sparcv9.pl
-a097f9d71de7cefa8e93629033ff1986fb01128623ec051d9b5afef55c0e5ebb  crypto/aes/asm/aesv8-armx.pl
+e3955352a92d56905d63e68937e4758f13190a14a10a3dcb1e5c641c49913c0c  crypto/aes/asm/aesv8-armx.pl
 5e8005fdb6641df465bdda20c3476f7176e6bcd63d5073044a0c02a327c7f172  crypto/aes/asm/bsaes-armv7.pl
 0726a2c4c15c27a12b2f7d5e16863df4a1b1daa7b7d9b728f621b2b224d290e6  crypto/aes/asm/bsaes-x86_64.pl
 1ff94d6bf6c8ae4809f64657eb89260fe3cb22137f649d3c73f72cb190258196  crypto/aes/asm/vpaes-armv8.pl
@@ -79,7 +79,7 @@ d94295953ab91469fe2b9da2a542b8ea11ac38551ecde8f8202b7f645c2dea16  crypto/bn/bn_d
 74b63a4515894592b7241fb30b91b21510beaa3d397809e3d74bc9a73e879d18  crypto/bn/bn_div.c
 a29b8b7fa8460f11e50f880e3c3c9e0755b93889bcbb5476206c4d938a9c5735  crypto/bn/bn_exp.c
 ec2b6e3af6df473a23e7f1a8522f2554cb0eb5d34e3282458c4a66d242278434  crypto/bn/bn_exp2.c
-1abab2cc5466b005b939d156e7d8664a4d42a191c9040dbb83941269d6844f0c  crypto/bn/bn_gcd.c
+baba7c8ae95af6aa36bc9f4be3a2eed33d500451e568ca4bfc6bc7cb48d4f7ea  crypto/bn/bn_gcd.c
 4d6cc7ed36978247a191df1eea0120f8ee97b639ba228793dabe5a8355a1a609  crypto/bn/bn_gf2m.c
 081e8a6abc23599307dab3b1a92113a65e0bf8717cbc40c970c7469350bc4581  crypto/bn/bn_intern.c
 602ed46fbfe12c899dfb7d9d99ff0dbfff96b454fce3cd02817f3e2488dd9192  crypto/bn/bn_kron.c
@@ -122,20 +122,20 @@ eeef5722ad56bf1af2ff71681bcc8b8525bc7077e973c98cee920ce9bcc66c81  crypto/des/ecb
 61926e30dd940616e80936d1c94c5f522daf0d475fb3a40a9e589e78f322901e  crypto/des/set_key.c
 8344811b14d151f6cd40a7bc45c8f4a1106252b119c1d5e6a589a023f39b107d  crypto/des/spr.h
 816472a54c273906d0a2b58650e0b9d28cc2c8023d120f0d77160f1fe34c4ca3  crypto/dh/dh_backend.c
-d2d0569bea2598bd405f23b60e5283a6ce353f1145a25ff8f28cf15711743156  crypto/dh/dh_check.c
+fcbfe5acb73e1b4094efec56a754b803d2c1a53644c78cf6a73ae868e3f3886d  crypto/dh/dh_check.c
 7838e9a35870b0fbcba0aff2f52a2439f64d026e9922bce6e5978c2f22c51120  crypto/dh/dh_gen.c
 6b17861887b2535159b9e6ca4f927767dad3e71b6e8be50055bc784f78e92d64  crypto/dh/dh_group_params.c
 a5cf5cb464b40f1bc5457dc2a6f2c5ec0f050196603cd2ba7037a23ab64adbf7  crypto/dh/dh_kdf.c
-0afa7dd237f9b21b0cfb0de10505facd57eb07ded905d888d43a1de2356d4002  crypto/dh/dh_key.c
-b0046b2c4e1d74ff4e93f2486a00f63728909b8a75cbdd29b9100e607f97995c  crypto/dh/dh_lib.c
+9e61a0b5017d835b348b15e93760c42d8d899ffae4251455c7b3085cfd25294c  crypto/dh/dh_key.c
+92345c259ea2a8c09e6d6b069d0942bd6ca4642231580f3e8148ae7a832a1115  crypto/dh/dh_lib.c
 8300775d88db0a1aa26a77eb49d6c4f7252e7fee69e1440de4c40edadc9da044  crypto/dh/dh_local.h
 bbcf4fc3067ac462a27d7277973180b7dc140df9262a686c7fbe4318ca01f7b8  crypto/dsa/dsa_backend.c
-b9c5992089203123c3fae46e39bb4d05e19854087bca7a30ad1f82a3505deec7  crypto/dsa/dsa_check.c
+d7e0d87494e3b3f0898a56785a219e87a2ce14416393ec32d8c0b5f539c7bdbf  crypto/dsa/dsa_check.c
 ae727bf6319eb57e682de35d75ea357921987953b3688365c710e7fba51c7c58  crypto/dsa/dsa_gen.c
 b1de1624e590dbf76f76953802ff162cc8de7c5e2eaba897313c866424d6902b  crypto/dsa/dsa_key.c
-9e436a2e0867920c3a5ac58bc14300cad4ab2c4c8fe5e40b355dfd21bfdfe146  crypto/dsa/dsa_lib.c
+9f4837c5abe53613a2dc1c5db81d073d4f42bd28b6a2d1e93a2b350d8e25d52a  crypto/dsa/dsa_lib.c
 f4d52d3897219786c6046bf76abb2f174655c584caa50272bf5d281720df5022  crypto/dsa/dsa_local.h
-38062c6eebdb2f88fa0c6592837a96a49de2ae520d3ad483a3e02921c8adb094  crypto/dsa/dsa_ossl.c
+c5c252f205482a71efeabe226d51a1c541a6ba2dfa9b8b8a70901087a9dc1667  crypto/dsa/dsa_ossl.c
 d612fd05ff98816ba6cf37f84c0e31443ad9d840ed587a7ab2066027da390325  crypto/dsa/dsa_sign.c
 53fa10cc87ac63e35df661882852dc46ae68e6fee83b842f1aeefe00b8900ee1  crypto/dsa/dsa_vrf.c
 d9722ad8c6b6e209865a921f3cda831d09bf54a55cacd1edd9802edb6559190a  crypto/ec/asm/ecp_nistp521-ppc64.pl
@@ -193,7 +193,7 @@ b4b7c683279454ba41438f50a015cb63ef056ccb9be0168918dfbae00313dc68  crypto/ec/ecp_
 0e75a058dcbbb62cfe39fec6c4a85385dc1a8fce794e4278ce6cebb29763b82b  crypto/evp/dh_support.c
 1af3872164b4a4757bc7896a24b4d2f8eb2cfb4cba0d872a93db69975693e0a6  crypto/evp/digest.c
 838277f228cd3025cf95a9cd435e5606ad1fb5d207bbb057aa29892e6a657c55  crypto/evp/ec_support.c
-1c3d1b1f800b1f1f5adb1fdbdd67cdf37ca7ea93b264d1468c72a63c140873ce  crypto/evp/evp_enc.c
+61df3942752307b7006f09d7628348a0cc9e5555469a3a8862349067a52824b7  crypto/evp/evp_enc.c
 7f10367f9b6191c4a8c01784130d26b2d778485a41cdac5fa17c9a1c4096f132  crypto/evp/evp_fetch.c
 ebe32b2895f7f9767710674352c8949efe93b4bbb5e7b71c27bb5d1822339b46  crypto/evp/evp_lib.c
 78f07bf50b6999611a4e9414ab3a20b219b0ab29ca2bd05002d6919a3f67b8eb  crypto/evp/evp_local.h
@@ -213,11 +213,11 @@ e7e8eb5683cd3fbd409df888020dc353b65ac291361829cc4131d5bc86c9fcb3  crypto/evp/mac
 1f0e9e94e9b0ad322956521b438b78d44cfcd8eb974e8921d05f9e21ba1c05cf  crypto/evp/pmeth_gn.c
 76511fba789089a50ef87774817a5482c33633a76a94ecf7b6e8eb915585575d  crypto/evp/pmeth_lib.c
 4b2dbddf0f9ceed34c3822347138be754fb194febca1c21c46bcc3a5cce33674  crypto/evp/signature.c
-b06cb8fd4bd95aae1f66e1e145269c82169257f1a60ef0f78f80a3d4c5131fac  crypto/ex_data.c
+f2acfb82aac20251d05a9c252cc6c282bd44e43feac4ac2e0faf68b9a38aef57  crypto/ex_data.c
 1c8389c5d49616d491978f0f2b2a54ba82d805ec41c8f75c67853216953cf46a  crypto/ffc/ffc_backend.c
 a12af33e605315cdddd6d759e70cd9632f0f33682b9aa7103ed1ecd354fc7e55  crypto/ffc/ffc_dh.c
 854378f57707e31ad02cca6eec94369f91f327288d3665713e249c12f7b13211  crypto/ffc/ffc_key_generate.c
-2695c9c8ad9193a8c1ab53d5d09712d50d12c91eb8d62e8a15cbc78f327afe84  crypto/ffc/ffc_key_validate.c
+4e973d956d4ec2087994de8e963be1a512da1441f22e6e7b9cd7ee536e3ff834  crypto/ffc/ffc_key_validate.c
 8b72d5a7452b2c15aec6d20027053a83f7df89d49a3b6cfedd77e2b1a29e9fc1  crypto/ffc/ffc_params.c
 1a1d227f9a0f427d2ec93bc646c726c9cd49a84a343b4aff0c9c744fa6df05a9  crypto/ffc/ffc_params_generate.c
 73dac805abab36cd9df53a421221c71d06a366a4ce479fa788be777f11b47159  crypto/ffc/ffc_params_validate.c
@@ -225,7 +225,7 @@ a12af33e605315cdddd6d759e70cd9632f0f33682b9aa7103ed1ecd354fc7e55  crypto/ffc/ffc
 0395c1b0834f2f4a0ca1756385f4dc1a4ef6fb925b2db3743df7f57256c5166f  crypto/hmac/hmac_local.h
 0e2d6129504d15ffaf5baa63158ccec0e4b6193a8275333956d8f868ef35127e  crypto/ia64cpuid.S
 f897493b50f4e9dd4cacb2a7accda6683c10ece602641874cdff1dac7128a751  crypto/initthread.c
-5482c47c266523129980302426d25839fda662f1544f4b684707e6b272a952c9  crypto/lhash/lhash.c
+7290d8d7ec31a98b17618f218d4f27b393501c7606c814a43db8af1975ad1d10  crypto/lhash/lhash.c
 5d49ce00fc06df1b64cbc139ef45c71e0faf08a33f966bc608c82d574521a49e  crypto/lhash/lhash_local.h
 f866aafae928db1b439ac950dc90744a2397dfe222672fe68b3798396190c8b0  crypto/mem_clr.c
 e14f48d4112c0efe3826b4aa390cc24045a85298cc551ec7f3f36ac4236d7d81  crypto/modes/asm/aes-gcm-armv8_64.pl
@@ -240,7 +240,7 @@ e472d73d06933667a51a0af973479993eed333c71b43af03095450acb36dbeb4  crypto/modes/a
 26f55a57e77f774d17dfba93d757f78edfa3a03f68a71ffa37ccf3bfc468b1e2  crypto/modes/asm/ghash-x86.pl
 72744131007d2389c09665a59a862f5f6bb61b64bd3456e9b400985cb56586b8  crypto/modes/asm/ghash-x86_64.pl
 a4e9f2e496bd9362b17a1b5989aa4682647cefcff6117f0607122a9e11a9dfd9  crypto/modes/asm/ghashp8-ppc.pl
-0029b5beb1d4cd4c5ad47164c23f3e7c9d1eaff66ef54af025ee26795b11a1c7  crypto/modes/asm/ghashv8-armx.pl
+69a13f423ca74c22543900c14aef4a848e3bc75504b65d2f51c6903aebcc17a7  crypto/modes/asm/ghashv8-armx.pl
 65112dfe63cd59487e7bdb1706b44acfcf48ecede12cc3ae51daa5b661f41f06  crypto/modes/cbc128.c
 1611e73dc1e01b5c2201f51756a7405b7673aa0bb872e2957d1ec80c3530486f  crypto/modes/ccm128.c
 d8c2f256532a4b94db6d03aea5cb609cccc938069f644b2fc77c5015648d148d  crypto/modes/cfb128.c
@@ -252,29 +252,29 @@ e55a816c356b2d526bc6e40c8b81afa02576e4d44c7d7b6bbe444fb8b01aad41  crypto/modes/w
 8aa2504f84a0637b5122f0c963c9d82773ba248bad972ab92be7169995d162b5  crypto/o_str.c
 8ddbbdf43131c10dcd4428aef0eff2b1e98b0410accada0fad41a4925868beef  crypto/packet.c
 a20bfd927d69737c86ca95d3cf636afa8cefd8fe23412d1a3897644a0da21211  crypto/param_build.c
-c2fe815fb3fd5efe9a6544cae55f9469063a0f6fb728361737b927f6182ae0bb  crypto/param_build_set.c
+2a0f272dd553b698e8c6fa57962694ebd6064cb03fe26a60df529205568d315d  crypto/param_build_set.c
 0e4a5388a92fabbe5a540176c0b4c5ce258b78dc9168ecc2e805352a06aaf0ba  crypto/params.c
 4fda13f6af05d80b0ab89ec4f5813c274a21a9b4565be958a02d006236cef05c  crypto/params_dup.c
 a0097ff2da8955fe15ba204cb54f3fd48a06f846e2b9826f507b26acf65715c3  crypto/params_from_text.c
 97cb7414dc2f165d5849ee3b46cdfff0afb067729435d9c01a747e0ca41e230c  crypto/ppccap.c
 3ca43596a7528dec8ff9d1a3cd0d68b62640f84b1d6a8b5e4842cfd0be1133ad  crypto/ppccpuid.pl
 b4d34272a0bd1fbe6562022bf7ea6259b6a5a021a48222d415be47ef5ef2a905  crypto/property/defn_cache.c
-7da6ae864beb1a4daa4be31eb41d48141a3a7eb7a263a4937a6889e05656a595  crypto/property/property.c
+3c4ade2fed4605e374d85ec1134a98da34e7124f89f44b81a754e8cfe81f14ba  crypto/property/property.c
 66da4f28d408133fb544b14aeb9ad4913e7c5c67e2826e53f0dc5bf4d8fada26  crypto/property/property_local.h
-921305e62749aec22da4843738bee3448b61e7e30d5309beddc7141ad07a8004  crypto/property/property_parse.c
+099407e68e705f1458b701b9336f633565fc0843355fedf1ec83794349548a51  crypto/property/property_parse.c
 a7cefda6a117550e2c76e0f307565ce1e11640b11ba10c80e469a837fd1212a3  crypto/property/property_query.c
 065698c8d88a5facc0cbc02a3bd0c642c94687a8c5dd79901c942138b406067d  crypto/property/property_string.c
-9653ec9c1476350a94b9cc7f8be3d99961fd803870c9ac03315298d2909a6a8e  crypto/provider_core.c
+0ba5d0297837940c972224c97cbbf3ea4a723c1eed9ce1112538c9bb26208639  crypto/provider_core.c
 d0af10d4091b2032aac1b7db80f8c2e14fa7176592716b25b9437ab6b53c0a89  crypto/provider_local.h
 5ba2e1c74ddcd0453d02e32612299d1eef18eff8493a7606c15d0dc3738ad1d9  crypto/provider_predefined.c
 a5a4472636b8b0095ad8d4acd37e275ad79da1a67ecff7b7b5c3e46c9ebc65b7  crypto/rand/rand_lib.c
 fd03b9bb2c23470fa40880ed3bf9847bb17d50592101a78c0ad7a0f121209788  crypto/rand/rand_local.h
 f0c8792a99132e0b9c027cfa7370f45594a115934cdc9e8f23bdd64abecaf7fd  crypto/rsa/rsa_acvp_test_params.c
-9e7dd6fc91d3266d4aa4f0f41b7986381122b7d98114e63ebf04c5ee298b5fda  crypto/rsa/rsa_backend.c
+5834d7c518ad53ea0dd3db811c0e51568c81cc6c117012030101d29003d0725c  crypto/rsa/rsa_backend.c
 38a102cd1da1f6ca5a46e6a22f018237964336274385f5c70cbedcaa6997647e  crypto/rsa/rsa_chk.c
 e32cfa04221a2a3ea33f7bcb93ee51b84cbeba97e94c1fbf6e420b24f97fc9ce  crypto/rsa/rsa_crpt.c
 e995da1c2e5007bd7f5907f369fe45ed15f4e657143a85078c755bd5e6863d0b  crypto/rsa/rsa_gen.c
-74ed75d1d8e0844800504a137bfd81c3dbcb6c4bd58b5d5fe9d0a362092b6e88  crypto/rsa/rsa_lib.c
+f2222f270e57559537d3da8abbeb1390bc5376b73dae59d536af6e73eb48bba0  crypto/rsa/rsa_lib.c
 a65e85be5269d8cb88e86b3413c978fa8994419a671092cbf104ff1a08fda23b  crypto/rsa/rsa_local.h
 cf0b75cd54b61b9b9a290ef18d0ddce9fb26a029a54eb3f720d9b25188440f00  crypto/rsa/rsa_mp_names.c
 5c60f6e05db82e13178d805deb1947b8eee4a905e6e77523d3b288da70a46bb5  crypto/rsa/rsa_none.c
@@ -344,7 +344,7 @@ c50c584c55e56347bb43aca4b796b5344d70daece3061f586b79c871c21f5d1a  crypto/sparse_
 8da78169fa8c09dc3c29c9bf1602b22e88c5eac4815e274ba1864c166e31584b  crypto/stack/stack.c
 7b4efa594d8d1f3ecbf4605cf54f72fb296a3b1d951bdc69e415aaa08f34e5c8  crypto/threads_lib.c
 a41ae93a755e2ec89b3cb5b4932e2b508fdda92ace2e025a2650a6da0e9e972c  crypto/threads_none.c
-2637a8727dee790812b000f2e02b336f7907949df633dda72938bbaafdb204fe  crypto/threads_pthread.c
+3729e2bd36f945808b578e0d89fac0fcb3114e4fc9381614bcbd8a9869991716  crypto/threads_pthread.c
 88423960f0414f6fd41fba4f4c67f9f7260c2741e4788adcd52493e895ec8027  crypto/threads_win.c
 fd6c27cf7c6b5449b17f2b725f4203c4c10207f1973db09fd41571efe5de08fd  crypto/x86_64cpuid.pl
 bbec287bb9bf35379885f8f8998b7fd9e8fc22efee9e1b299109af0f33a7ee16  crypto/x86cpuid.pl
@@ -430,7 +430,7 @@ bc9ec2be442a4f49980ba2c63c8f0da701de1f6e23d7db35d781658f833dd7b9  include/openss
 61c76ee3f12ed0e42503a56421ca00f1cb9a0f4caa5f9c4421c374bcd45917d7  include/openssl/encoder.h
 69dd983f45b8ccd551f084796519446552963a18c52b70470d978b597c81b2dc  include/openssl/encodererr.h
 c6ee8f17d7252bdd0807a124dc6d50a95c32c04e17688b7c2e061998570b7028  include/openssl/err.h.in
-12ec111c0e22581e0169be5e1838353a085fb51e3042ef59a7db1cee7da73c5b  include/openssl/evp.h
+b23bf3e2d0a60fe4d768afbe7aab48b47791e1274ae42b28895255119ae7f61d  include/openssl/evp.h
 5bd1b5dcd14067a1fe490d49df911002793c0b4f0bd4492cd8f71cfed7bf9f2a  include/openssl/evperr.h
 5381d96fe867a4ee0ebc09b9e3a262a0d7a27edc5f91dccfb010c7d713cd0820  include/openssl/fips_names.h
 b1d41beba560a41383f899a361b786e04f889106fb5960ec831b0af7996c9783  include/openssl/fipskey.h.in
@@ -567,18 +567,18 @@ abe2b0f3711eaa34846e155cffc9242e4051c45de896f747afd5ac9d87f637dc  providers/impl
 589f6133799da80760e8bc3ab0191a341ab6d4d2706e92e6eb4a24b0250fefa6  providers/implementations/kdfs/tls1_prf.c
 4d4a6d9a562d2dcfec941d3f113a544663b5ac2fbe4accd89ec70c1cc11751d0  providers/implementations/kdfs/x942kdf.c
 6b6c776b12664164f3cb54c21df61e1c4477c7855d89431a16fb338cdae58d43  providers/implementations/kem/rsa_kem.c
-37120f8a420de0e44b7dc1f31b50d59520e5318cf546e83684e0c3de5c7b76c5  providers/implementations/keymgmt/dh_kmgmt.c
-2a4493c9e68f41d37d7ec69c272005c6df7b1a34db2d49663f52e836e4fd888c  providers/implementations/keymgmt/dsa_kmgmt.c
+11a0d0fb88ed88e965f10b3a0ef6c880f60341df995128f57ad943053aaf15b2  providers/implementations/keymgmt/dh_kmgmt.c
+a329f57cb041cd03907e9d996fbc2f378ee116c7f8d7fbf1ea08b7a5df7e0304  providers/implementations/keymgmt/dsa_kmgmt.c
 9bc88451d3ae110c7a108ee73d3b3b6bda801ec3494d2dfb9c9970b85c2d34fe  providers/implementations/keymgmt/ec_kmgmt.c
 258ae17bb2dd87ed1511a8eb3fe99eed9b77f5c2f757215ff6b3d0e8791fc251  providers/implementations/keymgmt/ec_kmgmt_imexport.inc
-d77ece2494e6b12a6201a2806ee5fb24a6dc2fa3e1891a46012a870e0b781ab1  providers/implementations/keymgmt/ecx_kmgmt.c
+011c36aad6834729043f23eacab417732541ee23916d9afa5bb9164862be00bb  providers/implementations/keymgmt/ecx_kmgmt.c
 053a2be39a87f50b877ebdbbf799cf5faf8b2de33b04311d819d212ee1ea329b  providers/implementations/keymgmt/kdf_legacy_kmgmt.c
-e30357311e4a3e1c78266af6315fd1fc99584bfb09f4a7cd0ddc7261cf1e17e1  providers/implementations/keymgmt/mac_legacy_kmgmt.c
+1646b477fa231dd0f6c22444c99098f9b447cab0d39ff69b811262469d4dbe09  providers/implementations/keymgmt/mac_legacy_kmgmt.c
 19f22fc70a6321441e56d5bd4aab3d01d52d17069d4e4b5cefce0f411ecece75  providers/implementations/keymgmt/rsa_kmgmt.c
 aeb42590728ca87b916b8a3d337351b1c82ee0747213e5ce740c2350b3db7185  providers/implementations/macs/cmac_prov.c
 e69aa06f8f3c6f5a26702b9f44a844b8589b99dc0ee590953a29e8b9ef10acbe  providers/implementations/macs/gmac_prov.c
 895c8dc7235b9ad5ff893be0293cbc245a5455e8850195ac7d446646e4ea71d0  providers/implementations/macs/hmac_prov.c
-f75fbfe5348f93ad610da7d310f4e8fecf18c0549f27605da25d393c33e0edc2  providers/implementations/macs/kmac_prov.c
+8640b63fd8325aaf8f7128d6cc448d9af448a65bf51a8978075467d33a67944e  providers/implementations/macs/kmac_prov.c
 bf30274dd6b528ae913984775bd8f29c6c48c0ef06d464d0f738217727b7aa5c  providers/implementations/rands/crngt.c
 9d23df7f99beec7392c9d4ed813407050bc2d150098888fe802e2c9705fc33fa  providers/implementations/rands/drbg.c
 bb5f8161a80d0d1a7ee919af2b167972b00afd62e326252ca6aa93101f315f19  providers/implementations/rands/drbg_ctr.c
diff --git a/deps/openssl/openssl/providers/fips.checksum b/deps/openssl/openssl/providers/fips.checksum
index ec1978c7fedec1..347a9614339ee8 100644
--- a/deps/openssl/openssl/providers/fips.checksum
+++ b/deps/openssl/openssl/providers/fips.checksum
@@ -1 +1 @@
-f07990ec634ec6ea3c8c42a664768debcf92a1b0c39bde7041c24df33dd7f052  providers/fips-sources.checksums
+114b59f288ec2d6ddfcd26187f43cad614c6d4e4a7aba24410494f46f627671c  providers/fips-sources.checksums
diff --git a/deps/openssl/openssl/providers/implementations/ciphers/cipher_chacha20.c b/deps/openssl/openssl/providers/implementations/ciphers/cipher_chacha20.c
index 386c865d832e0f..ef80a515d756dc 100644
--- a/deps/openssl/openssl/providers/implementations/ciphers/cipher_chacha20.c
+++ b/deps/openssl/openssl/providers/implementations/ciphers/cipher_chacha20.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -21,6 +21,7 @@
 
 static OSSL_FUNC_cipher_newctx_fn chacha20_newctx;
 static OSSL_FUNC_cipher_freectx_fn chacha20_freectx;
+static OSSL_FUNC_cipher_dupctx_fn chacha20_dupctx;
 static OSSL_FUNC_cipher_get_params_fn chacha20_get_params;
 static OSSL_FUNC_cipher_get_ctx_params_fn chacha20_get_ctx_params;
 static OSSL_FUNC_cipher_set_ctx_params_fn chacha20_set_ctx_params;
@@ -64,6 +65,25 @@ static void chacha20_freectx(void *vctx)
     }
 }
 
+static void *chacha20_dupctx(void *vctx)
+{
+    PROV_CHACHA20_CTX *ctx = (PROV_CHACHA20_CTX *)vctx;
+    PROV_CHACHA20_CTX *dupctx = NULL;
+
+    if (ctx != NULL) {
+        dupctx = OPENSSL_memdup(ctx, sizeof(*dupctx));
+        if (dupctx != NULL && dupctx->base.tlsmac != NULL && dupctx->base.alloced) {
+            dupctx->base.tlsmac = OPENSSL_memdup(dupctx->base.tlsmac,
+                                                 dupctx->base.tlsmacsize);
+            if (dupctx->base.tlsmac == NULL) {
+                OPENSSL_free(dupctx);
+                dupctx = NULL;
+            }
+        }
+    }
+    return dupctx;
+}
+
 static int chacha20_get_params(OSSL_PARAM params[])
 {
     return ossl_cipher_generic_get_params(params, 0, CHACHA20_FLAGS,
@@ -187,6 +207,7 @@ int ossl_chacha20_dinit(void *vctx, const unsigned char *key, size_t keylen,
 const OSSL_DISPATCH ossl_chacha20_functions[] = {
     { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))chacha20_newctx },
     { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))chacha20_freectx },
+    { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))chacha20_dupctx },
     { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))ossl_chacha20_einit },
     { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))ossl_chacha20_dinit },
     { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))chacha20_update },
diff --git a/deps/openssl/openssl/providers/implementations/encode_decode/decode_der2key.c b/deps/openssl/openssl/providers/implementations/encode_decode/decode_der2key.c
index b9cee2571bf392..d598f7eba1acc9 100644
--- a/deps/openssl/openssl/providers/implementations/encode_decode/decode_der2key.c
+++ b/deps/openssl/openssl/providers/implementations/encode_decode/decode_der2key.c
@@ -316,10 +316,14 @@ static int der2key_export_object(void *vctx,
     void *keydata;
 
     if (reference_sz == sizeof(keydata) && export != NULL) {
+        int selection = ctx->selection;
+
+        if (selection == 0)
+            selection = OSSL_KEYMGMT_SELECT_ALL;
         /* The contents of the reference is the address to our object */
         keydata = *(void **)reference;
 
-        return export(keydata, ctx->selection, export_cb, export_cbarg);
+        return export(keydata, selection, export_cb, export_cbarg);
     }
     return 0;
 }
diff --git a/deps/openssl/openssl/providers/implementations/encode_decode/decode_msblob2key.c b/deps/openssl/openssl/providers/implementations/encode_decode/decode_msblob2key.c
index 501957faba0117..b9d0cabadae2e4 100644
--- a/deps/openssl/openssl/providers/implementations/encode_decode/decode_msblob2key.c
+++ b/deps/openssl/openssl/providers/implementations/encode_decode/decode_msblob2key.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -79,6 +79,18 @@ static void msblob2key_freectx(void *vctx)
     OPENSSL_free(ctx);
 }
 
+static int msblob2key_does_selection(void *provctx, int selection)
+{
+    if (selection == 0)
+        return 1;
+
+    if ((selection & (OSSL_KEYMGMT_SELECT_PRIVATE_KEY
+                      | OSSL_KEYMGMT_SELECT_PUBLIC_KEY))  != 0)
+        return 1;
+
+    return 0;
+}
+
 static int msblob2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
                              OSSL_CALLBACK *data_cb, void *data_cbarg,
                              OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
@@ -211,10 +223,14 @@ msblob2key_export_object(void *vctx,
     void *keydata;
 
     if (reference_sz == sizeof(keydata) && export != NULL) {
+        int selection = ctx->selection;
+
+        if (selection == 0)
+            selection = OSSL_KEYMGMT_SELECT_ALL;
         /* The contents of the reference is the address to our object */
         keydata = *(void **)reference;
 
-        return export(keydata, ctx->selection, export_cb, export_cbarg);
+        return export(keydata, selection, export_cb, export_cbarg);
     }
     return 0;
 }
@@ -260,6 +276,8 @@ static void rsa_adjust(void *key, struct msblob2key_ctx_st *ctx)
           (void (*)(void))msblob2##keytype##_newctx },                  \
         { OSSL_FUNC_DECODER_FREECTX,                                    \
           (void (*)(void))msblob2key_freectx },                         \
+        { OSSL_FUNC_DECODER_DOES_SELECTION,                             \
+          (void (*)(void))msblob2key_does_selection },                  \
         { OSSL_FUNC_DECODER_DECODE,                                     \
           (void (*)(void))msblob2key_decode },                          \
         { OSSL_FUNC_DECODER_EXPORT_OBJECT,                              \
diff --git a/deps/openssl/openssl/providers/implementations/encode_decode/decode_pvk2key.c b/deps/openssl/openssl/providers/implementations/encode_decode/decode_pvk2key.c
index c6424165b03bf7..2d7cb15e53e0ae 100644
--- a/deps/openssl/openssl/providers/implementations/encode_decode/decode_pvk2key.c
+++ b/deps/openssl/openssl/providers/implementations/encode_decode/decode_pvk2key.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -79,6 +79,17 @@ static void pvk2key_freectx(void *vctx)
     OPENSSL_free(ctx);
 }
 
+static int pvk2key_does_selection(void *provctx, int selection)
+{
+    if (selection == 0)
+        return 1;
+
+    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY)  != 0)
+        return 1;
+
+    return 0;
+}
+
 static int pvk2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
                          OSSL_CALLBACK *data_cb, void *data_cbarg,
                          OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
@@ -179,10 +190,14 @@ static int pvk2key_export_object(void *vctx,
     void *keydata;
 
     if (reference_sz == sizeof(keydata) && export != NULL) {
+        int selection = ctx->selection;
+
+        if (selection == 0)
+            selection = OSSL_KEYMGMT_SELECT_ALL;
         /* The contents of the reference is the address to our object */
         keydata = *(void **)reference;
 
-        return export(keydata, ctx->selection, export_cb, export_cbarg);
+        return export(keydata, selection, export_cb, export_cbarg);
     }
     return 0;
 }
@@ -226,6 +241,8 @@ static void rsa_adjust(void *key, struct pvk2key_ctx_st *ctx)
           (void (*)(void))pvk2##keytype##_newctx },                     \
         { OSSL_FUNC_DECODER_FREECTX,                                    \
           (void (*)(void))pvk2key_freectx },                            \
+        { OSSL_FUNC_DECODER_DOES_SELECTION,                             \
+          (void (*)(void))pvk2key_does_selection },                     \
         { OSSL_FUNC_DECODER_DECODE,                                     \
           (void (*)(void))pvk2key_decode },                             \
         { OSSL_FUNC_DECODER_EXPORT_OBJECT,                              \
diff --git a/deps/openssl/openssl/providers/implementations/encode_decode/encode_key2any.c b/deps/openssl/openssl/providers/implementations/encode_decode/encode_key2any.c
index c7b01cb2b3e5ef..0f4c62962ddcd4 100644
--- a/deps/openssl/openssl/providers/implementations/encode_decode/encode_key2any.c
+++ b/deps/openssl/openssl/providers/implementations/encode_decode/encode_key2any.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -858,14 +858,17 @@ static int prepare_rsa_params(const void *rsa, int nid, int save,
                 case 1:
                     if ((str = OPENSSL_malloc(str_sz)) == NULL
                         || !WPACKET_init_der(&pkt, str, str_sz)) {
+                        WPACKET_cleanup(&pkt);
                         goto err;
                     }
                     break;
                 }
                 if (!ossl_DER_w_RSASSA_PSS_params(&pkt, -1, pss)
                     || !WPACKET_finish(&pkt)
-                    || !WPACKET_get_total_written(&pkt, &str_sz))
+                    || !WPACKET_get_total_written(&pkt, &str_sz)) {
+                    WPACKET_cleanup(&pkt);
                     goto err;
+                }
                 WPACKET_cleanup(&pkt);
 
                 /*
diff --git a/deps/openssl/openssl/providers/implementations/encode_decode/encode_key2text.c b/deps/openssl/openssl/providers/implementations/encode_decode/encode_key2text.c
index 7d983f5e51c6df..3e75a9afb370c6 100644
--- a/deps/openssl/openssl/providers/implementations/encode_decode/encode_key2text.c
+++ b/deps/openssl/openssl/providers/implementations/encode_decode/encode_key2text.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -241,7 +241,7 @@ static int dh_to_text(BIO *out, const void *key, int selection)
             return 0;
         }
     }
-    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
         pub_key = DH_get0_pub_key(dh);
         if (pub_key == NULL) {
             ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
@@ -316,7 +316,7 @@ static int dsa_to_text(BIO *out, const void *key, int selection)
             return 0;
         }
     }
-    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
         pub_key = DSA_get0_pub_key(dsa);
         if (pub_key == NULL) {
             ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
@@ -525,7 +525,7 @@ static int ec_to_text(BIO *out, const void *key, int selection)
         if (priv_len == 0)
             goto err;
     }
-    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
         const EC_POINT *pub_pt = EC_KEY_get0_public_key(ec);
 
         if (pub_pt == NULL) {
@@ -575,26 +575,31 @@ static int ecx_to_text(BIO *out, const void *key, int selection)
         return 0;
     }
 
+    switch (ecx->type) {
+    case ECX_KEY_TYPE_X25519:
+        type_label = "X25519";
+        break;
+    case ECX_KEY_TYPE_X448:
+        type_label = "X448";
+        break;
+    case ECX_KEY_TYPE_ED25519:
+        type_label = "ED25519";
+        break;
+    case ECX_KEY_TYPE_ED448:
+        type_label = "ED448";
+        break;
+    }
+
     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
         if (ecx->privkey == NULL) {
             ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
             return 0;
         }
 
-        switch (ecx->type) {
-        case ECX_KEY_TYPE_X25519:
-            type_label = "X25519 Private-Key";
-            break;
-        case ECX_KEY_TYPE_X448:
-            type_label = "X448 Private-Key";
-            break;
-        case ECX_KEY_TYPE_ED25519:
-            type_label = "ED25519 Private-Key";
-            break;
-        case ECX_KEY_TYPE_ED448:
-            type_label = "ED448 Private-Key";
-            break;
-        }
+        if (BIO_printf(out, "%s Private-Key:\n", type_label) <= 0)
+            return 0;
+        if (!print_labeled_buf(out, "priv:", ecx->privkey, ecx->keylen))
+            return 0;
     } else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
         /* ecx->pubkey is an array, not a pointer... */
         if (!ecx->haspubkey) {
@@ -602,29 +607,11 @@ static int ecx_to_text(BIO *out, const void *key, int selection)
             return 0;
         }
 
-        switch (ecx->type) {
-        case ECX_KEY_TYPE_X25519:
-            type_label = "X25519 Public-Key";
-            break;
-        case ECX_KEY_TYPE_X448:
-            type_label = "X448 Public-Key";
-            break;
-        case ECX_KEY_TYPE_ED25519:
-            type_label = "ED25519 Public-Key";
-            break;
-        case ECX_KEY_TYPE_ED448:
-            type_label = "ED448 Public-Key";
-            break;
-        }
+        if (BIO_printf(out, "%s Public-Key:\n", type_label) <= 0)
+            return 0;
     }
 
-    if (BIO_printf(out, "%s:\n", type_label) <= 0)
-        return 0;
-    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
-        && !print_labeled_buf(out, "priv:", ecx->privkey, ecx->keylen))
-        return 0;
-    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0
-        && !print_labeled_buf(out, "pub:", ecx->pubkey, ecx->keylen))
+    if (!print_labeled_buf(out, "pub:", ecx->pubkey, ecx->keylen))
         return 0;
 
     return 1;
diff --git a/deps/openssl/openssl/providers/implementations/keymgmt/dh_kmgmt.c b/deps/openssl/openssl/providers/implementations/keymgmt/dh_kmgmt.c
index 9a7dde7c66273b..c14b9765d11b30 100644
--- a/deps/openssl/openssl/providers/implementations/keymgmt/dh_kmgmt.c
+++ b/deps/openssl/openssl/providers/implementations/keymgmt/dh_kmgmt.c
@@ -222,6 +222,9 @@ static int dh_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
     if (!ossl_prov_is_running() || dh == NULL)
         return 0;
 
+    if ((selection & DH_POSSIBLE_SELECTIONS) == 0)
+        return 0;
+
     tmpl = OSSL_PARAM_BLD_new();
     if (tmpl == NULL)
         return 0;
@@ -389,7 +392,7 @@ static int dh_validate_public(const DH *dh, int checktype)
         && ossl_dh_is_named_safe_prime_group(dh))
         return ossl_dh_check_pub_key_partial(dh, pub_key, &res);
 
-    return DH_check_pub_key(dh, pub_key, &res);
+    return DH_check_pub_key_ex(dh, pub_key);
 }
 
 static int dh_validate_private(const DH *dh)
diff --git a/deps/openssl/openssl/providers/implementations/keymgmt/dsa_kmgmt.c b/deps/openssl/openssl/providers/implementations/keymgmt/dsa_kmgmt.c
index cd8b4410b0db63..2f5742cfcc07ce 100644
--- a/deps/openssl/openssl/providers/implementations/keymgmt/dsa_kmgmt.c
+++ b/deps/openssl/openssl/providers/implementations/keymgmt/dsa_kmgmt.c
@@ -223,6 +223,9 @@ static int dsa_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
     if (!ossl_prov_is_running() || dsa == NULL)
         return 0;
 
+    if ((selection & DSA_POSSIBLE_SELECTIONS) == 0)
+        return 0;
+
     tmpl = OSSL_PARAM_BLD_new();
     if (tmpl == NULL)
         return 0;
diff --git a/deps/openssl/openssl/providers/implementations/keymgmt/ecx_kmgmt.c b/deps/openssl/openssl/providers/implementations/keymgmt/ecx_kmgmt.c
index 2a7f867aa56b3b..987d38456fba41 100644
--- a/deps/openssl/openssl/providers/implementations/keymgmt/ecx_kmgmt.c
+++ b/deps/openssl/openssl/providers/implementations/keymgmt/ecx_kmgmt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -238,6 +238,9 @@ static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
     if (!ossl_prov_is_running() || key == NULL)
         return 0;
 
+    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
+        return 0;
+
     tmpl = OSSL_PARAM_BLD_new();
     if (tmpl == NULL)
         return 0;
diff --git a/deps/openssl/openssl/providers/implementations/keymgmt/mac_legacy_kmgmt.c b/deps/openssl/openssl/providers/implementations/keymgmt/mac_legacy_kmgmt.c
index c934ff16409415..1fae4407fca609 100644
--- a/deps/openssl/openssl/providers/implementations/keymgmt/mac_legacy_kmgmt.c
+++ b/deps/openssl/openssl/providers/implementations/keymgmt/mac_legacy_kmgmt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -281,6 +281,9 @@ static int mac_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
     if (!ossl_prov_is_running() || key == NULL)
         return 0;
 
+    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) == 0)
+        return 0;
+
     tmpl = OSSL_PARAM_BLD_new();
     if (tmpl == NULL)
         return 0;
diff --git a/deps/openssl/openssl/providers/implementations/macs/kmac_prov.c b/deps/openssl/openssl/providers/implementations/macs/kmac_prov.c
index b2f85398b4e284..99e7c60a74ce50 100644
--- a/deps/openssl/openssl/providers/implementations/macs/kmac_prov.c
+++ b/deps/openssl/openssl/providers/implementations/macs/kmac_prov.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2018-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -249,7 +249,7 @@ static int kmac_setkey(struct kmac_data_st *kctx, const unsigned char *key,
         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
         return 0;
     }
-    if (w < 0) {
+    if (w <= 0) {
         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);
         return 0;
     }
@@ -289,7 +289,7 @@ static int kmac_init(void *vmacctx, const unsigned char *key,
         return 0;
 
     t = EVP_MD_get_block_size(ossl_prov_digest_md(&kctx->digest));
-    if (t < 0) {
+    if (t <= 0) {
         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);
         return 0;
     }
diff --git a/deps/openssl/openssl/ssl/ssl_lib.c b/deps/openssl/openssl/ssl/ssl_lib.c
index a00e1fe3621c9c..b0ab5c6ef80042 100644
--- a/deps/openssl/openssl/ssl/ssl_lib.c
+++ b/deps/openssl/openssl/ssl/ssl_lib.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
  * Copyright 2005 Nokia. All rights reserved.
  *
@@ -631,7 +631,7 @@ int SSL_clear(SSL *s)
     OPENSSL_free(s->psksession_id);
     s->psksession_id = NULL;
     s->psksession_id_len = 0;
-    s->hello_retry_request = 0;
+    s->hello_retry_request = SSL_HRR_NONE;
     s->sent_tickets = 0;
 
     s->error = 0;
@@ -2894,14 +2894,14 @@ char *SSL_get_shared_ciphers(const SSL *s, char *buf, int size)
         if (sk_SSL_CIPHER_find(srvrsk, c) < 0)
             continue;
 
-        n = strlen(c->name);
-        if (n + 1 > size) {
+        n = OPENSSL_strnlen(c->name, size);
+        if (n >= size) {
             if (p != buf)
                 --p;
             *p = '\0';
             return buf;
         }
-        strcpy(p, c->name);
+        memcpy(p, c->name, n);
         p += n;
         *(p++) = ':';
         size -= n + 1;
diff --git a/deps/openssl/openssl/ssl/ssl_sess.c b/deps/openssl/openssl/ssl/ssl_sess.c
index c322a11d9c52a5..d836b33ed0e81d 100644
--- a/deps/openssl/openssl/ssl/ssl_sess.c
+++ b/deps/openssl/openssl/ssl/ssl_sess.c
@@ -198,8 +198,11 @@ SSL_SESSION *ssl_session_dup(const SSL_SESSION *src, int ticket)
     dest->references = 1;
 
     dest->lock = CRYPTO_THREAD_lock_new();
-    if (dest->lock == NULL)
+    if (dest->lock == NULL) {
+        OPENSSL_free(dest);
+        dest = NULL;
         goto err;
+    }
 
     if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, dest, &dest->ex_data))
         goto err;
diff --git a/deps/openssl/openssl/ssl/statem/extensions_srvr.c b/deps/openssl/openssl/ssl/statem/extensions_srvr.c
index ed53b28aba80ab..0dfbfed9a4af6c 100644
--- a/deps/openssl/openssl/ssl/statem/extensions_srvr.c
+++ b/deps/openssl/openssl/ssl/statem/extensions_srvr.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -883,7 +883,7 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
     }
 
     /* Act as if this ClientHello came after a HelloRetryRequest */
-    s->hello_retry_request = 1;
+    s->hello_retry_request = SSL_HRR_PENDING;
 
     s->ext.cookieok = 1;
 #endif
diff --git a/deps/openssl/openssl/test/README-dev.md b/deps/openssl/openssl/test/README-dev.md
index d015bcf5bfb019..d8922de000800f 100644
--- a/deps/openssl/openssl/test/README-dev.md
+++ b/deps/openssl/openssl/test/README-dev.md
@@ -130,7 +130,11 @@ Generic form of C test executables
     int setup_tests(void)
     {
         ADD_TEST(my_test);                  /* Add each test separately     */
-        return 1;                           /* Indicate success             */
+        return 1;                           /* Indicates success.  Return 0 */
+                                            /* to produce an error with a   */
+                                            /* usage message and -1 for     */
+                                            /* failure to set up with no    */
+                                            /* usage message.               */
     }
 
 You should use the `TEST_xxx` macros provided by `testutil.h` to test all failure
diff --git a/deps/openssl/openssl/test/chacha_internal_test.c b/deps/openssl/openssl/test/chacha_internal_test.c
index 878bd752e054bb..d316bfd7b36170 100644
--- a/deps/openssl/openssl/test/chacha_internal_test.c
+++ b/deps/openssl/openssl/test/chacha_internal_test.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -181,7 +181,7 @@ static int test_cha_cha_internal(int n)
 
 int setup_tests(void)
 {
-#ifdef CPUID_OBJ
+#ifdef OPENSSL_CPUID_OBJ
     OPENSSL_cpuid_setup();
 #endif
 
diff --git a/deps/openssl/openssl/test/cmp_asn_test.c b/deps/openssl/openssl/test/cmp_asn_test.c
index 1e65b383753eab..42a6b93b6b2732 100644
--- a/deps/openssl/openssl/test/cmp_asn_test.c
+++ b/deps/openssl/openssl/test/cmp_asn_test.c
@@ -42,16 +42,28 @@ static void tear_down(CMP_ASN_TEST_FIXTURE *fixture)
 
 static int execute_cmp_asn1_get_int_test(CMP_ASN_TEST_FIXTURE *fixture)
 {
-    int res;
+    int res = 0;
     ASN1_INTEGER *asn1integer = ASN1_INTEGER_new();
+    const int good_int = 77;
+    const int64_t max_int = INT_MAX;
 
     if (!TEST_ptr(asn1integer))
-        return 0;
-    if (!TEST_true(ASN1_INTEGER_set(asn1integer, 77))) {
+        return res;
+
+    if (!TEST_true(ASN1_INTEGER_set(asn1integer, good_int))) {
         ASN1_INTEGER_free(asn1integer);
         return 0;
     }
-    res = TEST_int_eq(77, ossl_cmp_asn1_get_int(asn1integer));
+    res = TEST_int_eq(good_int, ossl_cmp_asn1_get_int(asn1integer));
+    if (res == 0)
+        goto err;
+
+    res = 0;
+    if (!TEST_true(ASN1_INTEGER_set_int64(asn1integer, max_int + 1)))
+        goto err;
+    res = TEST_int_eq(-2, ossl_cmp_asn1_get_int(asn1integer));
+
+ err:
     ASN1_INTEGER_free(asn1integer);
     return res;
 }
diff --git a/deps/openssl/openssl/test/cmp_protect_test.c b/deps/openssl/openssl/test/cmp_protect_test.c
index 32dae32d9398d9..09bf2ec17faffa 100644
--- a/deps/openssl/openssl/test/cmp_protect_test.c
+++ b/deps/openssl/openssl/test/cmp_protect_test.c
@@ -37,15 +37,17 @@ static OSSL_PROVIDER *default_null_provider = NULL, *provider = NULL;
 
 static void tear_down(CMP_PROTECT_TEST_FIXTURE *fixture)
 {
-    OSSL_CMP_CTX_free(fixture->cmp_ctx);
-    OSSL_CMP_MSG_free(fixture->msg);
-    OSSL_CMP_PKISI_free(fixture->si);
+    if (fixture != NULL) {
+        OSSL_CMP_CTX_free(fixture->cmp_ctx);
+        OSSL_CMP_MSG_free(fixture->msg);
+        OSSL_CMP_PKISI_free(fixture->si);
 
-    OPENSSL_free(fixture->mem);
-    sk_X509_free(fixture->certs);
-    sk_X509_free(fixture->chain);
+        OPENSSL_free(fixture->mem);
+        sk_X509_free(fixture->certs);
+        sk_X509_free(fixture->chain);
 
-    OPENSSL_free(fixture);
+        OPENSSL_free(fixture);
+    }
 }
 
 static CMP_PROTECT_TEST_FIXTURE *set_up(const char *const test_case_name)
diff --git a/deps/openssl/openssl/test/cmsapitest.c b/deps/openssl/openssl/test/cmsapitest.c
index d5c4cb8481c210..dbb05cd4962269 100644
--- a/deps/openssl/openssl/test/cmsapitest.c
+++ b/deps/openssl/openssl/test/cmsapitest.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2018-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -56,7 +56,7 @@ static int test_encrypt_decrypt(const EVP_CIPHER *cipher)
     BIO_free(outmsgbio);
     CMS_ContentInfo_free(content);
 
-    return testresult;
+    return testresult && TEST_int_eq(ERR_peek_error(), 0);
 }
 
 static int test_encrypt_decrypt_aes_cbc(void)
@@ -286,7 +286,7 @@ static int test_d2i_CMS_bio_NULL(void)
                                   CMS_NO_SIGNER_CERT_VERIFY));
     CMS_ContentInfo_free(cms);
     BIO_free(bio);
-    return ret;
+    return ret && TEST_int_eq(ERR_peek_error(), 0);
 }
 
 static unsigned char *read_all(BIO *bio, long *p_len)
diff --git a/deps/openssl/openssl/test/endecode_test.c b/deps/openssl/openssl/test/endecode_test.c
index e3f7b81f693077..5158b39ee41f19 100644
--- a/deps/openssl/openssl/test/endecode_test.c
+++ b/deps/openssl/openssl/test/endecode_test.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -158,6 +158,7 @@ static int test_encode_decode(const char *file, const int line,
     void *encoded = NULL;
     long encoded_len = 0;
     EVP_PKEY *pkey2 = NULL;
+    EVP_PKEY *pkey3 = NULL;
     void *encoded2 = NULL;
     long encoded2_len = 0;
     int ok = 0;
@@ -185,15 +186,25 @@ static int test_encode_decode(const char *file, const int line,
                                 output_type, output_structure,
                                 (flags & FLAG_DECODE_WITH_TYPE ? type : NULL),
                                 selection, pass))
+        || ((output_structure == NULL
+             || strcmp(output_structure, "type-specific") != 0)
+            && !TEST_true(decode_cb(file, line, (void **)&pkey3, encoded, encoded_len,
+                                    output_type, output_structure,
+                                    (flags & FLAG_DECODE_WITH_TYPE ? type : NULL),
+                                    0, pass)))
         || !TEST_true(encode_cb(file, line, &encoded2, &encoded2_len, pkey2, selection,
                                 output_type, output_structure, pass, pcipher)))
         goto end;
 
     if (selection == OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) {
-        if (!TEST_int_eq(EVP_PKEY_parameters_eq(pkey, pkey2), 1))
+        if (!TEST_int_eq(EVP_PKEY_parameters_eq(pkey, pkey2), 1)
+            || (pkey3 != NULL
+                && !TEST_int_eq(EVP_PKEY_parameters_eq(pkey, pkey3), 1)))
             goto end;
     } else {
-        if (!TEST_int_eq(EVP_PKEY_eq(pkey, pkey2), 1))
+        if (!TEST_int_eq(EVP_PKEY_eq(pkey, pkey2), 1)
+            || (pkey3 != NULL
+                && !TEST_int_eq(EVP_PKEY_eq(pkey, pkey3), 1)))
             goto end;
     }
 
@@ -218,6 +229,7 @@ static int test_encode_decode(const char *file, const int line,
     OPENSSL_free(encoded);
     OPENSSL_free(encoded2);
     EVP_PKEY_free(pkey2);
+    EVP_PKEY_free(pkey3);
     return ok;
 }
 
diff --git a/deps/openssl/openssl/test/evp_extra_test.c b/deps/openssl/openssl/test/evp_extra_test.c
index a6667105dcdcda..2318bf6a68c9fe 100644
--- a/deps/openssl/openssl/test/evp_extra_test.c
+++ b/deps/openssl/openssl/test/evp_extra_test.c
@@ -1133,11 +1133,11 @@ static int test_EVP_PKEY_sign(int tst)
 
     if (tst == 0 ) {
         if (!TEST_ptr(pkey = load_example_rsa_key()))
-                goto out;
+            goto out;
     } else if (tst == 1) {
 #ifndef OPENSSL_NO_DSA
         if (!TEST_ptr(pkey = load_example_dsa_key()))
-                goto out;
+            goto out;
 #else
         ret = 1;
         goto out;
@@ -1145,7 +1145,82 @@ static int test_EVP_PKEY_sign(int tst)
     } else {
 #ifndef OPENSSL_NO_EC
         if (!TEST_ptr(pkey = load_example_ec_key()))
+            goto out;
+#else
+        ret = 1;
+        goto out;
+#endif
+    }
+
+    ctx = EVP_PKEY_CTX_new_from_pkey(testctx, pkey, NULL);
+    if (!TEST_ptr(ctx)
+            || !TEST_int_gt(EVP_PKEY_sign_init(ctx), 0)
+            || !TEST_int_gt(EVP_PKEY_sign(ctx, NULL, &sig_len, tbs,
+                                          sizeof(tbs)), 0))
+        goto out;
+    sig = OPENSSL_malloc(sig_len);
+    if (!TEST_ptr(sig)
+            /* Test sending a signature buffer that is too short is rejected */
+            || !TEST_int_le(EVP_PKEY_sign(ctx, sig, &shortsig_len, tbs,
+                                          sizeof(tbs)), 0)
+            || !TEST_int_gt(EVP_PKEY_sign(ctx, sig, &sig_len, tbs, sizeof(tbs)),
+                            0)
+            /* Test the signature round-trips */
+            || !TEST_int_gt(EVP_PKEY_verify_init(ctx), 0)
+            || !TEST_int_gt(EVP_PKEY_verify(ctx, sig, sig_len, tbs, sizeof(tbs)),
+                            0))
+        goto out;
+
+    ret = 1;
+ out:
+    EVP_PKEY_CTX_free(ctx);
+    OPENSSL_free(sig);
+    EVP_PKEY_free(pkey);
+    return ret;
+}
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+static int test_EVP_PKEY_sign_with_app_method(int tst)
+{
+    int ret = 0;
+    EVP_PKEY *pkey = NULL;
+    RSA *rsa = NULL;
+    RSA_METHOD *rsa_meth = NULL;
+#ifndef OPENSSL_NO_DSA
+    DSA *dsa = NULL;
+    DSA_METHOD *dsa_meth = NULL;
+#endif
+    unsigned char *sig = NULL;
+    size_t sig_len = 0, shortsig_len = 1;
+    EVP_PKEY_CTX *ctx = NULL;
+    unsigned char tbs[] = {
+        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+        0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13
+    };
+
+    if (tst == 0) {
+        if (!TEST_ptr(pkey = load_example_rsa_key()))
+            goto out;
+        if (!TEST_ptr(rsa_meth = RSA_meth_dup(RSA_get_default_method())))
+            goto out;
+
+        if (!TEST_ptr(rsa = EVP_PKEY_get1_RSA(pkey))
+            || !TEST_int_gt(RSA_set_method(rsa, rsa_meth), 0)
+            || !TEST_int_gt(EVP_PKEY_assign_RSA(pkey, rsa), 0))
+            goto out;
+        rsa = NULL; /* now owned by the pkey */
+    } else {
+#ifndef OPENSSL_NO_DSA
+        if (!TEST_ptr(pkey = load_example_dsa_key()))
                 goto out;
+        if (!TEST_ptr(dsa_meth = DSA_meth_dup(DSA_get_default_method())))
+            goto out;
+
+        if (!TEST_ptr(dsa = EVP_PKEY_get1_DSA(pkey))
+            || !TEST_int_gt(DSA_set_method(dsa, dsa_meth), 0)
+            || !TEST_int_gt(EVP_PKEY_assign_DSA(pkey, dsa), 0))
+            goto out;
+        dsa = NULL; /* now owned by the pkey */
 #else
         ret = 1;
         goto out;
@@ -1176,8 +1251,15 @@ static int test_EVP_PKEY_sign(int tst)
     EVP_PKEY_CTX_free(ctx);
     OPENSSL_free(sig);
     EVP_PKEY_free(pkey);
+    RSA_free(rsa);
+    RSA_meth_free(rsa_meth);
+#ifndef OPENSSL_NO_DSA
+    DSA_free(dsa);
+    DSA_meth_free(dsa_meth);
+#endif
     return ret;
 }
+#endif /* !OPENSSL_NO_DEPRECATED_3_0 */
 
 /*
  * n = 0 => test using legacy cipher
@@ -2830,6 +2912,36 @@ static int test_RSA_OAEP_set_get_params(void)
     return ret;
 }
 
+/* https://github.com/openssl/openssl/issues/21288 */
+static int test_RSA_OAEP_set_null_label(void)
+{
+    int ret = 0;
+    EVP_PKEY *key = NULL;
+    EVP_PKEY_CTX *key_ctx = NULL;
+
+    if (!TEST_ptr(key = load_example_rsa_key())
+        || !TEST_ptr(key_ctx = EVP_PKEY_CTX_new_from_pkey(testctx, key, NULL))
+        || !TEST_true(EVP_PKEY_encrypt_init(key_ctx)))
+        goto err;
+
+    if (!TEST_true(EVP_PKEY_CTX_set_rsa_padding(key_ctx, RSA_PKCS1_OAEP_PADDING)))
+        goto err;
+
+    if (!TEST_true(EVP_PKEY_CTX_set0_rsa_oaep_label(key_ctx, OPENSSL_strdup("foo"), 0)))
+        goto err;
+
+    if (!TEST_true(EVP_PKEY_CTX_set0_rsa_oaep_label(key_ctx, NULL, 0)))
+        goto err;
+
+    ret = 1;
+
+ err:
+    EVP_PKEY_free(key);
+    EVP_PKEY_CTX_free(key_ctx);
+
+    return ret;
+}
+
 #if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
 static int test_decrypt_null_chunks(void)
 {
@@ -4739,6 +4851,253 @@ static int test_ecx_not_private_key(int tst)
 }
 #endif /* OPENSSL_NO_EC */
 
+static int aes_gcm_encrypt(const unsigned char *gcm_key, size_t gcm_key_s,
+                           const unsigned char *gcm_iv, size_t gcm_ivlen,
+                           const unsigned char *gcm_pt, size_t gcm_pt_s,
+                           const unsigned char *gcm_aad, size_t gcm_aad_s,
+                           const unsigned char *gcm_ct, size_t gcm_ct_s,
+                           const unsigned char *gcm_tag, size_t gcm_tag_s)
+{
+    int ret = 0;
+    EVP_CIPHER_CTX *ctx;
+    EVP_CIPHER *cipher = NULL;
+    int outlen, tmplen;
+    unsigned char outbuf[1024];
+    unsigned char outtag[16];
+    OSSL_PARAM params[2] = {
+        OSSL_PARAM_END, OSSL_PARAM_END
+    };
+
+    if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new())
+            || !TEST_ptr(cipher = EVP_CIPHER_fetch(testctx, "AES-256-GCM", "")))
+        goto err;
+
+    params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN,
+                                            &gcm_ivlen);
+
+    if (!TEST_true(EVP_EncryptInit_ex2(ctx, cipher, gcm_key, gcm_iv, params))
+            || (gcm_aad != NULL
+                && !TEST_true(EVP_EncryptUpdate(ctx, NULL, &outlen,
+                                                gcm_aad, gcm_aad_s)))
+            || !TEST_true(EVP_EncryptUpdate(ctx, outbuf, &outlen,
+                                            gcm_pt, gcm_pt_s))
+            || !TEST_true(EVP_EncryptFinal_ex(ctx, outbuf, &tmplen)))
+        goto err;
+
+    params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,
+                                                  outtag, sizeof(outtag));
+
+    if (!TEST_true(EVP_CIPHER_CTX_get_params(ctx, params))
+            || !TEST_mem_eq(outbuf, outlen, gcm_ct, gcm_ct_s)
+            || !TEST_mem_eq(outtag, gcm_tag_s, gcm_tag, gcm_tag_s))
+        goto err;
+
+    ret = 1;
+err:
+    EVP_CIPHER_free(cipher);
+    EVP_CIPHER_CTX_free(ctx);
+
+    return ret;
+}
+
+static int aes_gcm_decrypt(const unsigned char *gcm_key, size_t gcm_key_s,
+                           const unsigned char *gcm_iv, size_t gcm_ivlen,
+                           const unsigned char *gcm_pt, size_t gcm_pt_s,
+                           const unsigned char *gcm_aad, size_t gcm_aad_s,
+                           const unsigned char *gcm_ct, size_t gcm_ct_s,
+                           const unsigned char *gcm_tag, size_t gcm_tag_s)
+{
+    int ret = 0;
+    EVP_CIPHER_CTX *ctx;
+    EVP_CIPHER *cipher = NULL;
+    int outlen;
+    unsigned char outbuf[1024];
+    OSSL_PARAM params[2] = {
+        OSSL_PARAM_END, OSSL_PARAM_END
+    };
+
+    if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
+        goto err;
+
+    if ((cipher = EVP_CIPHER_fetch(testctx, "AES-256-GCM", "")) == NULL)
+        goto err;
+
+    params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN,
+                                            &gcm_ivlen);
+
+    if (!TEST_true(EVP_DecryptInit_ex2(ctx, cipher, gcm_key, gcm_iv, params))
+            || (gcm_aad != NULL
+                && !TEST_true(EVP_DecryptUpdate(ctx, NULL, &outlen,
+                                                gcm_aad, gcm_aad_s)))
+            || !TEST_true(EVP_DecryptUpdate(ctx, outbuf, &outlen,
+                                            gcm_ct, gcm_ct_s))
+            || !TEST_mem_eq(outbuf, outlen, gcm_pt, gcm_pt_s))
+        goto err;
+
+    params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,
+                                                  (void*)gcm_tag, gcm_tag_s);
+
+    if (!TEST_true(EVP_CIPHER_CTX_set_params(ctx, params))
+            ||!TEST_true(EVP_DecryptFinal_ex(ctx, outbuf, &outlen)))
+        goto err;
+
+    ret = 1;
+err:
+    EVP_CIPHER_free(cipher);
+    EVP_CIPHER_CTX_free(ctx);
+
+    return ret;
+}
+
+static int test_aes_gcm_ivlen_change_cve_2023_5363(void)
+{
+    /* AES-GCM test data obtained from NIST public test vectors */
+    static const unsigned char gcm_key[] = {
+        0xd0, 0xc2, 0x67, 0xc1, 0x9f, 0x30, 0xd8, 0x0b, 0x89, 0x14, 0xbb, 0xbf,
+        0xb7, 0x2f, 0x73, 0xb8, 0xd3, 0xcd, 0x5f, 0x6a, 0x78, 0x70, 0x15, 0x84,
+        0x8a, 0x7b, 0x30, 0xe3, 0x8f, 0x16, 0xf1, 0x8b,
+    };
+    static const unsigned char gcm_iv[] = {
+        0xb6, 0xdc, 0xda, 0x95, 0xac, 0x99, 0x77, 0x76, 0x25, 0xae, 0x87, 0xf8,
+        0xa3, 0xa9, 0xdd, 0x64, 0xd7, 0x9b, 0xbd, 0x5f, 0x4a, 0x0e, 0x54, 0xca,
+        0x1a, 0x9f, 0xa2, 0xe3, 0xf4, 0x5f, 0x5f, 0xc2, 0xce, 0xa7, 0xb6, 0x14,
+        0x12, 0x6f, 0xf0, 0xaf, 0xfd, 0x3e, 0x17, 0x35, 0x6e, 0xa0, 0x16, 0x09,
+        0xdd, 0xa1, 0x3f, 0xd8, 0xdd, 0xf3, 0xdf, 0x4f, 0xcb, 0x18, 0x49, 0xb8,
+        0xb3, 0x69, 0x2c, 0x5d, 0x4f, 0xad, 0x30, 0x91, 0x08, 0xbc, 0xbe, 0x24,
+        0x01, 0x0f, 0xbe, 0x9c, 0xfb, 0x4f, 0x5d, 0x19, 0x7f, 0x4c, 0x53, 0xb0,
+        0x95, 0x90, 0xac, 0x7b, 0x1f, 0x7b, 0xa0, 0x99, 0xe1, 0xf3, 0x48, 0x54,
+        0xd0, 0xfc, 0xa9, 0xcc, 0x91, 0xf8, 0x1f, 0x9b, 0x6c, 0x9a, 0xe0, 0xdc,
+        0x63, 0xea, 0x7d, 0x2a, 0x4a, 0x7d, 0xa5, 0xed, 0x68, 0x57, 0x27, 0x6b,
+        0x68, 0xe0, 0xf2, 0xb8, 0x51, 0x50, 0x8d, 0x3d,
+    };
+    static const unsigned char gcm_pt[] = {
+        0xb8, 0xb6, 0x88, 0x36, 0x44, 0xe2, 0x34, 0xdf, 0x24, 0x32, 0x91, 0x07,
+        0x4f, 0xe3, 0x6f, 0x81,
+    };
+    static const unsigned char gcm_ct[] = {
+        0xff, 0x4f, 0xb3, 0xf3, 0xf9, 0xa2, 0x51, 0xd4, 0x82, 0xc2, 0xbe, 0xf3,
+        0xe2, 0xd0, 0xec, 0xed,
+    };
+    static const unsigned char gcm_tag[] = {
+        0xbd, 0x06, 0x38, 0x09, 0xf7, 0xe1, 0xc4, 0x72, 0x0e, 0xf2, 0xea, 0x63,
+        0xdb, 0x99, 0x6c, 0x21,
+    };
+
+    return aes_gcm_encrypt(gcm_key, sizeof(gcm_key), gcm_iv, sizeof(gcm_iv),
+                           gcm_pt, sizeof(gcm_pt), NULL, 0,
+                           gcm_ct, sizeof(gcm_ct), gcm_tag, sizeof(gcm_tag))
+        && aes_gcm_decrypt(gcm_key, sizeof(gcm_key), gcm_iv, sizeof(gcm_iv),
+                           gcm_pt, sizeof(gcm_pt), NULL, 0,
+                           gcm_ct, sizeof(gcm_ct), gcm_tag, sizeof(gcm_tag));
+}
+
+#ifndef OPENSSL_NO_RC4
+static int rc4_encrypt(const unsigned char *rc4_key, size_t rc4_key_s,
+                       const unsigned char *rc4_pt, size_t rc4_pt_s,
+                       const unsigned char *rc4_ct, size_t rc4_ct_s)
+{
+    int ret = 0;
+    EVP_CIPHER_CTX *ctx;
+    EVP_CIPHER *cipher = NULL;
+    int outlen, tmplen;
+    unsigned char outbuf[1024];
+    OSSL_PARAM params[2] = {
+        OSSL_PARAM_END, OSSL_PARAM_END
+    };
+
+    if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new())
+            || !TEST_ptr(cipher = EVP_CIPHER_fetch(testctx, "RC4", "")))
+        goto err;
+
+    params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN,
+                                            &rc4_key_s);
+
+    if (!TEST_true(EVP_EncryptInit_ex2(ctx, cipher, rc4_key, NULL, params))
+            || !TEST_true(EVP_EncryptUpdate(ctx, outbuf, &outlen,
+                                            rc4_pt, rc4_pt_s))
+            || !TEST_true(EVP_EncryptFinal_ex(ctx, outbuf, &tmplen)))
+        goto err;
+
+    if (!TEST_mem_eq(outbuf, outlen, rc4_ct, rc4_ct_s))
+        goto err;
+
+    ret = 1;
+err:
+    EVP_CIPHER_free(cipher);
+    EVP_CIPHER_CTX_free(ctx);
+
+    return ret;
+}
+
+static int rc4_decrypt(const unsigned char *rc4_key, size_t rc4_key_s,
+                       const unsigned char *rc4_pt, size_t rc4_pt_s,
+                       const unsigned char *rc4_ct, size_t rc4_ct_s)
+{
+    int ret = 0;
+    EVP_CIPHER_CTX *ctx;
+    EVP_CIPHER *cipher = NULL;
+    int outlen;
+    unsigned char outbuf[1024];
+    OSSL_PARAM params[2] = {
+        OSSL_PARAM_END, OSSL_PARAM_END
+    };
+
+    if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
+        goto err;
+
+    if ((cipher = EVP_CIPHER_fetch(testctx, "RC4", "")) == NULL)
+        goto err;
+
+    params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN,
+                                            &rc4_key_s);
+
+    if (!TEST_true(EVP_DecryptInit_ex2(ctx, cipher, rc4_key, NULL, params))
+            || !TEST_true(EVP_DecryptUpdate(ctx, outbuf, &outlen,
+                                            rc4_ct, rc4_ct_s))
+            || !TEST_mem_eq(outbuf, outlen, rc4_pt, rc4_pt_s))
+        goto err;
+
+    ret = 1;
+err:
+    EVP_CIPHER_free(cipher);
+    EVP_CIPHER_CTX_free(ctx);
+
+    return ret;
+}
+
+static int test_aes_rc4_keylen_change_cve_2023_5363(void)
+{
+    /* RC4 test data obtained from RFC 6229 */
+    static const struct {
+        unsigned char key[5];
+        unsigned char padding[11];
+    } rc4_key = {
+        {   /* Five bytes of key material */
+            0x83, 0x32, 0x22, 0x77, 0x2a,
+        },
+        {   /* Random padding to 16 bytes */
+            0x80, 0xad, 0x97, 0xbd, 0xc9, 0x73, 0xdf, 0x8a, 0xaa, 0x32, 0x91
+        }
+    };
+    static const unsigned char rc4_pt[] = {
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+    };
+    static const unsigned char rc4_ct[] = {
+        0x80, 0xad, 0x97, 0xbd, 0xc9, 0x73, 0xdf, 0x8a,
+        0x2e, 0x87, 0x9e, 0x92, 0xa4, 0x97, 0xef, 0xda
+    };
+
+    if (lgcyprov == NULL)
+        return TEST_skip("Test requires legacy provider to be loaded");
+
+    return rc4_encrypt(rc4_key.key, sizeof(rc4_key.key),
+                       rc4_pt, sizeof(rc4_pt), rc4_ct, sizeof(rc4_ct))
+        && rc4_decrypt(rc4_key.key, sizeof(rc4_key.key),
+                       rc4_pt, sizeof(rc4_pt), rc4_ct, sizeof(rc4_ct));
+}
+#endif
+
 int setup_tests(void)
 {
     OPTION_CHOICE o;
@@ -4771,6 +5130,9 @@ int setup_tests(void)
     ADD_TEST(test_EVP_Digest);
     ADD_TEST(test_EVP_md_null);
     ADD_ALL_TESTS(test_EVP_PKEY_sign, 3);
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+    ADD_ALL_TESTS(test_EVP_PKEY_sign_with_app_method, 2);
+#endif
     ADD_ALL_TESTS(test_EVP_Enveloped, 2);
     ADD_ALL_TESTS(test_d2i_AutoPrivateKey, OSSL_NELEM(keydata));
     ADD_TEST(test_privatekey_to_pkcs8);
@@ -4814,6 +5176,7 @@ int setup_tests(void)
 #endif
     ADD_TEST(test_RSA_get_set_params);
     ADD_TEST(test_RSA_OAEP_set_get_params);
+    ADD_TEST(test_RSA_OAEP_set_null_label);
 #if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
     ADD_TEST(test_decrypt_null_chunks);
 #endif
@@ -4878,6 +5241,12 @@ int setup_tests(void)
     ADD_ALL_TESTS(test_ecx_not_private_key, OSSL_NELEM(keys));
 #endif
 
+    /* Test cases for CVE-2023-5363 */
+    ADD_TEST(test_aes_gcm_ivlen_change_cve_2023_5363);
+#ifndef OPENSSL_NO_RC4
+    ADD_TEST(test_aes_rc4_keylen_change_cve_2023_5363);
+#endif
+
     return 1;
 }
 
diff --git a/deps/openssl/openssl/test/ffc_internal_test.c b/deps/openssl/openssl/test/ffc_internal_test.c
index 7f8f44c8a9fdc7..83dec13c8c9b33 100644
--- a/deps/openssl/openssl/test/ffc_internal_test.c
+++ b/deps/openssl/openssl/test/ffc_internal_test.c
@@ -455,22 +455,20 @@ static int ffc_public_validate_test(void)
     if (!TEST_true(BN_set_word(pub, 1)))
         goto err;
     BN_set_negative(pub, 1);
-    /* Fail if public key is negative */
-    if (!TEST_false(ossl_ffc_validate_public_key(params, pub, &res)))
+    /* Check must succeed but set res if public key is negative */
+    if (!TEST_true(ossl_ffc_validate_public_key(params, pub, &res)))
         goto err;
     if (!TEST_int_eq(FFC_ERROR_PUBKEY_TOO_SMALL, res))
         goto err;
     if (!TEST_true(BN_set_word(pub, 0)))
         goto err;
-    if (!TEST_int_eq(FFC_ERROR_PUBKEY_TOO_SMALL, res))
-        goto err;
-    /* Fail if public key is zero */
-    if (!TEST_false(ossl_ffc_validate_public_key(params, pub, &res)))
+    /* Check must succeed but set res if public key is zero */
+    if (!TEST_true(ossl_ffc_validate_public_key(params, pub, &res)))
         goto err;
     if (!TEST_int_eq(FFC_ERROR_PUBKEY_TOO_SMALL, res))
         goto err;
-    /* Fail if public key is 1 */
-    if (!TEST_false(ossl_ffc_validate_public_key(params, BN_value_one(), &res)))
+    /* Check must succeed but set res if public key is 1 */
+    if (!TEST_true(ossl_ffc_validate_public_key(params, BN_value_one(), &res)))
         goto err;
     if (!TEST_int_eq(FFC_ERROR_PUBKEY_TOO_SMALL, res))
         goto err;
@@ -482,24 +480,24 @@ static int ffc_public_validate_test(void)
 
     if (!TEST_ptr(BN_copy(pub, params->p)))
         goto err;
-    /* Fail if public key = p */
-    if (!TEST_false(ossl_ffc_validate_public_key(params, pub, &res)))
+    /* Check must succeed but set res if public key = p */
+    if (!TEST_true(ossl_ffc_validate_public_key(params, pub, &res)))
         goto err;
     if (!TEST_int_eq(FFC_ERROR_PUBKEY_TOO_LARGE, res))
         goto err;
 
     if (!TEST_true(BN_sub_word(pub, 1)))
         goto err;
-    /* Fail if public key = p - 1 */
-    if (!TEST_false(ossl_ffc_validate_public_key(params, pub, &res)))
+    /* Check must succeed but set res if public key = p - 1 */
+    if (!TEST_true(ossl_ffc_validate_public_key(params, pub, &res)))
         goto err;
     if (!TEST_int_eq(FFC_ERROR_PUBKEY_TOO_LARGE, res))
         goto err;
 
     if (!TEST_true(BN_sub_word(pub, 1)))
         goto err;
-    /* Fail if public key is not related to p & q */
-    if (!TEST_false(ossl_ffc_validate_public_key(params, pub, &res)))
+    /* Check must succeed but set res if public key is not related to p & q */
+    if (!TEST_true(ossl_ffc_validate_public_key(params, pub, &res)))
         goto err;
     if (!TEST_int_eq(FFC_ERROR_PUBKEY_INVALID, res))
         goto err;
@@ -510,14 +508,14 @@ static int ffc_public_validate_test(void)
     if (!TEST_true(ossl_ffc_validate_public_key(params, pub, &res)))
         goto err;
 
-    /* Fail if params is NULL */
-    if (!TEST_false(ossl_ffc_validate_public_key(NULL, pub, &res)))
+    /* Check must succeed but set res if params is NULL */
+    if (!TEST_true(ossl_ffc_validate_public_key(NULL, pub, &res)))
         goto err;
     if (!TEST_int_eq(FFC_ERROR_PASSED_NULL_PARAM, res))
         goto err;
     res = -1;
-    /* Fail if pubkey is NULL */
-    if (!TEST_false(ossl_ffc_validate_public_key(params, NULL, &res)))
+    /* Check must succeed but set res if pubkey is NULL */
+    if (!TEST_true(ossl_ffc_validate_public_key(params, NULL, &res)))
         goto err;
     if (!TEST_int_eq(FFC_ERROR_PASSED_NULL_PARAM, res))
         goto err;
@@ -525,8 +523,8 @@ static int ffc_public_validate_test(void)
 
     BN_free(params->p);
     params->p = NULL;
-    /* Fail if params->p is NULL */
-    if (!TEST_false(ossl_ffc_validate_public_key(params, pub, &res)))
+    /* Check must succeed but set res if params->p is NULL */
+    if (!TEST_true(ossl_ffc_validate_public_key(params, pub, &res)))
         goto err;
     if (!TEST_int_eq(FFC_ERROR_PASSED_NULL_PARAM, res))
         goto err;
diff --git a/deps/openssl/openssl/test/pbetest.c b/deps/openssl/openssl/test/pbetest.c
index d73ae66fa536af..cfffc2b9323327 100644
--- a/deps/openssl/openssl/test/pbetest.c
+++ b/deps/openssl/openssl/test/pbetest.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2021-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -15,6 +15,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #if !defined OPENSSL_NO_RC4 && !defined OPENSSL_NO_MD5 \
     || !defined OPENSSL_NO_DES && !defined OPENSSL_NO_SHA1
@@ -123,8 +125,27 @@ static int test_pkcs5_pbe_des_sha1(void)
 }
 #endif
 
+#ifdef OPENSSL_NO_AUTOLOAD_CONFIG
+/*
+ * For configurations where we are not autoloading configuration, we need
+ * to access the legacy provider.  The easiest way is to load both the
+ * legacy and default providers directly and unload them on termination.
+ */
+static OSSL_PROVIDER *legacy, *dflt;
+#endif
+
 int setup_tests(void)
 {
+#ifdef OPENSSL_NO_AUTOLOAD_CONFIG
+    /* Load required providers if not done via configuration */
+    legacy = OSSL_PROVIDER_load(NULL, "legacy");
+    dflt = OSSL_PROVIDER_load(NULL, "default");
+    if (!TEST_ptr(legacy) || !TEST_ptr(dflt)) {
+        cleanup_tests();
+        return -1;
+    }
+#endif
+
 #if !defined OPENSSL_NO_RC4 && !defined OPENSSL_NO_MD5
     ADD_TEST(test_pkcs5_pbe_rc4_md5);
 #endif
@@ -134,3 +155,13 @@ int setup_tests(void)
 
     return 1;
 }
+
+#ifdef OPENSSL_NO_AUTOLOAD_CONFIG
+void cleanup_tests(void)
+{
+    /* Dispose of providers */
+    OSSL_PROVIDER_unload(legacy);
+    OSSL_PROVIDER_unload(dflt);
+    legacy = dflt = NULL;
+}
+#endif
diff --git a/deps/openssl/openssl/test/pemtest.c b/deps/openssl/openssl/test/pemtest.c
index c8c88bf1f1656f..bf970983654439 100644
--- a/deps/openssl/openssl/test/pemtest.c
+++ b/deps/openssl/openssl/test/pemtest.c
@@ -125,6 +125,35 @@ static int test_empty_payload(void)
     return ret;
 }
 
+static int test_protected_params(void)
+{
+    BIO *b;
+    static char *protectedpay =
+        "-----BEGIN RSA PRIVATE KEY-----\n"
+        "Proc-Type: 4,ENCRYPTED\n"
+        "DEK-Info: AES-256-CBC,4A44448ED28992710556549B35100CEA\n"
+        "\n"
+        "Xw3INxKeH+rUUF57mjATpvj6zknVhedwrlRmRvnwlLv5wqIy5Ae4UVLPh7SUswfC\n"
+        "-----END RSA PRIVATE KEY-----\n";
+    EVP_PKEY *pkey = NULL;
+    int ret = 0;
+
+    b = BIO_new_mem_buf(protectedpay, strlen(protectedpay));
+    if (!TEST_ptr(b))
+        return 0;
+
+    /* Expected to fail because we cannot decrypt protected PEM files */
+    pkey = PEM_read_bio_Parameters(b, NULL);
+    if (!TEST_ptr_null(pkey))
+        goto err;
+
+    ret = 1;
+ err:
+    EVP_PKEY_free(pkey);
+    BIO_free(b);
+    return ret;
+}
+
 int setup_tests(void)
 {
     if (!TEST_ptr(pemfile = test_get_argument(0)))
@@ -133,5 +162,6 @@ int setup_tests(void)
     ADD_TEST(test_invalid);
     ADD_TEST(test_cert_key_cert);
     ADD_TEST(test_empty_payload);
+    ADD_TEST(test_protected_params);
     return 1;
 }
diff --git a/deps/openssl/openssl/test/pkcs12_format_test.c b/deps/openssl/openssl/test/pkcs12_format_test.c
index d4129d2522bce8..c142093f72bbbc 100644
--- a/deps/openssl/openssl/test/pkcs12_format_test.c
+++ b/deps/openssl/openssl/test/pkcs12_format_test.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -792,6 +792,70 @@ static int pkcs12_create_test(void)
 }
 #endif
 
+static int pkcs12_recreate_test(void)
+{
+    int ret = 0;
+    X509 *cert = NULL;
+    X509 *cert_parsed = NULL;
+    EVP_PKEY *pkey = NULL;
+    EVP_PKEY *pkey_parsed = NULL;
+    PKCS12 *p12 = NULL;
+    PKCS12 *p12_parsed = NULL;
+    PKCS12 *p12_recreated = NULL;
+    const unsigned char *cert_bytes = CERT1;
+    const unsigned char *key_bytes = KEY1;
+    BIO *bio = NULL;
+
+    cert = d2i_X509(NULL, &cert_bytes, sizeof(CERT1));
+    if (!TEST_ptr(cert))
+        goto err;
+    pkey = d2i_AutoPrivateKey(NULL, &key_bytes, sizeof(KEY1));
+    if (!TEST_ptr(pkey))
+        goto err;
+    p12 = PKCS12_create("pass", NULL, pkey, cert, NULL, NID_aes_256_cbc,
+                        NID_aes_256_cbc, 2, 1, 0);
+    if (!TEST_ptr(p12))
+        goto err;
+    if (!TEST_int_eq(ERR_peek_error(), 0))
+        goto err;
+
+    bio = BIO_new(BIO_s_mem());
+    if (!TEST_ptr(bio))
+        goto err;
+    if (!TEST_int_eq(i2d_PKCS12_bio(bio, p12), 1))
+        goto err;
+    p12_parsed = PKCS12_init_ex(NID_pkcs7_data, testctx, NULL);
+    if (!TEST_ptr(p12_parsed))
+        goto err;
+    p12_parsed = d2i_PKCS12_bio(bio, &p12_parsed);
+    if (!TEST_ptr(p12_parsed))
+        goto err;
+    if (!TEST_int_eq(PKCS12_parse(p12_parsed, "pass", &pkey_parsed,
+                                  &cert_parsed, NULL), 1))
+        goto err;
+
+    /* cert_parsed also contains auxiliary data */
+    p12_recreated = PKCS12_create("new_pass", NULL, pkey_parsed, cert_parsed,
+                                  NULL, NID_aes_256_cbc, NID_aes_256_cbc,
+                                  2, 1, 0);
+    if (!TEST_ptr(p12_recreated))
+        goto err;
+    if (!TEST_int_eq(ERR_peek_error(), 0))
+        goto err;
+
+    ret = 1;
+err:
+    BIO_free(bio);
+    PKCS12_free(p12);
+    PKCS12_free(p12_parsed);
+    PKCS12_free(p12_recreated);
+    EVP_PKEY_free(pkey);
+    EVP_PKEY_free(pkey_parsed);
+    X509_free(cert);
+    X509_free(cert_parsed);
+    return ret;
+}
+
 typedef enum OPTION_choice {
     OPT_ERR = -1,
     OPT_EOF = 0,
@@ -873,6 +937,8 @@ int setup_tests(void)
     if (default_libctx)
         ADD_TEST(pkcs12_create_test);
 #endif
+    if (default_libctx)
+        ADD_TEST(pkcs12_recreate_test);
     ADD_ALL_TESTS(test_single_key_enc_pass, OSSL_NELEM(passwords));
     ADD_ALL_TESTS(test_single_key_enc_iter, OSSL_NELEM(iters));
     ADD_TEST(test_single_key_with_attrs);
diff --git a/deps/openssl/openssl/test/property_test.c b/deps/openssl/openssl/test/property_test.c
index 6a405e364baf10..1005b9952c9a6c 100644
--- a/deps/openssl/openssl/test/property_test.c
+++ b/deps/openssl/openssl/test/property_test.c
@@ -616,6 +616,9 @@ static struct {
     { "", "" },
     { "fips=3", "fips=3" },
     { "fips=-3", "fips=-3" },
+    { "provider='foo bar'", "provider='foo bar'" },
+    { "provider=\"foo bar'\"", "provider=\"foo bar'\"" },
+    { "provider=abc***", "provider='abc***'" },
     { NULL, "" }
 };
 
diff --git a/deps/openssl/openssl/test/provider_internal_test.c b/deps/openssl/openssl/test/provider_internal_test.c
index cb7d5efcf54889..1fe8fb0cc5c412 100644
--- a/deps/openssl/openssl/test/provider_internal_test.c
+++ b/deps/openssl/openssl/test/provider_internal_test.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -83,6 +83,7 @@ static int test_loaded_provider(void)
         && test_provider(prov, expected_greeting1(name));
 }
 
+# ifndef OPENSSL_NO_AUTOLOAD_CONFIG
 static int test_configured_provider(void)
 {
     const char *name = "p_test_configured";
@@ -95,6 +96,7 @@ static int test_configured_provider(void)
         TEST_ptr(prov = ossl_provider_find(NULL, name, 0))
         && test_provider(prov, expected_greeting);
 }
+# endif
 #endif
 
 static int test_cache_flushes(void)
@@ -139,7 +141,9 @@ int setup_tests(void)
     ADD_TEST(test_builtin_provider);
 #ifndef NO_PROVIDER_MODULE
     ADD_TEST(test_loaded_provider);
+# ifndef OPENSSL_NO_AUTOLOAD_CONFIG
     ADD_TEST(test_configured_provider);
+# endif
 #endif
     ADD_TEST(test_cache_flushes);
     return 1;
diff --git a/deps/openssl/openssl/test/recipes/05-test_rand.t b/deps/openssl/openssl/test/recipes/05-test_rand.t
index 3f352db9df3a6d..aa012c1907adee 100644
--- a/deps/openssl/openssl/test/recipes/05-test_rand.t
+++ b/deps/openssl/openssl/test/recipes/05-test_rand.t
@@ -1,5 +1,5 @@
 #! /usr/bin/env perl
-# Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the Apache License 2.0 (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
@@ -29,12 +29,12 @@ SKIP: {
     @randdata = run(app(['openssl', 'rand', '-engine', 'ossltest', '-hex', '16' ]),
                     capture => 1, statusvar => \$success);
     chomp(@randdata);
-    ok($success and $randdata[0] eq $expected,
+    ok($success && $randdata[0] eq $expected,
        "rand with ossltest: Check rand output is as expected");
 
     @randdata = run(app(['openssl', 'rand', '-engine', 'dasync', '-hex', '16' ]),
                     capture => 1, statusvar => \$success);
     chomp(@randdata);
-    ok($success and length($randdata[0]) == 32,
+    ok($success && length($randdata[0]) == 32,
        "rand with dasync: Check rand output is of expected length");
 }
diff --git a/deps/openssl/openssl/test/recipes/15-test_rsapss.t b/deps/openssl/openssl/test/recipes/15-test_rsapss.t
index c566ade933e9d6..44721a32372f78 100644
--- a/deps/openssl/openssl/test/recipes/15-test_rsapss.t
+++ b/deps/openssl/openssl/test/recipes/15-test_rsapss.t
@@ -1,5 +1,5 @@
 #! /usr/bin/env perl
-# Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2017-2023 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the Apache License 2.0 (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
@@ -16,7 +16,7 @@ use OpenSSL::Test::Utils;
 
 setup("test_rsapss");
 
-plan tests => 11;
+plan tests => 13;
 
 #using test/testrsa.pem which happens to be a 512 bit RSA
 ok(run(app(['openssl', 'dgst', '-sign', srctop_file('test', 'testrsa.pem'), '-sha1',
@@ -79,6 +79,8 @@ ok(run(app(['openssl', 'dgst', '-prverify', srctop_file('test', 'testrsa.pem'),
    my $rsapss = "rsapss.key";
    ok(run(app(['openssl', 'genpkey', '-algorithm', 'RSA-PSS',
                '-pkeyopt', 'rsa_keygen_bits:1024',
+               '-pkeyopt', 'rsa_keygen_pubexp:65537',
+               '-pkeyopt', 'rsa_keygen_primes:2',
                '--out', $rsapss])));
    ok(run(app(['openssl', 'rsa', '-check',
                '-in', $rsapss])));
@@ -87,3 +89,11 @@ ok(run(app(['openssl', 'dgst', '-prverify', srctop_file('test', 'testrsa.pem'),
 ok(!run(app([ 'openssl', 'rsa',
              '-in' => data_file('negativesaltlen.pem')],
              '-out' => 'badout')));
+
+ok(run(app(['openssl', 'genpkey', '-algorithm', 'RSA-PSS', '-pkeyopt', 'rsa_keygen_bits:1024',
+            '-pkeyopt', 'rsa_pss_keygen_md:SHA256', '-pkeyopt', 'rsa_pss_keygen_saltlen:10',
+            '-out', 'testrsapss.pem'])),
+   "openssl genpkey RSA-PSS with pss parameters");
+ok(run(app(['openssl', 'pkey', '-in', 'testrsapss.pem', '-pubout', '-text'])),
+   "openssl pkey, execute rsa_pub_encode with pss parameters");
+unlink 'testrsapss.pem';
diff --git a/deps/openssl/openssl/test/recipes/25-test_req.t b/deps/openssl/openssl/test/recipes/25-test_req.t
index e615f1b338855f..8c8274aee699ce 100644
--- a/deps/openssl/openssl/test/recipes/25-test_req.t
+++ b/deps/openssl/openssl/test/recipes/25-test_req.t
@@ -1,5 +1,5 @@
 #! /usr/bin/env perl
-# Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the Apache License 2.0 (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
@@ -15,7 +15,7 @@ use OpenSSL::Test qw/:DEFAULT srctop_file/;
 
 setup("test_req");
 
-plan tests => 44;
+plan tests => 46;
 
 require_ok(srctop_file('test', 'recipes', 'tconversion.pl'));
 
@@ -473,3 +473,14 @@ my $cert = "self-signed_CA_with_keyUsages.pem";
 generate_cert($cert, "-in", srctop_file(@certs, "ext-check.csr"),
     "-copy_extensions", "copy");
 has_keyUsage($cert, 1);
+
+# Generate cert using req with '-modulus'
+ok(run(app(["openssl", "req", "-x509", "-new", "-days", "365",
+            "-key", srctop_file("test", "testrsa.pem"),
+            "-config", srctop_file('test', 'test.cnf'),
+            "-out", "testreq-cert.pem",
+            "-modulus"])), "cert req creation - with -modulus");
+
+# Verify cert
+ok(run(app(["openssl", "x509", "-in", "testreq-cert.pem",
+            "-noout", "-text"])), "cert verification");
diff --git a/deps/openssl/openssl/test/recipes/30-test_defltfips.t b/deps/openssl/openssl/test/recipes/30-test_defltfips.t
index 426bd660d1fd61..c8f145405b2b4e 100644
--- a/deps/openssl/openssl/test/recipes/30-test_defltfips.t
+++ b/deps/openssl/openssl/test/recipes/30-test_defltfips.t
@@ -1,5 +1,5 @@
 #! /usr/bin/env perl
-# Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the Apache License 2.0 (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
@@ -21,6 +21,9 @@ BEGIN {
 use lib srctop_dir('Configurations');
 use lib bldtop_dir('.');
 
+plan skip_all => "Configuration loading is turned off"
+    if disabled("autoload-config");
+
 my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0);
 
 plan tests =>
diff --git a/deps/openssl/openssl/test/recipes/30-test_evp.t b/deps/openssl/openssl/test/recipes/30-test_evp.t
index 0a036b7da01826..af823515f9bd64 100644
--- a/deps/openssl/openssl/test/recipes/30-test_evp.t
+++ b/deps/openssl/openssl/test/recipes/30-test_evp.t
@@ -1,5 +1,5 @@
 #! /usr/bin/env perl
-# Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the Apache License 2.0 (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
@@ -173,7 +173,8 @@ sub test_errors { # actually tests diagnostics of OSSL_STORE
 }
 
 SKIP: {
-    skip "DSA not disabled", 2 if !disabled("dsa");
+    skip "DSA not disabled or ERR disabled", 2
+        if !disabled("dsa") || disabled("err");
 
     ok(test_errors(key => 'server-dsa-key.pem',
                    out => 'server-dsa-key.err'),
diff --git a/deps/openssl/openssl/test/recipes/80-test_cms.t b/deps/openssl/openssl/test/recipes/80-test_cms.t
index cabbe3ecdf1a5d..be779233130e20 100644
--- a/deps/openssl/openssl/test/recipes/80-test_cms.t
+++ b/deps/openssl/openssl/test/recipes/80-test_cms.t
@@ -50,7 +50,7 @@ my ($no_des, $no_dh, $no_dsa, $no_ec, $no_ec2m, $no_rc2, $no_zlib)
 
 $no_rc2 = 1 if disabled("legacy");
 
-plan tests => 16;
+plan tests => 18;
 
 ok(run(test(["pkcs7_test"])), "test pkcs7");
 
@@ -994,3 +994,28 @@ with({ exit_checker => sub { return shift == 6; } },
                    ])),
             "Check failure during BIO setup with -stream is handled correctly");
     });
+
+# Test case for return value mis-check reported in #21986
+with({ exit_checker => sub { return shift == 3; } },
+    sub {
+        SKIP: {
+          skip "DSA is not supported in this build", 1 if $no_dsa;
+
+          ok(run(app(['openssl', 'cms', '-sign',
+                      '-in', srctop_file("test", "smcont.txt"),
+                      '-signer', srctop_file("test/smime-certs", "smdsa1.pem"),
+                      '-md', 'SHAKE256'])),
+            "issue#21986");
+        }
+    });
+
+# Test for problem reported in #22225
+with({ exit_checker => sub { return shift == 3; } },
+    sub {
+	ok(run(app(['openssl', 'cms', '-encrypt',
+		    '-in', srctop_file("test", "smcont.txt"),
+		    '-aes-256-ctr', '-recip',
+		    catfile($smdir, "smec1.pem"),
+		   ])),
+	   "Check for failure when cipher does not have an assigned OID (issue#22225)");
+     });
diff --git a/deps/openssl/openssl/test/recipes/99-test_fuzz_x509.t b/deps/openssl/openssl/test/recipes/99-test_fuzz_x509.t
index 9a1e3a19cadce4..b0b86365d10193 100644
--- a/deps/openssl/openssl/test/recipes/99-test_fuzz_x509.t
+++ b/deps/openssl/openssl/test/recipes/99-test_fuzz_x509.t
@@ -1,5 +1,5 @@
 #!/usr/bin/env perl
-# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the Apache License 2.0 (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
@@ -15,6 +15,9 @@ use OpenSSL::Test::Utils;
 my $fuzzer = "x509";
 setup("test_fuzz_${fuzzer}");
 
+plan skip_all => "This test requires ocsp support"
+    if disabled("ocsp");
+
 plan tests => 2; # one more due to below require_ok(...)
 
 require_ok(srctop_file('test','recipes','fuzz.pl'));
diff --git a/deps/openssl/openssl/test/rsa_test.c b/deps/openssl/openssl/test/rsa_test.c
index 62a54df74d89db..18345b431a7cc5 100644
--- a/deps/openssl/openssl/test/rsa_test.c
+++ b/deps/openssl/openssl/test/rsa_test.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -391,10 +391,126 @@ static int test_rsa_security_bit(int n)
     return r;
 }
 
+static int test_EVP_rsa_legacy_key(void)
+{
+    int ret;
+    size_t buflen = 384;
+    size_t msglen = 64;
+    unsigned char sigbuf[384];
+    unsigned char msgbuf[64];
+    BIGNUM *p;
+    BIGNUM *q;
+    BIGNUM *n;
+    BIGNUM *d;
+    BIGNUM *e;
+    RSA *rsa;
+    const EVP_MD *md;
+    EVP_MD_CTX *ctx = NULL;
+    EVP_PKEY *pkey = NULL;
+
+    unsigned char n_data[] = {
+    0x00, 0xc7, 0x28, 0x7a, 0x28, 0x91, 0x51, 0xa5, 0xe8, 0x3c, 0x45, 0xcf,
+    0x1d, 0xa9, 0x69, 0x7a, 0x0d, 0xdb, 0xdd, 0x8f, 0xe2, 0xde, 0x85, 0xdd,
+    0x85, 0x6d, 0x8f, 0x78, 0x20, 0xd6, 0xe, 0xe5, 0x06, 0xcb, 0x9c, 0xd6,
+    0xd3, 0xca, 0xef, 0x1d, 0x80, 0xd3, 0x18, 0x23, 0x91, 0x5c, 0xe5, 0xc8,
+    0x44, 0x37, 0x56, 0x1b, 0x68, 0x7f, 0x08, 0xa3, 0x1c, 0xf6, 0xe8, 0x11,
+    0x38, 0x0f, 0x2e, 0xad, 0xb1, 0x89, 0x8b, 0x08, 0xe8, 0x35, 0xaf, 0x3b,
+    0xfe, 0x37, 0x8d, 0x21, 0xd5, 0x3f, 0x1f, 0x4b, 0x01, 0x30, 0xd8, 0xd0,
+    0x24, 0xf7, 0xab, 0x57, 0xad, 0xac, 0xbc, 0x53, 0x6d, 0x84, 0x8e, 0xa1,
+    0xb2, 0x5b, 0x8e, 0xe7, 0xb3, 0xac, 0xfc, 0x60, 0x22, 0x10, 0x1e, 0x99,
+    0xfa, 0xa0, 0x60, 0x00, 0x69, 0x5f, 0x8e, 0xca, 0x6d, 0x9c, 0xee, 0x5e,
+    0x84, 0x4e, 0x53, 0x83, 0x42, 0x76, 0x4d, 0xb8, 0xc1, 0xeb, 0x4e, 0x3d,
+    0xc3, 0xce, 0xac, 0x79, 0xbb, 0x29, 0x5d, 0x92, 0x33, 0x6e, 0xcf, 0x8f,
+    0x5a, 0xf0, 0xb3, 0xb5, 0xdc, 0xd5, 0xa3, 0xaf, 0x40, 0x4b, 0x0f, 0x05,
+    0xac, 0x46, 0x53, 0x2d, 0x5f, 0x20, 0x96, 0x42, 0xa8, 0x47, 0x61, 0x54,
+    0x05, 0x2c, 0x8a, 0x26, 0x5d, 0x92, 0x1d, 0x01, 0x2a, 0x27, 0x8a, 0xfc,
+    0x64, 0x24, 0x5c, 0x34, 0xde, 0x92, 0xc6, 0x82, 0xea, 0x4d, 0xe2, 0x52,
+    0xe5, 0xad, 0x62, 0x00, 0xc6, 0xc8, 0xe9, 0x0c, 0x22, 0xf0, 0x9e, 0xbe,
+    0xdc, 0x51, 0x58, 0xad, 0x3b, 0xba, 0x2e, 0x45, 0x65, 0xcc, 0x5b, 0x55,
+    0x46, 0x67, 0x18, 0x4a, 0x80, 0x67, 0x5b, 0x84, 0x7f, 0x13, 0x37, 0x45,
+    0xd8, 0x03, 0xc6, 0x22, 0xc3, 0x4a, 0x46, 0x6b, 0xde, 0x50, 0xbf, 0x16,
+    0x0a, 0x23, 0x0b, 0xaa, 0x50, 0x54, 0xf6, 0x20, 0x83, 0x74, 0x33, 0x97,
+    0x2e, 0xf2, 0x8e, 0x7e, 0x13 };
+
+    unsigned char e_data[]  = { 0x01, 0x00, 0x01 };
+
+    unsigned char d_data[] = {
+    0x09, 0x2d, 0xcb, 0xe7, 0x87, 0xbf, 0x10, 0x1a, 0xf2, 0x80, 0x33, 0x2a,
+    0x06, 0x4f, 0x56, 0xb1, 0x41, 0xd3, 0x65, 0xd8, 0xca, 0x71, 0xb8, 0x02,
+    0x78, 0xc8, 0xb6, 0x7c, 0x28, 0xf4, 0x6c, 0xe8, 0xd1, 0xc4, 0x92, 0x40,
+    0x23, 0xa7, 0xbe, 0x9f, 0xdb, 0xda, 0xce, 0x74, 0xda, 0x27, 0xbb, 0x01,
+    0xad, 0xdd, 0x39, 0x99, 0x28, 0xd5, 0xb0, 0x92, 0xda, 0xac, 0x5a, 0x72,
+    0xcf, 0x7c, 0x52, 0xc4, 0x0e, 0x77, 0x4a, 0x7b, 0x4d, 0x52, 0x1c, 0xbd,
+    0x3c, 0x39, 0x34, 0x78, 0x7c, 0x16, 0xc8, 0xa1, 0xae, 0xeb, 0x27, 0x38,
+    0xb4, 0xf3, 0x80, 0x30, 0x80, 0x78, 0x13, 0x8e, 0x46, 0x20, 0x3e, 0xc2,
+    0x96, 0x26, 0xb1, 0x76, 0x1e, 0x00, 0x69, 0xbb, 0xd8, 0x2b, 0x58, 0xe4,
+    0x6c, 0xb4, 0xd0, 0x00, 0x0b, 0x47, 0xec, 0xfb, 0x7d, 0x52, 0x9d, 0x27,
+    0x92, 0xe6, 0x95, 0x73, 0xa0, 0x39, 0x37, 0xcd, 0x1f, 0x60, 0x13, 0x1c,
+    0x87, 0x9d, 0xa7, 0x91, 0x90, 0xf9, 0x36, 0xc5, 0xfa, 0x3f, 0xf9, 0x7f,
+    0x50, 0xf8, 0xb3, 0x54, 0x65, 0xff, 0x6f, 0xa6, 0x22, 0xcc, 0x4a, 0x1e,
+    0x49, 0x3f, 0x07, 0xc6, 0xf2, 0x65, 0x73, 0x13, 0x1b, 0x2d, 0xb6, 0x15,
+    0xff, 0xcd, 0x9a, 0x1c, 0xea, 0xef, 0x58, 0x56, 0x91, 0x2d, 0x47, 0x81,
+    0x56, 0x0d, 0xc3, 0xb0, 0x47, 0x58, 0x8d, 0x05, 0x7d, 0x5b, 0xc0, 0x22,
+    0xa4, 0xf0, 0x2e, 0x70, 0x36, 0x01, 0x89, 0xa1, 0x71, 0xed, 0x76, 0xe9,
+    0x8d, 0xf5, 0x49, 0xaf, 0x11, 0xbe, 0xe4, 0xd4, 0x48, 0x92, 0xb6, 0x5b,
+    0xc2, 0x04, 0xd4, 0x0c, 0x5c, 0x8b, 0xe3, 0xfa, 0x29, 0x63, 0x86, 0xb4,
+    0x10, 0xad, 0x32, 0x07, 0x85, 0xe2, 0x43, 0x76, 0x16, 0x90, 0xab, 0xdf,
+    0xb3, 0x36, 0x0a, 0xc4, 0x49, 0x7b, 0x95, 0x48, 0x50, 0x72, 0x8f, 0x7d,
+    0xf4, 0xfa, 0x60, 0xc1 };
+
+    unsigned char p_data[] = {
+    0x00, 0xed, 0xf7, 0xa7, 0x00, 0x5a, 0xbb, 0xd1, 0x52, 0x65, 0x9b, 0xec,
+    0xfe, 0x27, 0x8b, 0xe2, 0xbe, 0x40, 0x8c, 0x2f, 0x6f, 0xb4, 0x26, 0xb2,
+    0xbe, 0x45, 0x4b, 0x3b, 0x5a, 0xaa, 0xc6, 0xaa, 0xfa, 0xc1, 0x3a, 0xa9,
+    0xa1, 0xba, 0xb7, 0x86, 0x1a, 0x98, 0x15, 0x5f, 0x5c, 0x1c, 0x57, 0x78,
+    0x78, 0x6a, 0x13, 0xc2, 0x40, 0x7d, 0x07, 0x87, 0x47, 0xc6, 0x96, 0xd5,
+    0x92, 0xc9, 0x65, 0x2c, 0xfe, 0xbb, 0xe0, 0xd6, 0x76, 0x25, 0x5a, 0xa3,
+    0xdf, 0x97, 0x4b, 0x64, 0xfd, 0x3b, 0x2b, 0xbc, 0xfb, 0x80, 0xad, 0x3b,
+    0x7d, 0x1f, 0x48, 0x56, 0x27, 0xf7, 0x2f, 0x8e, 0x92, 0x07, 0xa8, 0x9f,
+    0xbc, 0x5a, 0xce, 0xfa, 0xd5, 0x67, 0xad, 0xf4, 0xbf, 0xe0, 0xc9, 0x3e,
+    0x8e, 0xb5, 0x90, 0x58, 0x54, 0x92, 0x9f, 0xda, 0x36, 0xc0, 0x0d, 0x57,
+    0xfe, 0x6c, 0x23, 0x63, 0x8b, 0xd1, 0x1e, 0x4f, 0xd3 };
+
+    unsigned char q_data[] = {
+    0x00, 0xd6, 0x3f, 0xf5, 0xee, 0xff, 0x4d, 0x7d, 0x8c, 0x1a, 0x85, 0x5d,
+    0x3c, 0x4f, 0x9d, 0xdf, 0xc7, 0x68, 0x27, 0x7f, 0xe4, 0x4f, 0x4f, 0xd7,
+    0xa2, 0x3b, 0xcd, 0x4a, 0x34, 0xd8, 0x55, 0x4a, 0x3e, 0x8e, 0xb3, 0xa8,
+    0xe9, 0x8a, 0xc5, 0x94, 0xd1, 0x09, 0x32, 0x4b, 0x79, 0x8d, 0x7b, 0x03,
+    0x0b, 0x5d, 0xca, 0x91, 0x41, 0xbc, 0x82, 0xc3, 0x89, 0x67, 0x4d, 0x03,
+    0x68, 0x03, 0x2d, 0x0e, 0x4e, 0x97, 0x6c, 0xf6, 0x3e, 0x1f, 0xf4, 0x50,
+    0x06, 0x5d, 0x05, 0x22, 0xf2, 0xf8, 0xf2, 0xde, 0xad, 0x2e, 0x9d, 0xc3,
+    0x97, 0x1b, 0xc3, 0x75, 0xe7, 0x86, 0xde, 0xc5, 0x11, 0x89, 0xed, 0x6a,
+    0x13, 0x14, 0x23, 0x4b, 0x98, 0x81, 0xf7, 0xd4, 0x1c, 0xee, 0x30, 0x92,
+    0x85, 0x20, 0x4f, 0x35, 0x02, 0xfa, 0xda, 0x14, 0x77, 0xfa, 0x08, 0x34,
+    0x60, 0xc7, 0x93, 0x72, 0xdc, 0xc4, 0x18, 0x70, 0xc1 };
+
+    memset(msgbuf, 0xef, 64);
+
+    ret = (TEST_ptr((p = BN_bin2bn(p_data, sizeof(p_data), NULL)))
+           && TEST_ptr((q = BN_bin2bn(q_data, sizeof(q_data), NULL)))
+           && TEST_ptr((n = BN_bin2bn(n_data, sizeof(n_data), NULL)))
+           && TEST_ptr((d = BN_bin2bn(d_data, sizeof(d_data), NULL)))
+           && TEST_ptr((e = BN_bin2bn(e_data, sizeof(e_data), NULL)))
+           && TEST_ptr((rsa = RSA_new()))
+           && TEST_ptr((md = EVP_sha256()))
+           && TEST_ptr((ctx = EVP_MD_CTX_new()))
+           && TEST_ptr((pkey = EVP_PKEY_new()))
+           && TEST_true(RSA_set0_factors(rsa, p, q))
+           && TEST_true(RSA_set0_key(rsa, n, e, d))
+           && TEST_true(EVP_PKEY_assign_RSA(pkey, rsa))
+           && TEST_true(EVP_DigestSignInit(ctx, NULL, md, NULL, pkey))
+           && TEST_true(EVP_DigestSign(ctx, sigbuf, &buflen, msgbuf, msglen)));
+
+    EVP_MD_CTX_free(ctx);
+    EVP_PKEY_free(pkey);
+    return ret;
+}
+
 int setup_tests(void)
 {
     ADD_ALL_TESTS(test_rsa_pkcs1, 3);
     ADD_ALL_TESTS(test_rsa_oaep, 3);
     ADD_ALL_TESTS(test_rsa_security_bit, OSSL_NELEM(rsa_security_bits_cases));
+    ADD_TEST(test_EVP_rsa_legacy_key);
     return 1;
 }
diff --git a/deps/openssl/openssl/test/ssl_old_test.c b/deps/openssl/openssl/test/ssl_old_test.c
index 91c8b5b7b535f6..6b56754b824017 100644
--- a/deps/openssl/openssl/test/ssl_old_test.c
+++ b/deps/openssl/openssl/test/ssl_old_test.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
  * Copyright 2005 Nokia. All rights reserved.
  *
@@ -1525,8 +1525,10 @@ int main(int argc, char *argv[])
             ERR_print_errors(bio_err);
             goto end;
         }
-        SSL_CTX_set0_tmp_dh_pkey(s_ctx, dhpkey);
-        SSL_CTX_set0_tmp_dh_pkey(s_ctx2, dhpkey);
+        if (!SSL_CTX_set0_tmp_dh_pkey(s_ctx, dhpkey))
+            EVP_PKEY_free(dhpkey);
+        if (!SSL_CTX_set0_tmp_dh_pkey(s_ctx2, dhpkey))
+            EVP_PKEY_free(dhpkey);
     }
 #endif
 
diff --git a/deps/openssl/openssl/test/sslapitest.c b/deps/openssl/openssl/test/sslapitest.c
index 3d0319ee3881af..a7df6552eb16b2 100644
--- a/deps/openssl/openssl/test/sslapitest.c
+++ b/deps/openssl/openssl/test/sslapitest.c
@@ -1681,6 +1681,8 @@ static int test_large_app_data(int tst)
     return testresult;
 }
 
+#if !defined(OPENSSL_NO_TLS1_2) || !defined(OSSL_NO_USABLE_TLS1_3) \
+    || !defined(OPENSSL_NO_DTLS)
 static int execute_cleanse_plaintext(const SSL_METHOD *smeth,
                                      const SSL_METHOD *cmeth,
                                      int min_version, int max_version)
@@ -1702,15 +1704,13 @@ static int execute_cleanse_plaintext(const SSL_METHOD *smeth,
                                        privkey)))
         goto end;
 
-#ifdef OPENSSL_NO_DTLS1_2
-    if (smeth == DTLS_server_method()) {
 # ifdef OPENSSL_NO_DTLS1_2
+    if (smeth == DTLS_server_method()) {
         /* Not supported in the FIPS provider */
         if (is_fips) {
             testresult = 1;
             goto end;
         };
-# endif
         /*
          * Default sigalgs are SHA1 based in  0) {
         ret = run_tests(argv[0]);
         cleanup_tests();
         opt_check_usage();
-    } else {
+    } else if (setup_res == 0) {
         opt_help(test_get_options());
     }
 end:
diff --git a/deps/openssl/openssl/util/missingssl.txt b/deps/openssl/openssl/util/missingssl.txt
index 48219fd99a9a47..41ca8a8bbc0022 100644
--- a/deps/openssl/openssl/util/missingssl.txt
+++ b/deps/openssl/openssl/util/missingssl.txt
@@ -3,7 +3,6 @@ ERR_load_SSL_strings(3)
 SRP_Calc_A_param(3)
 SSL_COMP_get_name(3)
 SSL_COMP_set0_compression_methods(3)
-SSL_CONF_CTX_finish(3)
 SSL_CTX_SRP_CTX_free(3)
 SSL_CTX_SRP_CTX_init(3)
 SSL_CTX_get0_certificate(3)
diff --git a/deps/openssl/openssl_asm.gypi b/deps/openssl/openssl_asm.gypi
index dbd5a5f69ff8d9..dd7e636eb08893 100644
--- a/deps/openssl/openssl_asm.gypi
+++ b/deps/openssl/openssl_asm.gypi
@@ -1,6 +1,6 @@
 {
   'conditions': [
-    ['target_arch=="ppc64" and OS=="aix"', {
+    ['target_arch=="ppc64" and OS in ("aix", "os400")', {
       'includes': ['config/archs/aix64-gcc-as/asm/openssl.gypi'],
     }, 'target_arch=="ppc64" and OS=="linux" and node_byteorder =="little"', {
       'includes': ['config/archs/linux-ppc64le/asm/openssl.gypi'],
diff --git a/deps/openssl/openssl_asm_avx2.gypi b/deps/openssl/openssl_asm_avx2.gypi
index 2883f83d694394..6a9c56d76a211a 100644
--- a/deps/openssl/openssl_asm_avx2.gypi
+++ b/deps/openssl/openssl_asm_avx2.gypi
@@ -1,6 +1,6 @@
 {
   'conditions': [
-    ['target_arch=="ppc64" and OS=="aix"', {
+    ['target_arch=="ppc64" and OS in ("aix", "os400")', {
       'includes': ['config/archs/aix64-gcc-as/asm_avx2/openssl.gypi'],
     }, 'target_arch=="ppc64" and OS=="linux" and node_byteorder =="little"', {
       'includes': ['config/archs/linux-ppc64le/asm_avx2/openssl.gypi'],
diff --git a/deps/openssl/openssl_common.gypi b/deps/openssl/openssl_common.gypi
index 256eb7d1808db3..1290fff251fc5b 100644
--- a/deps/openssl/openssl_common.gypi
+++ b/deps/openssl/openssl_common.gypi
@@ -13,7 +13,7 @@
   ],
   # build options specific to OS
   'conditions': [
-    [ 'OS=="aix"', {
+    [ 'OS in ("aix", "os400")', {
       # AIX is missing /usr/include/endian.h
       'defines': [
         '__LITTLE_ENDIAN=1234',
diff --git a/deps/openssl/openssl_no_asm.gypi b/deps/openssl/openssl_no_asm.gypi
index de0e486f67e90e..20663decabba23 100644
--- a/deps/openssl/openssl_no_asm.gypi
+++ b/deps/openssl/openssl_no_asm.gypi
@@ -1,7 +1,7 @@
 {
   'defines': ['OPENSSL_NO_ASM'],
   'conditions': [
-    ['target_arch=="ppc64" and OS=="aix"', {
+    ['target_arch=="ppc64" and OS in ("aix", "os400")', {
       'includes': ['config/archs/aix64-gcc-as/no-asm/openssl.gypi'],
     }, 'target_arch=="ppc64" and OS=="linux" and node_byteorder =="little"', {
       'includes': ['config/archs/linux-ppc64le/no-asm/openssl.gypi'],
diff --git a/deps/simdutf/simdutf.cpp b/deps/simdutf/simdutf.cpp
index 712bf0cf85833a..70b461ab550b46 100644
--- a/deps/simdutf/simdutf.cpp
+++ b/deps/simdutf/simdutf.cpp
@@ -1,8 +1,8 @@
-/* auto-generated on 2023-06-05 08:58:28 -0400. Do not edit! */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf.cpp
+/* auto-generated on 2023-10-08 13:48:09 -0400. Do not edit! */
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf.cpp
 /* begin file src/simdutf.cpp */
 #include "simdutf.h"
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=implementation.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=implementation.cpp
 /* begin file src/implementation.cpp */
 #include 
 #include 
@@ -26,7 +26,7 @@ std::string toBinaryString(T b) {
 
 // Implementations
 // The best choice should always come first!
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/arm64.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/arm64.h
 /* begin file src/simdutf/arm64.h */
 #ifndef SIMDUTF_ARM64_H
 #define SIMDUTF_ARM64_H
@@ -53,7 +53,7 @@ namespace arm64 {
 } // namespace arm64
 } // namespace simdutf
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/arm64/implementation.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/arm64/implementation.h
 /* begin file src/simdutf/arm64/implementation.h */
 #ifndef SIMDUTF_ARM64_IMPLEMENTATION_H
 #define SIMDUTF_ARM64_IMPLEMENTATION_H
@@ -130,14 +130,14 @@ class implementation final : public simdutf::implementation {
 #endif // SIMDUTF_ARM64_IMPLEMENTATION_H
 /* end file src/simdutf/arm64/implementation.h */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/arm64/begin.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/arm64/begin.h
 /* begin file src/simdutf/arm64/begin.h */
 // redefining SIMDUTF_IMPLEMENTATION to "arm64"
 // #define SIMDUTF_IMPLEMENTATION arm64
 /* end file src/simdutf/arm64/begin.h */
 
 // Declarations
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/arm64/intrinsics.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/arm64/intrinsics.h
 /* begin file src/simdutf/arm64/intrinsics.h */
 #ifndef SIMDUTF_ARM64_INTRINSICS_H
 #define SIMDUTF_ARM64_INTRINSICS_H
@@ -149,7 +149,7 @@ class implementation final : public simdutf::implementation {
 
 #endif //  SIMDUTF_ARM64_INTRINSICS_H
 /* end file src/simdutf/arm64/intrinsics.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/arm64/bitmanipulation.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/arm64/bitmanipulation.h
 /* begin file src/simdutf/arm64/bitmanipulation.h */
 #ifndef SIMDUTF_ARM64_BITMANIPULATION_H
 #define SIMDUTF_ARM64_BITMANIPULATION_H
@@ -169,7 +169,7 @@ simdutf_really_inline int count_ones(uint64_t input_num) {
 
 #endif // SIMDUTF_ARM64_BITMANIPULATION_H
 /* end file src/simdutf/arm64/bitmanipulation.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/arm64/simd.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/arm64/simd.h
 /* begin file src/simdutf/arm64/simd.h */
 #ifndef SIMDUTF_ARM64_SIMD_H
 #define SIMDUTF_ARM64_SIMD_H
@@ -782,7 +782,7 @@ simdutf_really_inline int16x8_t make_int16x8_t(int16_t x1,  int16_t x2,  int16_t
       ).to_bitmask();
     }
   }; // struct simd8x64
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/arm64/simd16-inl.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/arm64/simd16-inl.h
 /* begin file src/simdutf/arm64/simd16-inl.h */
 template
 struct simd16;
@@ -1095,7 +1095,7 @@ simdutf_really_inline simd16::operator simd16() const { retur
 #endif // SIMDUTF_ARM64_SIMD_H
 /* end file src/simdutf/arm64/simd.h */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/arm64/end.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/arm64/end.h
 /* begin file src/simdutf/arm64/end.h */
 /* end file src/simdutf/arm64/end.h */
 
@@ -1103,7 +1103,7 @@ simdutf_really_inline simd16::operator simd16() const { retur
 
 #endif // SIMDUTF_ARM64_H
 /* end file src/simdutf/arm64.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/icelake.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/icelake.h
 /* begin file src/simdutf/icelake.h */
 #ifndef SIMDUTF_ICELAKE_H
 #define SIMDUTF_ICELAKE_H
@@ -1119,9 +1119,12 @@ simdutf_really_inline simd16::operator simd16() const { retur
 #endif
 
 #ifdef _MSC_VER
-#if _MSC_VER >= 1920
-// Visual Studio 2019 and up support VBMI2 under x64 even if the header
+#if _MSC_VER >= 1930
+// Visual Studio 2022 and up support VBMI2 under x64 even if the header
 // avx512vbmi2intrin.h is not found.
+// Visual Studio 2019 technically supports VBMI2, but the implementation
+// might be unreliable. Search for visualstudio2019icelakeissue in our
+// tests.
 #define SIMDUTF_COMPILER_SUPPORTS_VBMI2 1
 #endif
 #endif
@@ -1155,7 +1158,7 @@ namespace icelake {
 //
 // These two need to be included outside SIMDUTF_TARGET_REGION
 //
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/icelake/intrinsics.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/icelake/intrinsics.h
 /* begin file src/simdutf/icelake/intrinsics.h */
 #ifndef SIMDUTF_ICELAKE_INTRINSICS_H
 #define SIMDUTF_ICELAKE_INTRINSICS_H
@@ -1265,7 +1268,7 @@ inline __m512i _mm512_set_epi8(uint8_t a0, uint8_t a1, uint8_t a2, uint8_t a3, u
 
 #endif // SIMDUTF_HASWELL_INTRINSICS_H
 /* end file src/simdutf/icelake/intrinsics.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/icelake/implementation.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/icelake/implementation.h
 /* begin file src/simdutf/icelake/implementation.h */
 #ifndef SIMDUTF_ICELAKE_IMPLEMENTATION_H
 #define SIMDUTF_ICELAKE_IMPLEMENTATION_H
@@ -1348,7 +1351,7 @@ class implementation final : public simdutf::implementation {
 //
 // The rest need to be inside the region
 //
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/icelake/begin.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/icelake/begin.h
 /* begin file src/simdutf/icelake/begin.h */
 // redefining SIMDUTF_IMPLEMENTATION to "icelake"
 // #define SIMDUTF_IMPLEMENTATION icelake
@@ -1364,7 +1367,7 @@ SIMDUTF_DISABLE_GCC_WARNING(-Wmaybe-uninitialized)
 #endif // end of workaround
 /* end file src/simdutf/icelake/begin.h */
 // Declarations
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/icelake/bitmanipulation.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/icelake/bitmanipulation.h
 /* begin file src/simdutf/icelake/bitmanipulation.h */
 #ifndef SIMDUTF_ICELAKE_BITMANIPULATION_H
 #define SIMDUTF_ICELAKE_BITMANIPULATION_H
@@ -1390,7 +1393,7 @@ simdutf_really_inline long long int count_ones(uint64_t input_num) {
 
 #endif // SIMDUTF_ICELAKE_BITMANIPULATION_H
 /* end file src/simdutf/icelake/bitmanipulation.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/icelake/end.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/icelake/end.h
 /* begin file src/simdutf/icelake/end.h */
 #if SIMDUTF_CAN_ALWAYS_RUN_ICELAKE
 // nothing needed.
@@ -1409,7 +1412,7 @@ SIMDUTF_POP_DISABLE_WARNINGS
 #endif // SIMDUTF_IMPLEMENTATION_ICELAKE
 #endif // SIMDUTF_ICELAKE_H
 /* end file src/simdutf/icelake.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/haswell.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/haswell.h
 /* begin file src/simdutf/haswell.h */
 #ifndef SIMDUTF_HASWELL_H
 #define SIMDUTF_HASWELL_H
@@ -1455,7 +1458,7 @@ namespace haswell {
 //
 // These two need to be included outside SIMDUTF_TARGET_REGION
 //
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/haswell/implementation.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/haswell/implementation.h
 /* begin file src/simdutf/haswell/implementation.h */
 #ifndef SIMDUTF_HASWELL_IMPLEMENTATION_H
 #define SIMDUTF_HASWELL_IMPLEMENTATION_H
@@ -1534,7 +1537,7 @@ class implementation final : public simdutf::implementation {
 
 #endif // SIMDUTF_HASWELL_IMPLEMENTATION_H
 /* end file src/simdutf/haswell/implementation.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/haswell/intrinsics.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/haswell/intrinsics.h
 /* begin file src/simdutf/haswell/intrinsics.h */
 #ifndef SIMDUTF_HASWELL_INTRINSICS_H
 #define SIMDUTF_HASWELL_INTRINSICS_H
@@ -1603,7 +1606,7 @@ SIMDUTF_POP_DISABLE_WARNINGS
 //
 // The rest need to be inside the region
 //
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/haswell/begin.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/haswell/begin.h
 /* begin file src/simdutf/haswell/begin.h */
 // redefining SIMDUTF_IMPLEMENTATION to "haswell"
 // #define SIMDUTF_IMPLEMENTATION haswell
@@ -1619,7 +1622,7 @@ SIMDUTF_DISABLE_GCC_WARNING(-Wmaybe-uninitialized)
 #endif // end of workaround
 /* end file src/simdutf/haswell/begin.h */
 // Declarations
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/haswell/bitmanipulation.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/haswell/bitmanipulation.h
 /* begin file src/simdutf/haswell/bitmanipulation.h */
 #ifndef SIMDUTF_HASWELL_BITMANIPULATION_H
 #define SIMDUTF_HASWELL_BITMANIPULATION_H
@@ -1645,7 +1648,7 @@ simdutf_really_inline long long int count_ones(uint64_t input_num) {
 
 #endif // SIMDUTF_HASWELL_BITMANIPULATION_H
 /* end file src/simdutf/haswell/bitmanipulation.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/haswell/simd.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/haswell/simd.h
 /* begin file src/simdutf/haswell/simd.h */
 #ifndef SIMDUTF_HASWELL_SIMD_H
 #define SIMDUTF_HASWELL_SIMD_H
@@ -2041,7 +2044,7 @@ namespace simd {
     }
   }; // struct simd8x64
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/haswell/simd16-inl.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/haswell/simd16-inl.h
 /* begin file src/simdutf/haswell/simd16-inl.h */
 #ifdef __GNUC__
 #if __GNUC__ < 8
@@ -2320,7 +2323,7 @@ struct simd16: base16_numeric  {
 #endif // SIMDUTF_HASWELL_SIMD_H
 /* end file src/simdutf/haswell/simd.h */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/haswell/end.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/haswell/end.h
 /* begin file src/simdutf/haswell/end.h */
 #if SIMDUTF_CAN_ALWAYS_RUN_HASWELL
 // nothing needed.
@@ -2337,7 +2340,7 @@ SIMDUTF_POP_DISABLE_WARNINGS
 #endif // SIMDUTF_IMPLEMENTATION_HASWELL
 #endif // SIMDUTF_HASWELL_COMMON_H
 /* end file src/simdutf/haswell.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/westmere.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/westmere.h
 /* begin file src/simdutf/westmere.h */
 #ifndef SIMDUTF_WESTMERE_H
 #define SIMDUTF_WESTMERE_H
@@ -2378,7 +2381,7 @@ namespace westmere {
 //
 // These two need to be included outside SIMDUTF_TARGET_REGION
 //
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/westmere/implementation.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/westmere/implementation.h
 /* begin file src/simdutf/westmere/implementation.h */
 #ifndef SIMDUTF_WESTMERE_IMPLEMENTATION_H
 #define SIMDUTF_WESTMERE_IMPLEMENTATION_H
@@ -2455,7 +2458,7 @@ class implementation final : public simdutf::implementation {
 
 #endif // SIMDUTF_WESTMERE_IMPLEMENTATION_H
 /* end file src/simdutf/westmere/implementation.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/westmere/intrinsics.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/westmere/intrinsics.h
 /* begin file src/simdutf/westmere/intrinsics.h */
 #ifndef SIMDUTF_WESTMERE_INTRINSICS_H
 #define SIMDUTF_WESTMERE_INTRINSICS_H
@@ -2504,7 +2507,7 @@ SIMDUTF_POP_DISABLE_WARNINGS
 //
 // The rest need to be inside the region
 //
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/westmere/begin.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/westmere/begin.h
 /* begin file src/simdutf/westmere/begin.h */
 // redefining SIMDUTF_IMPLEMENTATION to "westmere"
 // #define SIMDUTF_IMPLEMENTATION westmere
@@ -2517,7 +2520,7 @@ SIMDUTF_TARGET_WESTMERE
 /* end file src/simdutf/westmere/begin.h */
 
 // Declarations
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/westmere/bitmanipulation.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/westmere/bitmanipulation.h
 /* begin file src/simdutf/westmere/bitmanipulation.h */
 #ifndef SIMDUTF_WESTMERE_BITMANIPULATION_H
 #define SIMDUTF_WESTMERE_BITMANIPULATION_H
@@ -2543,7 +2546,7 @@ simdutf_really_inline long long int count_ones(uint64_t input_num) {
 
 #endif // SIMDUTF_WESTMERE_BITMANIPULATION_H
 /* end file src/simdutf/westmere/bitmanipulation.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/westmere/simd.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/westmere/simd.h
 /* begin file src/simdutf/westmere/simd.h */
 #ifndef SIMDUTF_WESTMERE_SIMD_H
 #define SIMDUTF_WESTMERE_SIMD_H
@@ -2987,7 +2990,7 @@ namespace simd {
     }
   }; // struct simd8x64
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/westmere/simd16-inl.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/westmere/simd16-inl.h
 /* begin file src/simdutf/westmere/simd16-inl.h */
 template
 struct simd16;
@@ -3264,7 +3267,7 @@ template
 #endif // SIMDUTF_WESTMERE_SIMD_INPUT_H
 /* end file src/simdutf/westmere/simd.h */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/westmere/end.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/westmere/end.h
 /* begin file src/simdutf/westmere/end.h */
 #if SIMDUTF_CAN_ALWAYS_RUN_WESTMERE
 // nothing needed.
@@ -3277,7 +3280,7 @@ SIMDUTF_UNTARGET_REGION
 #endif // SIMDUTF_IMPLEMENTATION_WESTMERE
 #endif // SIMDUTF_WESTMERE_COMMON_H
 /* end file src/simdutf/westmere.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/ppc64.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/ppc64.h
 /* begin file src/simdutf/ppc64.h */
 #ifndef SIMDUTF_PPC64_H
 #define SIMDUTF_PPC64_H
@@ -3304,7 +3307,7 @@ namespace ppc64 {
 } // namespace ppc64
 } // namespace simdutf
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/ppc64/implementation.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/ppc64/implementation.h
 /* begin file src/simdutf/ppc64/implementation.h */
 #ifndef SIMDUTF_PPC64_IMPLEMENTATION_H
 #define SIMDUTF_PPC64_IMPLEMENTATION_H
@@ -3383,14 +3386,14 @@ class implementation final : public simdutf::implementation {
 #endif // SIMDUTF_PPC64_IMPLEMENTATION_H
 /* end file src/simdutf/ppc64/implementation.h */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/ppc64/begin.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/ppc64/begin.h
 /* begin file src/simdutf/ppc64/begin.h */
 // redefining SIMDUTF_IMPLEMENTATION to "ppc64"
 // #define SIMDUTF_IMPLEMENTATION ppc64
 /* end file src/simdutf/ppc64/begin.h */
 
 // Declarations
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/ppc64/intrinsics.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/ppc64/intrinsics.h
 /* begin file src/simdutf/ppc64/intrinsics.h */
 #ifndef SIMDUTF_PPC64_INTRINSICS_H
 #define SIMDUTF_PPC64_INTRINSICS_H
@@ -3411,7 +3414,7 @@ class implementation final : public simdutf::implementation {
 
 #endif //  SIMDUTF_PPC64_INTRINSICS_H
 /* end file src/simdutf/ppc64/intrinsics.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/ppc64/bitmanipulation.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/ppc64/bitmanipulation.h
 /* begin file src/simdutf/ppc64/bitmanipulation.h */
 #ifndef SIMDUTF_PPC64_BITMANIPULATION_H
 #define SIMDUTF_PPC64_BITMANIPULATION_H
@@ -3437,7 +3440,7 @@ simdutf_really_inline int count_ones(uint64_t input_num) {
 
 #endif // SIMDUTF_PPC64_BITMANIPULATION_H
 /* end file src/simdutf/ppc64/bitmanipulation.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/ppc64/simd.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/ppc64/simd.h
 /* begin file src/simdutf/ppc64/simd.h */
 #ifndef SIMDUTF_PPC64_SIMD_H
 #define SIMDUTF_PPC64_SIMD_H
@@ -3929,7 +3932,7 @@ template  struct simd8x64 {
 #endif // SIMDUTF_PPC64_SIMD_INPUT_H
 /* end file src/simdutf/ppc64/simd.h */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/ppc64/end.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/ppc64/end.h
 /* begin file src/simdutf/ppc64/end.h */
 /* end file src/simdutf/ppc64/end.h */
 
@@ -3937,7 +3940,7 @@ template  struct simd8x64 {
 
 #endif // SIMDUTF_PPC64_H
 /* end file src/simdutf/ppc64.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/fallback.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/fallback.h
 /* begin file src/simdutf/fallback.h */
 #ifndef SIMDUTF_FALLBACK_H
 #define SIMDUTF_FALLBACK_H
@@ -3966,7 +3969,7 @@ namespace fallback {
 } // namespace fallback
 } // namespace simdutf
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/fallback/implementation.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/fallback/implementation.h
 /* begin file src/simdutf/fallback/implementation.h */
 #ifndef SIMDUTF_FALLBACK_IMPLEMENTATION_H
 #define SIMDUTF_FALLBACK_IMPLEMENTATION_H
@@ -4047,14 +4050,14 @@ class implementation final : public simdutf::implementation {
 #endif // SIMDUTF_FALLBACK_IMPLEMENTATION_H
 /* end file src/simdutf/fallback/implementation.h */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/fallback/begin.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/fallback/begin.h
 /* begin file src/simdutf/fallback/begin.h */
 // redefining SIMDUTF_IMPLEMENTATION to "fallback"
 // #define SIMDUTF_IMPLEMENTATION fallback
 /* end file src/simdutf/fallback/begin.h */
 
 // Declarations
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/fallback/bitmanipulation.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/fallback/bitmanipulation.h
 /* begin file src/simdutf/fallback/bitmanipulation.h */
 #ifndef SIMDUTF_FALLBACK_BITMANIPULATION_H
 #define SIMDUTF_FALLBACK_BITMANIPULATION_H
@@ -4089,7 +4092,7 @@ static unsigned char _BitScanReverse64(unsigned long* ret, uint64_t x) {
 #endif // SIMDUTF_FALLBACK_BITMANIPULATION_H
 /* end file src/simdutf/fallback/bitmanipulation.h */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/fallback/end.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/fallback/end.h
 /* begin file src/simdutf/fallback/end.h */
 /* end file src/simdutf/fallback/end.h */
 
@@ -4978,7 +4981,7 @@ const implementation * builtin_implementation() {
 } // namespace simdutf
 
 /* end file src/implementation.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=encoding_types.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=encoding_types.cpp
 /* begin file src/encoding_types.cpp */
 
 namespace simdutf {
@@ -5040,7 +5043,7 @@ encoding_type check_bom(const char* byte, size_t length) {
 }
 }
 /* end file src/encoding_types.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=error.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=error.cpp
 /* begin file src/error.cpp */
 namespace simdutf {
 
@@ -5052,7 +5055,7 @@ namespace simdutf {
 /* end file src/error.cpp */
 // The large tables should be included once and they
 // should not depend on a kernel.
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=tables/utf8_to_utf16_tables.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=tables/utf8_to_utf16_tables.h
 /* begin file src/tables/utf8_to_utf16_tables.h */
 #ifndef SIMDUTF_UTF8_TO_UTF16_TABLES_H
 #define SIMDUTF_UTF8_TO_UTF16_TABLES_H
@@ -9391,7 +9394,7 @@ const uint8_t utf8bigindex[4096][2] =
 
 #endif // SIMDUTF_UTF8_TO_UTF16_TABLES_H
 /* end file src/tables/utf8_to_utf16_tables.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=tables/utf16_to_utf8_tables.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=tables/utf16_to_utf8_tables.h
 /* begin file src/tables/utf16_to_utf8_tables.h */
 // file generated by scripts/sse_convert_utf16_to_utf8.py
 #ifndef SIMDUTF_UTF16_TO_UTF8_TABLES_H
@@ -9932,7 +9935,7 @@ namespace utf16_to_utf8 {
 // End of tables.
 
 // The scalar routines should be included once.
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=scalar/ascii.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=scalar/ascii.h
 /* begin file src/scalar/ascii.h */
 #ifndef SIMDUTF_ASCII_H
 #define SIMDUTF_ASCII_H
@@ -9993,7 +9996,7 @@ inline simdutf_warn_unused result validate_with_errors(const char *buf, size_t l
 
 #endif
 /* end file src/scalar/ascii.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=scalar/utf8.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=scalar/utf8.h
 /* begin file src/scalar/utf8.h */
 #ifndef SIMDUTF_UTF8_H
 #define SIMDUTF_UTF8_H
@@ -10138,7 +10141,11 @@ inline simdutf_warn_unused result validate_with_errors(const char *buf, size_t l
 
 // Finds the previous leading byte and validates with errors from there
 // Used to pinpoint the location of an error when an invalid chunk is detected
-inline simdutf_warn_unused result rewind_and_validate_with_errors(const char *buf, size_t len) noexcept {
+inline simdutf_warn_unused result rewind_and_validate_with_errors(const char *start, const char *buf, size_t len) noexcept {
+  // First check that we start with a leading byte
+  if ((*start & 0b11000000) == 0b10000000) {
+    return result(error_code::TOO_LONG, 0);
+  }
   size_t extra_len{0};
   // A leading byte cannot be further than 4 bytes away
   for(int i = 0; i < 5; i++) {
@@ -10183,7 +10190,7 @@ inline size_t utf16_length_from_utf8(const char* buf, size_t len) {
 
 #endif
 /* end file src/scalar/utf8.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=scalar/utf16.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=scalar/utf16.h
 /* begin file src/scalar/utf16.h */
 #ifndef SIMDUTF_UTF16_H
 #define SIMDUTF_UTF16_H
@@ -10297,7 +10304,7 @@ simdutf_really_inline void change_endianness_utf16(const char16_t* in, size_t si
 
 #endif
 /* end file src/scalar/utf16.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=scalar/utf32.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=scalar/utf32.h
 /* begin file src/scalar/utf32.h */
 #ifndef SIMDUTF_UTF32_H
 #define SIMDUTF_UTF32_H
@@ -10372,7 +10379,7 @@ inline size_t utf16_length_from_utf32(const char32_t* buf, size_t len) {
 #endif
 /* end file src/scalar/utf32.h */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=scalar/utf32_to_utf8/valid_utf32_to_utf8.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=scalar/utf32_to_utf8/valid_utf32_to_utf8.h
 /* begin file src/scalar/utf32_to_utf8/valid_utf32_to_utf8.h */
 #ifndef SIMDUTF_VALID_UTF32_TO_UTF8_H
 #define SIMDUTF_VALID_UTF32_TO_UTF8_H
@@ -10439,7 +10446,7 @@ inline size_t convert_valid(const char32_t* buf, size_t len, char* utf8_output)
 
 #endif
 /* end file src/scalar/utf32_to_utf8/valid_utf32_to_utf8.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=scalar/utf32_to_utf8/utf32_to_utf8.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=scalar/utf32_to_utf8/utf32_to_utf8.h
 /* begin file src/scalar/utf32_to_utf8/utf32_to_utf8.h */
 #ifndef SIMDUTF_UTF32_TO_UTF8_H
 #define SIMDUTF_UTF32_TO_UTF8_H
@@ -10555,7 +10562,7 @@ inline result convert_with_errors(const char32_t* buf, size_t len, char* utf8_ou
 #endif
 /* end file src/scalar/utf32_to_utf8/utf32_to_utf8.h */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=scalar/utf32_to_utf16/valid_utf32_to_utf16.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=scalar/utf32_to_utf16/valid_utf32_to_utf16.h
 /* begin file src/scalar/utf32_to_utf16/valid_utf32_to_utf16.h */
 #ifndef SIMDUTF_VALID_UTF32_TO_UTF16_H
 #define SIMDUTF_VALID_UTF32_TO_UTF16_H
@@ -10600,7 +10607,7 @@ inline size_t convert_valid(const char32_t* buf, size_t len, char16_t* utf16_out
 
 #endif
 /* end file src/scalar/utf32_to_utf16/valid_utf32_to_utf16.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=scalar/utf32_to_utf16/utf32_to_utf16.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=scalar/utf32_to_utf16/utf32_to_utf16.h
 /* begin file src/scalar/utf32_to_utf16/utf32_to_utf16.h */
 #ifndef SIMDUTF_UTF32_TO_UTF16_H
 #define SIMDUTF_UTF32_TO_UTF16_H
@@ -10676,7 +10683,7 @@ inline result convert_with_errors(const char32_t* buf, size_t len, char16_t* utf
 #endif
 /* end file src/scalar/utf32_to_utf16/utf32_to_utf16.h */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=scalar/utf16_to_utf8/valid_utf16_to_utf8.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=scalar/utf16_to_utf8/valid_utf16_to_utf8.h
 /* begin file src/scalar/utf16_to_utf8/valid_utf16_to_utf8.h */
 #ifndef SIMDUTF_VALID_UTF16_TO_UTF8_H
 #define SIMDUTF_VALID_UTF16_TO_UTF8_H
@@ -10751,7 +10758,7 @@ inline size_t convert_valid(const char16_t* buf, size_t len, char* utf8_output)
 
 #endif
 /* end file src/scalar/utf16_to_utf8/valid_utf16_to_utf8.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=scalar/utf16_to_utf8/utf16_to_utf8.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=scalar/utf16_to_utf8/utf16_to_utf8.h
 /* begin file src/scalar/utf16_to_utf8/utf16_to_utf8.h */
 #ifndef SIMDUTF_UTF16_TO_UTF8_H
 #define SIMDUTF_UTF16_TO_UTF8_H
@@ -10887,7 +10894,7 @@ inline result convert_with_errors(const char16_t* buf, size_t len, char* utf8_ou
 #endif
 /* end file src/scalar/utf16_to_utf8/utf16_to_utf8.h */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=scalar/utf16_to_utf32/valid_utf16_to_utf32.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=scalar/utf16_to_utf32/valid_utf16_to_utf32.h
 /* begin file src/scalar/utf16_to_utf32/valid_utf16_to_utf32.h */
 #ifndef SIMDUTF_VALID_UTF16_TO_UTF32_H
 #define SIMDUTF_VALID_UTF16_TO_UTF32_H
@@ -10929,7 +10936,7 @@ inline size_t convert_valid(const char16_t* buf, size_t len, char32_t* utf32_out
 
 #endif
 /* end file src/scalar/utf16_to_utf32/valid_utf16_to_utf32.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=scalar/utf16_to_utf32/utf16_to_utf32.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=scalar/utf16_to_utf32/utf16_to_utf32.h
 /* begin file src/scalar/utf16_to_utf32/utf16_to_utf32.h */
 #ifndef SIMDUTF_UTF16_TO_UTF32_H
 #define SIMDUTF_UTF16_TO_UTF32_H
@@ -11001,7 +11008,7 @@ inline result convert_with_errors(const char16_t* buf, size_t len, char32_t* utf
 #endif
 /* end file src/scalar/utf16_to_utf32/utf16_to_utf32.h */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=scalar/utf8_to_utf16/valid_utf8_to_utf16.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=scalar/utf8_to_utf16/valid_utf8_to_utf16.h
 /* begin file src/scalar/utf8_to_utf16/valid_utf8_to_utf16.h */
 #ifndef SIMDUTF_VALID_UTF8_TO_UTF16_H
 #define SIMDUTF_VALID_UTF8_TO_UTF16_H
@@ -11086,7 +11093,7 @@ inline size_t convert_valid(const char* buf, size_t len, char16_t* utf16_output)
 
 #endif
 /* end file src/scalar/utf8_to_utf16/valid_utf8_to_utf16.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=scalar/utf8_to_utf16/utf8_to_utf16.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=scalar/utf8_to_utf16/utf8_to_utf16.h
 /* begin file src/scalar/utf8_to_utf16/utf8_to_utf16.h */
 #ifndef SIMDUTF_UTF8_TO_UTF16_H
 #define SIMDUTF_UTF8_TO_UTF16_H
@@ -11336,7 +11343,7 @@ inline result rewind_and_convert_with_errors(size_t prior_bytes, const char* buf
 #endif
 /* end file src/scalar/utf8_to_utf16/utf8_to_utf16.h */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=scalar/utf8_to_utf32/valid_utf8_to_utf32.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=scalar/utf8_to_utf32/valid_utf8_to_utf32.h
 /* begin file src/scalar/utf8_to_utf32/valid_utf8_to_utf32.h */
 #ifndef SIMDUTF_VALID_UTF8_TO_UTF32_H
 #define SIMDUTF_VALID_UTF8_TO_UTF32_H
@@ -11402,7 +11409,7 @@ inline size_t convert_valid(const char* buf, size_t len, char32_t* utf32_output)
 
 #endif
 /* end file src/scalar/utf8_to_utf32/valid_utf8_to_utf32.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=scalar/utf8_to_utf32/utf8_to_utf32.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=scalar/utf8_to_utf32/utf8_to_utf32.h
 /* begin file src/scalar/utf8_to_utf32/utf8_to_utf32.h */
 #ifndef SIMDUTF_UTF8_TO_UTF32_H
 #define SIMDUTF_UTF8_TO_UTF32_H
@@ -11622,9 +11629,9 @@ SIMDUTF_DISABLE_UNDESIRED_WARNINGS
 
 
 #if SIMDUTF_IMPLEMENTATION_ARM64
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=arm64/implementation.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=arm64/implementation.cpp
 /* begin file src/arm64/implementation.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/arm64/begin.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/arm64/begin.h
 /* begin file src/simdutf/arm64/begin.h */
 // redefining SIMDUTF_IMPLEMENTATION to "arm64"
 // #define SIMDUTF_IMPLEMENTATION arm64
@@ -11660,7 +11667,7 @@ simdutf_really_inline simd8 must_be_2_3_continuation(const simd8
     return is_third_byte ^ is_fourth_byte;
 }
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=arm64/arm_detect_encodings.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=arm64/arm_detect_encodings.cpp
 /* begin file src/arm64/arm_detect_encodings.cpp */
 template
 // len is known to be a multiple of 2 when this is called
@@ -11868,7 +11875,7 @@ int arm_detect_encodings(const char * buf, size_t len) {
 }
 /* end file src/arm64/arm_detect_encodings.cpp */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=arm64/arm_validate_utf16.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=arm64/arm_validate_utf16.cpp
 /* begin file src/arm64/arm_validate_utf16.cpp */
 template 
 const char16_t* arm_validate_utf16(const char16_t* input, size_t size) {
@@ -12018,7 +12025,7 @@ const result arm_validate_utf16_with_errors(const char16_t* input, size_t size)
     return result(error_code::SUCCESS, input - start);
 }
 /* end file src/arm64/arm_validate_utf16.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=arm64/arm_validate_utf32le.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=arm64/arm_validate_utf32le.cpp
 /* begin file src/arm64/arm_validate_utf32le.cpp */
 
 const char32_t* arm_validate_utf32le(const char32_t* input, size_t size) {
@@ -12083,7 +12090,7 @@ const result arm_validate_utf32le_with_errors(const char32_t* input, size_t size
 }
 /* end file src/arm64/arm_validate_utf32le.cpp */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=arm64/arm_convert_utf8_to_utf16.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=arm64/arm_convert_utf8_to_utf16.cpp
 /* begin file src/arm64/arm_convert_utf8_to_utf16.cpp */
 // Convert up to 12 bytes from utf8 to utf16 using a mask indicating the
 // end of the code points. Only the least significant 12 bits of the mask
@@ -12270,7 +12277,7 @@ size_t convert_masked_utf8_to_utf16(const char *input,
   return consumed;
 }
 /* end file src/arm64/arm_convert_utf8_to_utf16.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=arm64/arm_convert_utf8_to_utf32.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=arm64/arm_convert_utf8_to_utf32.cpp
 /* begin file src/arm64/arm_convert_utf8_to_utf32.cpp */
 // Convert up to 12 bytes from utf8 to utf32 using a mask indicating the
 // end of the code points. Only the least significant 12 bits of the mask
@@ -12407,7 +12414,7 @@ size_t convert_masked_utf8_to_utf32(const char *input,
 }
 /* end file src/arm64/arm_convert_utf8_to_utf32.cpp */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=arm64/arm_convert_utf16_to_utf8.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=arm64/arm_convert_utf16_to_utf8.cpp
 /* begin file src/arm64/arm_convert_utf16_to_utf8.cpp */
 /*
     The vectorized algorithm works on single SSE register i.e., it
@@ -12987,7 +12994,7 @@ std::pair arm_convert_utf16_to_utf8_with_errors(const char16_t* b
   return std::make_pair(result(error_code::SUCCESS, buf - start), reinterpret_cast(utf8_output));
 }
 /* end file src/arm64/arm_convert_utf16_to_utf8.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=arm64/arm_convert_utf16_to_utf32.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=arm64/arm_convert_utf16_to_utf32.cpp
 /* begin file src/arm64/arm_convert_utf16_to_utf32.cpp */
 /*
     The vectorized algorithm works on single SSE register i.e., it
@@ -13164,7 +13171,7 @@ std::pair arm_convert_utf16_to_utf32_with_errors(const char16
 }
 /* end file src/arm64/arm_convert_utf16_to_utf32.cpp */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=arm64/arm_convert_utf32_to_utf8.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=arm64/arm_convert_utf32_to_utf8.cpp
 /* begin file src/arm64/arm_convert_utf32_to_utf8.cpp */
 std::pair arm_convert_utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_out) {
   uint8_t * utf8_output = reinterpret_cast(utf8_out);
@@ -13636,7 +13643,7 @@ std::pair arm_convert_utf32_to_utf8_with_errors(const char32_t* b
   return std::make_pair(result(error_code::SUCCESS, buf - start), reinterpret_cast(utf8_output));
 }
 /* end file src/arm64/arm_convert_utf32_to_utf8.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=arm64/arm_convert_utf32_to_utf16.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=arm64/arm_convert_utf32_to_utf16.cpp
 /* begin file src/arm64/arm_convert_utf32_to_utf16.cpp */
 template 
 std::pair arm_convert_utf32_to_utf16(const char32_t* buf, size_t len, char16_t* utf16_out) {
@@ -13769,7 +13776,7 @@ std::pair arm_convert_utf32_to_utf16_with_errors(const char32
 } // unnamed namespace
 } // namespace arm64
 } // namespace simdutf
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/buf_block_reader.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/buf_block_reader.h
 /* begin file src/generic/buf_block_reader.h */
 namespace simdutf {
 namespace arm64 {
@@ -13864,7 +13871,7 @@ simdutf_really_inline void buf_block_reader::advance() {
 } // namespace arm64
 } // namespace simdutf
 /* end file src/generic/buf_block_reader.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_validation/utf8_lookup4_algorithm.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_validation/utf8_lookup4_algorithm.h
 /* begin file src/generic/utf8_validation/utf8_lookup4_algorithm.h */
 namespace simdutf {
 namespace arm64 {
@@ -14053,7 +14060,7 @@ using utf8_validation::utf8_checker;
 } // namespace arm64
 } // namespace simdutf
 /* end file src/generic/utf8_validation/utf8_lookup4_algorithm.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_validation/utf8_validator.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_validation/utf8_validator.h
 /* begin file src/generic/utf8_validation/utf8_validator.h */
 namespace simdutf {
 namespace arm64 {
@@ -14098,7 +14105,7 @@ result generic_validate_utf8_with_errors(const uint8_t * input, size_t length) {
       c.check_next_input(in);
       if(c.errors()) {
         if (count != 0) { count--; } // Sometimes the error is only detected in the next chunk
-        result res = scalar::utf8::rewind_and_validate_with_errors(reinterpret_cast(input + count), length - count);
+        result res = scalar::utf8::rewind_and_validate_with_errors(reinterpret_cast(input), reinterpret_cast(input + count), length - count);
         res.count += count;
         return res;
       }
@@ -14112,7 +14119,8 @@ result generic_validate_utf8_with_errors(const uint8_t * input, size_t length) {
     reader.advance();
     c.check_eof();
     if (c.errors()) {
-      result res = scalar::utf8::rewind_and_validate_with_errors(reinterpret_cast(input) + count, length - count);
+      if (count != 0) { count--; } // Sometimes the error is only detected in the next chunk
+      result res = scalar::utf8::rewind_and_validate_with_errors(reinterpret_cast(input), reinterpret_cast(input) + count, length - count);
       res.count += count;
       return res;
     } else {
@@ -14180,7 +14188,7 @@ result generic_validate_ascii_with_errors(const char * input, size_t length) {
 } // namespace simdutf
 /* end file src/generic/utf8_validation/utf8_validator.h */
 // transcoding from UTF-8 to UTF-16
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf16/valid_utf8_to_utf16.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf16/valid_utf8_to_utf16.h
 /* begin file src/generic/utf8_to_utf16/valid_utf8_to_utf16.h */
 
 
@@ -14255,7 +14263,7 @@ simdutf_warn_unused size_t convert_valid(const char* input, size_t size,
 } // namespace arm64
 } // namespace simdutf
 /* end file src/generic/utf8_to_utf16/valid_utf8_to_utf16.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf16/utf8_to_utf16.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf16/utf8_to_utf16.h
 /* begin file src/generic/utf8_to_utf16/utf8_to_utf16.h */
 
 
@@ -14563,7 +14571,7 @@ using namespace simd;
 } // namespace simdutf
 /* end file src/generic/utf8_to_utf16/utf8_to_utf16.h */
 // transcoding from UTF-8 to UTF-32
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf32/valid_utf8_to_utf32.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf32/valid_utf8_to_utf32.h
 /* begin file src/generic/utf8_to_utf32/valid_utf8_to_utf32.h */
 
 namespace simdutf {
@@ -14609,7 +14617,7 @@ simdutf_warn_unused size_t convert_valid(const char* input, size_t size,
 } // namespace arm64
 } // namespace simdutf
 /* end file src/generic/utf8_to_utf32/valid_utf8_to_utf32.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf32/utf8_to_utf32.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf32/utf8_to_utf32.h
 /* begin file src/generic/utf8_to_utf32/utf8_to_utf32.h */
 
 
@@ -14910,7 +14918,7 @@ using namespace simd;
 } // namespace simdutf
 /* end file src/generic/utf8_to_utf32/utf8_to_utf32.h */
 // other functions
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8.h
 /* begin file src/generic/utf8.h */
 
 namespace simdutf {
@@ -14957,7 +14965,7 @@ simdutf_really_inline size_t utf32_length_from_utf8(const char* in, size_t size)
 } // namespace arm64
 } // namespace simdutf
 /* end file src/generic/utf8.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf16.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf16.h
 /* begin file src/generic/utf16.h */
 namespace simdutf {
 namespace arm64 {
@@ -15492,15 +15500,15 @@ simdutf_warn_unused size_t implementation::utf32_length_from_utf8(const char * i
 } // namespace arm64
 } // namespace simdutf
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/arm64/end.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/arm64/end.h
 /* begin file src/simdutf/arm64/end.h */
 /* end file src/simdutf/arm64/end.h */
 /* end file src/arm64/implementation.cpp */
 #endif
 #if SIMDUTF_IMPLEMENTATION_FALLBACK
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=fallback/implementation.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=fallback/implementation.cpp
 /* begin file src/fallback/implementation.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/fallback/begin.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/fallback/begin.h
 /* begin file src/simdutf/fallback/begin.h */
 // redefining SIMDUTF_IMPLEMENTATION to "fallback"
 // #define SIMDUTF_IMPLEMENTATION fallback
@@ -15744,17 +15752,17 @@ simdutf_warn_unused size_t implementation::utf32_length_from_utf8(const char * i
 } // namespace fallback
 } // namespace simdutf
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/fallback/end.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/fallback/end.h
 /* begin file src/simdutf/fallback/end.h */
 /* end file src/simdutf/fallback/end.h */
 /* end file src/fallback/implementation.cpp */
 #endif
 #if SIMDUTF_IMPLEMENTATION_ICELAKE
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=icelake/implementation.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=icelake/implementation.cpp
 /* begin file src/icelake/implementation.cpp */
 
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/icelake/begin.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/icelake/begin.h
 /* begin file src/simdutf/icelake/begin.h */
 // redefining SIMDUTF_IMPLEMENTATION to "icelake"
 // #define SIMDUTF_IMPLEMENTATION icelake
@@ -15775,7 +15783,7 @@ namespace {
 #ifndef SIMDUTF_ICELAKE_H
 #error "icelake.h must be included"
 #endif
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=icelake/icelake_utf8_common.inl.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=icelake/icelake_utf8_common.inl.cpp
 /* begin file src/icelake/icelake_utf8_common.inl.cpp */
 // Common procedures for both validating and non-validating conversions from UTF-8.
 enum block_processing_mode { SIMDUTF_FULL, SIMDUTF_TAIL};
@@ -16440,7 +16448,7 @@ simdutf_really_inline __m512i expand_utf8_to_utf32(__m512i input) {
     return expanded_utf8_to_utf32(char_class, input);
 }
 /* end file src/icelake/icelake_utf8_common.inl.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=icelake/icelake_macros.inl.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=icelake/icelake_macros.inl.cpp
 /* begin file src/icelake/icelake_macros.inl.cpp */
 
 /*
@@ -16576,7 +16584,7 @@ simdutf_really_inline __m512i expand_utf8_to_utf32(__m512i input) {
                 }                                                                         \
         }
 /* end file src/icelake/icelake_macros.inl.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=icelake/icelake_from_valid_utf8.inl.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=icelake/icelake_from_valid_utf8.inl.cpp
 /* begin file src/icelake/icelake_from_valid_utf8.inl.cpp */
 // file included directly
 
@@ -16715,7 +16723,7 @@ std::pair valid_utf8_to_fixed_length(const char* str, size
 
 using utf8_to_utf16_result = std::pair;
 /* end file src/icelake/icelake_from_valid_utf8.inl.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=icelake/icelake_utf8_validation.inl.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=icelake/icelake_utf8_validation.inl.cpp
 /* begin file src/icelake/icelake_utf8_validation.inl.cpp */
 // file included directly
 
@@ -16845,7 +16853,7 @@ simdutf_really_inline __m512i check_special_cases(__m512i input, const __m512i p
 
   }; // struct avx512_utf8_checker
 /* end file src/icelake/icelake_utf8_validation.inl.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=icelake/icelake_from_utf8.inl.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=icelake/icelake_from_utf8.inl.cpp
 /* begin file src/icelake/icelake_from_utf8.inl.cpp */
 // file included directly
 
@@ -17148,7 +17156,7 @@ std::tuple validating_utf8_to_fixed_length_with_cons
     return {ptr, output, true};
 }
 /* end file src/icelake/icelake_from_utf8.inl.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=icelake/icelake_convert_utf16_to_utf32.inl.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=icelake/icelake_convert_utf16_to_utf32.inl.cpp
 /* begin file src/icelake/icelake_convert_utf16_to_utf32.inl.cpp */
 // file included directly
 
@@ -17260,7 +17268,7 @@ std::tuple convert_utf16_to_utf32(const char16
   return std::make_tuple(buf+carry, utf32_output, true);
 }
 /* end file src/icelake/icelake_convert_utf16_to_utf32.inl.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=icelake/icelake_convert_utf32_to_utf8.inl.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=icelake/icelake_convert_utf32_to_utf8.inl.cpp
 /* begin file src/icelake/icelake_convert_utf32_to_utf8.inl.cpp */
 // file included directly
 
@@ -17746,7 +17754,7 @@ std::pair avx512_convert_utf32_to_utf8_with_errors(const char32_t
   return std::make_pair(result(error_code::SUCCESS, buf - start), utf8_output);
 }
 /* end file src/icelake/icelake_convert_utf32_to_utf8.inl.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=icelake/icelake_convert_utf32_to_utf16.inl.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=icelake/icelake_convert_utf32_to_utf16.inl.cpp
 /* begin file src/icelake/icelake_convert_utf32_to_utf16.inl.cpp */
 // file included directly
 
@@ -17881,7 +17889,7 @@ std::pair avx512_convert_utf32_to_utf16_with_errors(const cha
   return std::make_pair(result(error_code::SUCCESS, buf - start), utf16_output);
 }
 /* end file src/icelake/icelake_convert_utf32_to_utf16.inl.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=icelake/icelake_ascii_validation.inl.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=icelake/icelake_ascii_validation.inl.cpp
 /* begin file src/icelake/icelake_ascii_validation.inl.cpp */
 // file included directly
 
@@ -17900,7 +17908,7 @@ bool validate_ascii(const char* buf, size_t len) {
   return (_mm512_test_epi8_mask(running_or, running_or) == 0);
 }
 /* end file src/icelake/icelake_ascii_validation.inl.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=icelake/icelake_utf32_validation.inl.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=icelake/icelake_utf32_validation.inl.cpp
 /* begin file src/icelake/icelake_utf32_validation.inl.cpp */
 // file included directly
 
@@ -17932,7 +17940,7 @@ const char32_t* validate_utf32(const char32_t* buf, size_t len) {
     return buf;
 }
 /* end file src/icelake/icelake_utf32_validation.inl.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=icelake/icelake_convert_utf16_to_utf8.inl.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=icelake/icelake_convert_utf16_to_utf8.inl.cpp
 /* begin file src/icelake/icelake_convert_utf16_to_utf8.inl.cpp */
 // file included directly
 
@@ -18299,7 +18307,7 @@ simdutf_warn_unused result implementation::validate_utf8_with_errors(const char
       checker.check_next_input(utf8);
       if(checker.errors()) {
         if (count != 0) { count--; } // Sometimes the error is only detected in the next chunk
-        result res = scalar::utf8::rewind_and_validate_with_errors(reinterpret_cast(buf + count), len - count);
+        result res = scalar::utf8::rewind_and_validate_with_errors(reinterpret_cast(buf), reinterpret_cast(buf + count), len - count);
         res.count += count;
         return res;
       }
@@ -18310,7 +18318,7 @@ simdutf_warn_unused result implementation::validate_utf8_with_errors(const char
       checker.check_next_input(utf8);
       if(checker.errors()) {
         if (count != 0) { count--; } // Sometimes the error is only detected in the next chunk
-        result res = scalar::utf8::rewind_and_validate_with_errors(reinterpret_cast(buf + count), len - count);
+        result res = scalar::utf8::rewind_and_validate_with_errors(reinterpret_cast(buf), reinterpret_cast(buf + count), len - count);
         res.count += count;
         return res;
       } else {
@@ -19244,7 +19252,7 @@ simdutf_warn_unused size_t implementation::utf32_length_from_utf8(const char * i
 } // namespace icelake
 } // namespace simdutf
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/icelake/end.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/icelake/end.h
 /* begin file src/simdutf/icelake/end.h */
 #if SIMDUTF_CAN_ALWAYS_RUN_ICELAKE
 // nothing needed.
@@ -19260,10 +19268,10 @@ SIMDUTF_POP_DISABLE_WARNINGS
 /* end file src/icelake/implementation.cpp */
 #endif
 #if SIMDUTF_IMPLEMENTATION_HASWELL
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=haswell/implementation.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=haswell/implementation.cpp
 /* begin file src/haswell/implementation.cpp */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/haswell/begin.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/haswell/begin.h
 /* begin file src/simdutf/haswell/begin.h */
 // redefining SIMDUTF_IMPLEMENTATION to "haswell"
 // #define SIMDUTF_IMPLEMENTATION haswell
@@ -19306,7 +19314,7 @@ simdutf_really_inline simd8 must_be_2_3_continuation(const simd8
   return simd8(is_third_byte | is_fourth_byte) > int8_t(0);
 }
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=haswell/avx2_detect_encodings.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=haswell/avx2_detect_encodings.cpp
 /* begin file src/haswell/avx2_detect_encodings.cpp */
 template
 // len is known to be a multiple of 2 when this is called
@@ -19496,7 +19504,7 @@ int avx2_detect_encodings(const char * buf, size_t len) {
 }
 /* end file src/haswell/avx2_detect_encodings.cpp */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=haswell/avx2_validate_utf16.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=haswell/avx2_validate_utf16.cpp
 /* begin file src/haswell/avx2_validate_utf16.cpp */
 /*
     In UTF-16 words in range 0xD800 to 0xDFFF have special meaning.
@@ -19697,7 +19705,7 @@ const result avx2_validate_utf16_with_errors(const char16_t* input, size_t size)
     return result(error_code::SUCCESS, input - start);
 }
 /* end file src/haswell/avx2_validate_utf16.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=haswell/avx2_validate_utf32le.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=haswell/avx2_validate_utf32le.cpp
 /* begin file src/haswell/avx2_validate_utf32le.cpp */
 /* Returns:
    - pointer to the last unprocessed character (a scalar fallback should check the rest);
@@ -19763,7 +19771,7 @@ const result avx2_validate_utf32le_with_errors(const char32_t* input, size_t siz
 }
 /* end file src/haswell/avx2_validate_utf32le.cpp */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=haswell/avx2_convert_utf8_to_utf16.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=haswell/avx2_convert_utf8_to_utf16.cpp
 /* begin file src/haswell/avx2_convert_utf8_to_utf16.cpp */
 // depends on "tables/utf8_to_utf16_tables.h"
 
@@ -19946,7 +19954,7 @@ size_t convert_masked_utf8_to_utf16(const char *input,
   return consumed;
 }
 /* end file src/haswell/avx2_convert_utf8_to_utf16.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=haswell/avx2_convert_utf8_to_utf32.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=haswell/avx2_convert_utf8_to_utf32.cpp
 /* begin file src/haswell/avx2_convert_utf8_to_utf32.cpp */
 // depends on "tables/utf8_to_utf16_tables.h"
 
@@ -20075,7 +20083,7 @@ size_t convert_masked_utf8_to_utf32(const char *input,
 }
 /* end file src/haswell/avx2_convert_utf8_to_utf32.cpp */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=haswell/avx2_convert_utf16_to_utf8.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=haswell/avx2_convert_utf16_to_utf8.cpp
 /* begin file src/haswell/avx2_convert_utf16_to_utf8.cpp */
 /*
     The vectorized algorithm works on single SSE register i.e., it
@@ -20608,7 +20616,7 @@ std::pair avx2_convert_utf16_to_utf8_with_errors(const char16_t*
   return std::make_pair(result(error_code::SUCCESS, buf - start), utf8_output);
 }
 /* end file src/haswell/avx2_convert_utf16_to_utf8.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=haswell/avx2_convert_utf16_to_utf32.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=haswell/avx2_convert_utf16_to_utf32.cpp
 /* begin file src/haswell/avx2_convert_utf16_to_utf32.cpp */
 /*
     The vectorized algorithm works on single SSE register i.e., it
@@ -20793,7 +20801,7 @@ std::pair avx2_convert_utf16_to_utf32_with_errors(const char1
 }
 /* end file src/haswell/avx2_convert_utf16_to_utf32.cpp */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=haswell/avx2_convert_utf32_to_utf8.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=haswell/avx2_convert_utf32_to_utf8.cpp
 /* begin file src/haswell/avx2_convert_utf32_to_utf8.cpp */
 std::pair avx2_convert_utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_output) {
   const char32_t* end = buf + len;
@@ -21276,7 +21284,7 @@ std::pair avx2_convert_utf32_to_utf8_with_errors(const char32_t*
   return std::make_pair(result(error_code::SUCCESS, buf - start), utf8_output);
 }
 /* end file src/haswell/avx2_convert_utf32_to_utf8.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=haswell/avx2_convert_utf32_to_utf16.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=haswell/avx2_convert_utf32_to_utf16.cpp
 /* begin file src/haswell/avx2_convert_utf32_to_utf16.cpp */
 template 
 std::pair avx2_convert_utf32_to_utf16(const char32_t* buf, size_t len, char16_t* utf16_output) {
@@ -21412,7 +21420,7 @@ std::pair avx2_convert_utf32_to_utf16_with_errors(const char3
 } // namespace haswell
 } // namespace simdutf
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/buf_block_reader.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/buf_block_reader.h
 /* begin file src/generic/buf_block_reader.h */
 namespace simdutf {
 namespace haswell {
@@ -21507,7 +21515,7 @@ simdutf_really_inline void buf_block_reader::advance() {
 } // namespace haswell
 } // namespace simdutf
 /* end file src/generic/buf_block_reader.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_validation/utf8_lookup4_algorithm.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_validation/utf8_lookup4_algorithm.h
 /* begin file src/generic/utf8_validation/utf8_lookup4_algorithm.h */
 namespace simdutf {
 namespace haswell {
@@ -21696,7 +21704,7 @@ using utf8_validation::utf8_checker;
 } // namespace haswell
 } // namespace simdutf
 /* end file src/generic/utf8_validation/utf8_lookup4_algorithm.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_validation/utf8_validator.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_validation/utf8_validator.h
 /* begin file src/generic/utf8_validation/utf8_validator.h */
 namespace simdutf {
 namespace haswell {
@@ -21741,7 +21749,7 @@ result generic_validate_utf8_with_errors(const uint8_t * input, size_t length) {
       c.check_next_input(in);
       if(c.errors()) {
         if (count != 0) { count--; } // Sometimes the error is only detected in the next chunk
-        result res = scalar::utf8::rewind_and_validate_with_errors(reinterpret_cast(input + count), length - count);
+        result res = scalar::utf8::rewind_and_validate_with_errors(reinterpret_cast(input), reinterpret_cast(input + count), length - count);
         res.count += count;
         return res;
       }
@@ -21755,7 +21763,8 @@ result generic_validate_utf8_with_errors(const uint8_t * input, size_t length) {
     reader.advance();
     c.check_eof();
     if (c.errors()) {
-      result res = scalar::utf8::rewind_and_validate_with_errors(reinterpret_cast(input) + count, length - count);
+      if (count != 0) { count--; } // Sometimes the error is only detected in the next chunk
+      result res = scalar::utf8::rewind_and_validate_with_errors(reinterpret_cast(input), reinterpret_cast(input) + count, length - count);
       res.count += count;
       return res;
     } else {
@@ -21823,7 +21832,7 @@ result generic_validate_ascii_with_errors(const char * input, size_t length) {
 } // namespace simdutf
 /* end file src/generic/utf8_validation/utf8_validator.h */
 // transcoding from UTF-8 to UTF-16
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf16/valid_utf8_to_utf16.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf16/valid_utf8_to_utf16.h
 /* begin file src/generic/utf8_to_utf16/valid_utf8_to_utf16.h */
 
 
@@ -21898,7 +21907,7 @@ simdutf_warn_unused size_t convert_valid(const char* input, size_t size,
 } // namespace haswell
 } // namespace simdutf
 /* end file src/generic/utf8_to_utf16/valid_utf8_to_utf16.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf16/utf8_to_utf16.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf16/utf8_to_utf16.h
 /* begin file src/generic/utf8_to_utf16/utf8_to_utf16.h */
 
 
@@ -22206,7 +22215,7 @@ using namespace simd;
 } // namespace simdutf
 /* end file src/generic/utf8_to_utf16/utf8_to_utf16.h */
 // transcoding from UTF-8 to UTF-32
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf32/valid_utf8_to_utf32.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf32/valid_utf8_to_utf32.h
 /* begin file src/generic/utf8_to_utf32/valid_utf8_to_utf32.h */
 
 namespace simdutf {
@@ -22252,7 +22261,7 @@ simdutf_warn_unused size_t convert_valid(const char* input, size_t size,
 } // namespace haswell
 } // namespace simdutf
 /* end file src/generic/utf8_to_utf32/valid_utf8_to_utf32.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf32/utf8_to_utf32.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf32/utf8_to_utf32.h
 /* begin file src/generic/utf8_to_utf32/utf8_to_utf32.h */
 
 
@@ -22553,7 +22562,7 @@ using namespace simd;
 } // namespace simdutf
 /* end file src/generic/utf8_to_utf32/utf8_to_utf32.h */
 // other functions
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8.h
 /* begin file src/generic/utf8.h */
 
 namespace simdutf {
@@ -22600,7 +22609,7 @@ simdutf_really_inline size_t utf32_length_from_utf8(const char* in, size_t size)
 } // namespace haswell
 } // namespace simdutf
 /* end file src/generic/utf8.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf16.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf16.h
 /* begin file src/generic/utf16.h */
 namespace simdutf {
 namespace haswell {
@@ -23128,7 +23137,7 @@ simdutf_warn_unused size_t implementation::utf32_length_from_utf8(const char * i
 } // namespace haswell
 } // namespace simdutf
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/haswell/end.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/haswell/end.h
 /* begin file src/simdutf/haswell/end.h */
 #if SIMDUTF_CAN_ALWAYS_RUN_HASWELL
 // nothing needed.
@@ -23144,14 +23153,14 @@ SIMDUTF_POP_DISABLE_WARNINGS
 /* end file src/haswell/implementation.cpp */
 #endif
 #if SIMDUTF_IMPLEMENTATION_PPC64
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=ppc64/implementation.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=ppc64/implementation.cpp
 /* begin file src/ppc64/implementation.cpp */
 
 
 
 
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/ppc64/begin.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/ppc64/begin.h
 /* begin file src/simdutf/ppc64/begin.h */
 // redefining SIMDUTF_IMPLEMENTATION to "ppc64"
 // #define SIMDUTF_IMPLEMENTATION ppc64
@@ -23189,7 +23198,7 @@ simdutf_really_inline simd8 must_be_2_3_continuation(const simd8
 } // namespace ppc64
 } // namespace simdutf
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/buf_block_reader.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/buf_block_reader.h
 /* begin file src/generic/buf_block_reader.h */
 namespace simdutf {
 namespace ppc64 {
@@ -23284,7 +23293,7 @@ simdutf_really_inline void buf_block_reader::advance() {
 } // namespace ppc64
 } // namespace simdutf
 /* end file src/generic/buf_block_reader.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_validation/utf8_lookup4_algorithm.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_validation/utf8_lookup4_algorithm.h
 /* begin file src/generic/utf8_validation/utf8_lookup4_algorithm.h */
 namespace simdutf {
 namespace ppc64 {
@@ -23473,7 +23482,7 @@ using utf8_validation::utf8_checker;
 } // namespace ppc64
 } // namespace simdutf
 /* end file src/generic/utf8_validation/utf8_lookup4_algorithm.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_validation/utf8_validator.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_validation/utf8_validator.h
 /* begin file src/generic/utf8_validation/utf8_validator.h */
 namespace simdutf {
 namespace ppc64 {
@@ -23518,7 +23527,7 @@ result generic_validate_utf8_with_errors(const uint8_t * input, size_t length) {
       c.check_next_input(in);
       if(c.errors()) {
         if (count != 0) { count--; } // Sometimes the error is only detected in the next chunk
-        result res = scalar::utf8::rewind_and_validate_with_errors(reinterpret_cast(input + count), length - count);
+        result res = scalar::utf8::rewind_and_validate_with_errors(reinterpret_cast(input), reinterpret_cast(input + count), length - count);
         res.count += count;
         return res;
       }
@@ -23532,7 +23541,8 @@ result generic_validate_utf8_with_errors(const uint8_t * input, size_t length) {
     reader.advance();
     c.check_eof();
     if (c.errors()) {
-      result res = scalar::utf8::rewind_and_validate_with_errors(reinterpret_cast(input) + count, length - count);
+      if (count != 0) { count--; } // Sometimes the error is only detected in the next chunk
+      result res = scalar::utf8::rewind_and_validate_with_errors(reinterpret_cast(input), reinterpret_cast(input) + count, length - count);
       res.count += count;
       return res;
     } else {
@@ -23600,7 +23610,7 @@ result generic_validate_ascii_with_errors(const char * input, size_t length) {
 } // namespace simdutf
 /* end file src/generic/utf8_validation/utf8_validator.h */
 // transcoding from UTF-8 to UTF-16
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf16/valid_utf8_to_utf16.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf16/valid_utf8_to_utf16.h
 /* begin file src/generic/utf8_to_utf16/valid_utf8_to_utf16.h */
 
 
@@ -23675,7 +23685,7 @@ simdutf_warn_unused size_t convert_valid(const char* input, size_t size,
 } // namespace ppc64
 } // namespace simdutf
 /* end file src/generic/utf8_to_utf16/valid_utf8_to_utf16.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf16/utf8_to_utf16.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf16/utf8_to_utf16.h
 /* begin file src/generic/utf8_to_utf16/utf8_to_utf16.h */
 
 
@@ -23983,7 +23993,7 @@ using namespace simd;
 } // namespace simdutf
 /* end file src/generic/utf8_to_utf16/utf8_to_utf16.h */
 // transcoding from UTF-8 to UTF-32
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf32/valid_utf8_to_utf32.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf32/valid_utf8_to_utf32.h
 /* begin file src/generic/utf8_to_utf32/valid_utf8_to_utf32.h */
 
 namespace simdutf {
@@ -24029,7 +24039,7 @@ simdutf_warn_unused size_t convert_valid(const char* input, size_t size,
 } // namespace ppc64
 } // namespace simdutf
 /* end file src/generic/utf8_to_utf32/valid_utf8_to_utf32.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf32/utf8_to_utf32.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf32/utf8_to_utf32.h
 /* begin file src/generic/utf8_to_utf32/utf8_to_utf32.h */
 
 
@@ -24330,7 +24340,7 @@ using namespace simd;
 } // namespace simdutf
 /* end file src/generic/utf8_to_utf32/utf8_to_utf32.h */
 // other functions
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8.h
 /* begin file src/generic/utf8.h */
 
 namespace simdutf {
@@ -24377,7 +24387,7 @@ simdutf_really_inline size_t utf32_length_from_utf8(const char* in, size_t size)
 } // namespace ppc64
 } // namespace simdutf
 /* end file src/generic/utf8.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf16.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf16.h
 /* begin file src/generic/utf16.h */
 namespace simdutf {
 namespace ppc64 {
@@ -24676,15 +24686,15 @@ simdutf_warn_unused size_t implementation::utf32_length_from_utf8(const char * i
 } // namespace ppc64
 } // namespace simdutf
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/ppc64/end.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/ppc64/end.h
 /* begin file src/simdutf/ppc64/end.h */
 /* end file src/simdutf/ppc64/end.h */
 /* end file src/ppc64/implementation.cpp */
 #endif
 #if SIMDUTF_IMPLEMENTATION_WESTMERE
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=westmere/implementation.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=westmere/implementation.cpp
 /* begin file src/westmere/implementation.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/westmere/begin.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/westmere/begin.h
 /* begin file src/simdutf/westmere/begin.h */
 // redefining SIMDUTF_IMPLEMENTATION to "westmere"
 // #define SIMDUTF_IMPLEMENTATION westmere
@@ -24722,7 +24732,7 @@ simdutf_really_inline simd8 must_be_2_3_continuation(const simd8
   return simd8(is_third_byte | is_fourth_byte) > int8_t(0);
 }
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=westmere/sse_detect_encodings.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=westmere/sse_detect_encodings.cpp
 /* begin file src/westmere/sse_detect_encodings.cpp */
 template
 // len is known to be a multiple of 2 when this is called
@@ -24932,7 +24942,7 @@ int sse_detect_encodings(const char * buf, size_t len) {
 }
 /* end file src/westmere/sse_detect_encodings.cpp */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=westmere/sse_validate_utf16.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=westmere/sse_validate_utf16.cpp
 /* begin file src/westmere/sse_validate_utf16.cpp */
 /*
     In UTF-16 words in range 0xD800 to 0xDFFF have special meaning.
@@ -25132,7 +25142,7 @@ const result sse_validate_utf16_with_errors(const char16_t* input, size_t size)
     return result(error_code::SUCCESS, input - start);
 }
 /* end file src/westmere/sse_validate_utf16.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=westmere/sse_validate_utf32le.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=westmere/sse_validate_utf32le.cpp
 /* begin file src/westmere/sse_validate_utf32le.cpp */
 /* Returns:
    - pointer to the last unprocessed character (a scalar fallback should check the rest);
@@ -25198,7 +25208,7 @@ const result sse_validate_utf32le_with_errors(const char32_t* input, size_t size
 }
 /* end file src/westmere/sse_validate_utf32le.cpp */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=westmere/sse_convert_utf8_to_utf16.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=westmere/sse_convert_utf8_to_utf16.cpp
 /* begin file src/westmere/sse_convert_utf8_to_utf16.cpp */
 // depends on "tables/utf8_to_utf16_tables.h"
 
@@ -25383,7 +25393,7 @@ size_t convert_masked_utf8_to_utf16(const char *input,
   return consumed;
 }
 /* end file src/westmere/sse_convert_utf8_to_utf16.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=westmere/sse_convert_utf8_to_utf32.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=westmere/sse_convert_utf8_to_utf32.cpp
 /* begin file src/westmere/sse_convert_utf8_to_utf32.cpp */
 // depends on "tables/utf8_to_utf16_tables.h"
 
@@ -25515,7 +25525,7 @@ size_t convert_masked_utf8_to_utf32(const char *input,
 }
 /* end file src/westmere/sse_convert_utf8_to_utf32.cpp */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=westmere/sse_convert_utf16_to_utf8.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=westmere/sse_convert_utf16_to_utf8.cpp
 /* begin file src/westmere/sse_convert_utf16_to_utf8.cpp */
 /*
     The vectorized algorithm works on single SSE register i.e., it
@@ -26043,7 +26053,7 @@ std::pair sse_convert_utf16_to_utf8_with_errors(const char16_t* b
   return std::make_pair(result(error_code::SUCCESS, buf - start), utf8_output);
 }
 /* end file src/westmere/sse_convert_utf16_to_utf8.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=westmere/sse_convert_utf16_to_utf32.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=westmere/sse_convert_utf16_to_utf32.cpp
 /* begin file src/westmere/sse_convert_utf16_to_utf32.cpp */
 /*
     The vectorized algorithm works on single SSE register i.e., it
@@ -26227,7 +26237,7 @@ std::pair sse_convert_utf16_to_utf32_with_errors(const char16
 }
 /* end file src/westmere/sse_convert_utf16_to_utf32.cpp */
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=westmere/sse_convert_utf32_to_utf8.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=westmere/sse_convert_utf32_to_utf8.cpp
 /* begin file src/westmere/sse_convert_utf32_to_utf8.cpp */
 std::pair sse_convert_utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_output) {
   const char32_t* end = buf + len;
@@ -26728,7 +26738,7 @@ std::pair sse_convert_utf32_to_utf8_with_errors(const char32_t* b
   return std::make_pair(result(error_code::SUCCESS, buf - start), utf8_output);
 }
 /* end file src/westmere/sse_convert_utf32_to_utf8.cpp */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=westmere/sse_convert_utf32_to_utf16.cpp
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=westmere/sse_convert_utf32_to_utf16.cpp
 /* begin file src/westmere/sse_convert_utf32_to_utf16.cpp */
 template 
 std::pair sse_convert_utf32_to_utf16(const char32_t* buf, size_t len, char16_t* utf16_output) {
@@ -26867,7 +26877,7 @@ std::pair sse_convert_utf32_to_utf16_with_errors(const char32
 } // namespace westmere
 } // namespace simdutf
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/buf_block_reader.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/buf_block_reader.h
 /* begin file src/generic/buf_block_reader.h */
 namespace simdutf {
 namespace westmere {
@@ -26962,7 +26972,7 @@ simdutf_really_inline void buf_block_reader::advance() {
 } // namespace westmere
 } // namespace simdutf
 /* end file src/generic/buf_block_reader.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_validation/utf8_lookup4_algorithm.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_validation/utf8_lookup4_algorithm.h
 /* begin file src/generic/utf8_validation/utf8_lookup4_algorithm.h */
 namespace simdutf {
 namespace westmere {
@@ -27151,7 +27161,7 @@ using utf8_validation::utf8_checker;
 } // namespace westmere
 } // namespace simdutf
 /* end file src/generic/utf8_validation/utf8_lookup4_algorithm.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_validation/utf8_validator.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_validation/utf8_validator.h
 /* begin file src/generic/utf8_validation/utf8_validator.h */
 namespace simdutf {
 namespace westmere {
@@ -27196,7 +27206,7 @@ result generic_validate_utf8_with_errors(const uint8_t * input, size_t length) {
       c.check_next_input(in);
       if(c.errors()) {
         if (count != 0) { count--; } // Sometimes the error is only detected in the next chunk
-        result res = scalar::utf8::rewind_and_validate_with_errors(reinterpret_cast(input + count), length - count);
+        result res = scalar::utf8::rewind_and_validate_with_errors(reinterpret_cast(input), reinterpret_cast(input + count), length - count);
         res.count += count;
         return res;
       }
@@ -27210,7 +27220,8 @@ result generic_validate_utf8_with_errors(const uint8_t * input, size_t length) {
     reader.advance();
     c.check_eof();
     if (c.errors()) {
-      result res = scalar::utf8::rewind_and_validate_with_errors(reinterpret_cast(input) + count, length - count);
+      if (count != 0) { count--; } // Sometimes the error is only detected in the next chunk
+      result res = scalar::utf8::rewind_and_validate_with_errors(reinterpret_cast(input), reinterpret_cast(input) + count, length - count);
       res.count += count;
       return res;
     } else {
@@ -27278,7 +27289,7 @@ result generic_validate_ascii_with_errors(const char * input, size_t length) {
 } // namespace simdutf
 /* end file src/generic/utf8_validation/utf8_validator.h */
 // transcoding from UTF-8 to UTF-16
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf16/valid_utf8_to_utf16.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf16/valid_utf8_to_utf16.h
 /* begin file src/generic/utf8_to_utf16/valid_utf8_to_utf16.h */
 
 
@@ -27353,7 +27364,7 @@ simdutf_warn_unused size_t convert_valid(const char* input, size_t size,
 } // namespace westmere
 } // namespace simdutf
 /* end file src/generic/utf8_to_utf16/valid_utf8_to_utf16.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf16/utf8_to_utf16.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf16/utf8_to_utf16.h
 /* begin file src/generic/utf8_to_utf16/utf8_to_utf16.h */
 
 
@@ -27661,7 +27672,7 @@ using namespace simd;
 } // namespace simdutf
 /* end file src/generic/utf8_to_utf16/utf8_to_utf16.h */
 // transcoding from UTF-8 to UTF-32
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf32/valid_utf8_to_utf32.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf32/valid_utf8_to_utf32.h
 /* begin file src/generic/utf8_to_utf32/valid_utf8_to_utf32.h */
 
 namespace simdutf {
@@ -27707,7 +27718,7 @@ simdutf_warn_unused size_t convert_valid(const char* input, size_t size,
 } // namespace westmere
 } // namespace simdutf
 /* end file src/generic/utf8_to_utf32/valid_utf8_to_utf32.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf32/utf8_to_utf32.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8_to_utf32/utf8_to_utf32.h
 /* begin file src/generic/utf8_to_utf32/utf8_to_utf32.h */
 
 
@@ -28008,7 +28019,7 @@ using namespace simd;
 } // namespace simdutf
 /* end file src/generic/utf8_to_utf32/utf8_to_utf32.h */
 // other functions
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf8.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf8.h
 /* begin file src/generic/utf8.h */
 
 namespace simdutf {
@@ -28055,7 +28066,7 @@ simdutf_really_inline size_t utf32_length_from_utf8(const char* in, size_t size)
 } // namespace westmere
 } // namespace simdutf
 /* end file src/generic/utf8.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=generic/utf16.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=generic/utf16.h
 /* begin file src/generic/utf16.h */
 namespace simdutf {
 namespace westmere {
@@ -28587,7 +28598,7 @@ simdutf_warn_unused size_t implementation::utf32_length_from_utf8(const char * i
 } // namespace westmere
 } // namespace simdutf
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/src, filename=simdutf/westmere/end.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/src, filename=simdutf/westmere/end.h
 /* begin file src/simdutf/westmere/end.h */
 #if SIMDUTF_CAN_ALWAYS_RUN_WESTMERE
 // nothing needed.
diff --git a/deps/simdutf/simdutf.h b/deps/simdutf/simdutf.h
index f63c163c0f2b30..6ab1c34d7b30a7 100644
--- a/deps/simdutf/simdutf.h
+++ b/deps/simdutf/simdutf.h
@@ -1,11 +1,11 @@
-/* auto-generated on 2023-06-05 08:58:28 -0400. Do not edit! */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/include, filename=simdutf.h
+/* auto-generated on 2023-10-08 13:48:09 -0400. Do not edit! */
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/include, filename=simdutf.h
 /* begin file include/simdutf.h */
 #ifndef SIMDUTF_H
 #define SIMDUTF_H
 #include 
 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/include, filename=simdutf/compiler_check.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/include, filename=simdutf/compiler_check.h
 /* begin file include/simdutf/compiler_check.h */
 #ifndef SIMDUTF_COMPILER_CHECK_H
 #define SIMDUTF_COMPILER_CHECK_H
@@ -43,13 +43,13 @@
 
 #endif // SIMDUTF_COMPILER_CHECK_H
 /* end file include/simdutf/compiler_check.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/include, filename=simdutf/common_defs.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/include, filename=simdutf/common_defs.h
 /* begin file include/simdutf/common_defs.h */
 #ifndef SIMDUTF_COMMON_DEFS_H
 #define SIMDUTF_COMMON_DEFS_H
 
 #include 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/include, filename=simdutf/portability.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/include, filename=simdutf/portability.h
 /* begin file include/simdutf/portability.h */
 #ifndef SIMDUTF_PORTABILITY_H
 #define SIMDUTF_PORTABILITY_H
@@ -280,7 +280,7 @@ use a 64-bit target such as x64, 64-bit ARM or 64-bit PPC.")
 
 #endif // SIMDUTF_PORTABILITY_H
 /* end file include/simdutf/portability.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/include, filename=simdutf/avx512.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/include, filename=simdutf/avx512.h
 /* begin file include/simdutf/avx512.h */
 #ifndef SIMDUTF_AVX512_H_
 #define SIMDUTF_AVX512_H_
@@ -483,7 +483,7 @@ use a 64-bit target such as x64, 64-bit ARM or 64-bit PPC.")
 
 #endif // SIMDUTF_COMMON_DEFS_H
 /* end file include/simdutf/common_defs.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/include, filename=simdutf/encoding_types.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/include, filename=simdutf/encoding_types.h
 /* begin file include/simdutf/encoding_types.h */
 #include 
 
@@ -531,7 +531,7 @@ size_t bom_byte_size(encoding_type bom);
 } // BOM namespace
 } // simdutf namespace
 /* end file include/simdutf/encoding_types.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/include, filename=simdutf/error.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/include, filename=simdutf/error.h
 /* begin file include/simdutf/error.h */
 #ifndef ERROR_H
 #define ERROR_H
@@ -568,7 +568,7 @@ SIMDUTF_PUSH_DISABLE_WARNINGS
 SIMDUTF_DISABLE_UNDESIRED_WARNINGS
 
 // Public API
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/include, filename=simdutf/simdutf_version.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/include, filename=simdutf/simdutf_version.h
 /* begin file include/simdutf/simdutf_version.h */
 // /include/simdutf/simdutf_version.h automatically generated by release.py,
 // do not change by hand
@@ -576,7 +576,7 @@ SIMDUTF_DISABLE_UNDESIRED_WARNINGS
 #define SIMDUTF_SIMDUTF_VERSION_H
 
 /** The version of simdutf being used (major.minor.revision) */
-#define SIMDUTF_VERSION "3.2.14"
+#define SIMDUTF_VERSION "3.2.18"
 
 namespace simdutf {
 enum {
@@ -591,13 +591,13 @@ enum {
   /**
    * The revision (major.minor.REVISION) of simdutf being used.
    */
-  SIMDUTF_VERSION_REVISION = 14
+  SIMDUTF_VERSION_REVISION = 18
 };
 } // namespace simdutf
 
 #endif // SIMDUTF_SIMDUTF_VERSION_H
 /* end file include/simdutf/simdutf_version.h */
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/include, filename=simdutf/implementation.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/include, filename=simdutf/implementation.h
 /* begin file include/simdutf/implementation.h */
 #ifndef SIMDUTF_IMPLEMENTATION_H
 #define SIMDUTF_IMPLEMENTATION_H
@@ -607,7 +607,7 @@ enum {
 #endif
 #include 
 #include 
-// dofile: invoked with prepath=/Users/lemire/CVS/github/simdutf/include, filename=simdutf/internal/isadetection.h
+// dofile: invoked with prepath=/Users/dlemire/CVS/github/simdutf/include, filename=simdutf/internal/isadetection.h
 /* begin file include/simdutf/internal/isadetection.h */
 /* From
 https://github.com/endorno/pytorch/blob/master/torch/lib/TH/generic/simd/simd.h
diff --git a/deps/undici/src/docs/api/DispatchInterceptor.md b/deps/undici/src/docs/api/DispatchInterceptor.md
index 652b2e86bf9920..7dfc260e32a9c8 100644
--- a/deps/undici/src/docs/api/DispatchInterceptor.md
+++ b/deps/undici/src/docs/api/DispatchInterceptor.md
@@ -1,4 +1,4 @@
-#Interface: DispatchInterceptor
+# Interface: DispatchInterceptor
 
 Extends: `Function`
 
diff --git a/deps/undici/src/lib/api/api-stream.js b/deps/undici/src/lib/api/api-stream.js
index 3a8e71a5730eee..c571a6f79a7d06 100644
--- a/deps/undici/src/lib/api/api-stream.js
+++ b/deps/undici/src/lib/api/api-stream.js
@@ -104,6 +104,10 @@ class StreamHandler extends AsyncResource {
         { callback, body: res, contentType, statusCode, statusMessage, headers }
       )
     } else {
+      if (factory === null) {
+        return
+      }
+
       res = this.runInAsyncScope(factory, null, {
         statusCode,
         headers,
@@ -152,7 +156,7 @@ class StreamHandler extends AsyncResource {
   onData (chunk) {
     const { res } = this
 
-    return res.write(chunk)
+    return res ? res.write(chunk) : true
   }
 
   onComplete (trailers) {
@@ -160,6 +164,10 @@ class StreamHandler extends AsyncResource {
 
     removeSignal(this)
 
+    if (!res) {
+      return
+    }
+
     this.trailers = util.parseHeaders(trailers)
 
     res.end()
diff --git a/deps/undici/src/lib/api/readable.js b/deps/undici/src/lib/api/readable.js
index 398a75ba8bbaa7..fa05d9195de655 100644
--- a/deps/undici/src/lib/api/readable.js
+++ b/deps/undici/src/lib/api/readable.js
@@ -265,7 +265,7 @@ function consumeEnd (consume) {
         pos += buf.byteLength
       }
 
-      resolve(dst)
+      resolve(dst.buffer)
     } else if (type === 'blob') {
       if (!Blob) {
         Blob = require('buffer').Blob
diff --git a/deps/undici/src/lib/client.js b/deps/undici/src/lib/client.js
index 065fb563380dcc..00f4467cc8b718 100644
--- a/deps/undici/src/lib/client.js
+++ b/deps/undici/src/lib/client.js
@@ -1070,7 +1070,9 @@ function onParserTimeout (parser) {
 
 function onSocketReadable () {
   const { [kParser]: parser } = this
-  parser.readMore()
+  if (parser) {
+    parser.readMore()
+  }
 }
 
 function onSocketError (err) {
diff --git a/deps/undici/src/package-lock.json b/deps/undici/src/package-lock.json
new file mode 100644
index 00000000000000..eb929e548c2d86
--- /dev/null
+++ b/deps/undici/src/package-lock.json
@@ -0,0 +1,15026 @@
+{
+  "name": "undici",
+  "version": "5.26.4",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "undici",
+      "version": "5.26.4",
+      "license": "MIT",
+      "dependencies": {
+        "@fastify/busboy": "^2.0.0"
+      },
+      "devDependencies": {
+        "@sinonjs/fake-timers": "^11.1.0",
+        "@types/node": "^18.0.3",
+        "abort-controller": "^3.0.0",
+        "atomic-sleep": "^1.0.0",
+        "chai": "^4.3.4",
+        "chai-as-promised": "^7.1.1",
+        "chai-iterator": "^3.0.2",
+        "chai-string": "^1.5.0",
+        "concurrently": "^8.0.1",
+        "cronometro": "^1.0.5",
+        "delay": "^5.0.0",
+        "dns-packet": "^5.4.0",
+        "docsify-cli": "^4.4.3",
+        "form-data": "^4.0.0",
+        "formdata-node": "^4.3.1",
+        "https-pem": "^3.0.0",
+        "husky": "^8.0.1",
+        "import-fresh": "^3.3.0",
+        "jest": "^29.0.2",
+        "jsdom": "^22.1.0",
+        "jsfuzz": "^1.0.15",
+        "mocha": "^10.0.0",
+        "p-timeout": "^3.2.0",
+        "pre-commit": "^1.2.2",
+        "proxy": "^1.0.2",
+        "proxyquire": "^2.1.3",
+        "semver": "^7.5.4",
+        "sinon": "^16.1.0",
+        "snazzy": "^9.0.0",
+        "standard": "^17.0.0",
+        "table": "^6.8.0",
+        "tap": "^16.1.0",
+        "tsd": "^0.29.0",
+        "typescript": "^5.0.2",
+        "wait-on": "^7.0.1",
+        "ws": "^8.11.0"
+      },
+      "engines": {
+        "node": ">=14.0"
+      }
+    },
+    "node_modules/@aashutoshrathi/word-wrap": {
+      "version": "1.2.6",
+      "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
+      "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/@ampproject/remapping": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
+      "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.0",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@assemblyscript/loader": {
+      "version": "0.19.23",
+      "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.19.23.tgz",
+      "integrity": "sha512-ulkCYfFbYj01ie1MDOyxv2F6SpRN1TOj7fQxbP07D6HmeR+gr2JLSmINKjga2emB+b1L2KGrFKBTc+e00p54nw==",
+      "dev": true
+    },
+    "node_modules/@babel/code-frame": {
+      "version": "7.22.13",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
+      "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
+      "dev": true,
+      "dependencies": {
+        "@babel/highlight": "^7.22.13",
+        "chalk": "^2.4.2"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/code-frame/node_modules/ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "dev": true,
+      "dependencies": {
+        "color-convert": "^1.9.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/@babel/code-frame/node_modules/chalk": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/@babel/code-frame/node_modules/color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "dev": true,
+      "dependencies": {
+        "color-name": "1.1.3"
+      }
+    },
+    "node_modules/@babel/code-frame/node_modules/color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+      "dev": true
+    },
+    "node_modules/@babel/code-frame/node_modules/escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.8.0"
+      }
+    },
+    "node_modules/@babel/code-frame/node_modules/has-flag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/@babel/code-frame/node_modules/supports-color": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/@babel/compat-data": {
+      "version": "7.23.2",
+      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz",
+      "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/core": {
+      "version": "7.23.2",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz",
+      "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==",
+      "dev": true,
+      "dependencies": {
+        "@ampproject/remapping": "^2.2.0",
+        "@babel/code-frame": "^7.22.13",
+        "@babel/generator": "^7.23.0",
+        "@babel/helper-compilation-targets": "^7.22.15",
+        "@babel/helper-module-transforms": "^7.23.0",
+        "@babel/helpers": "^7.23.2",
+        "@babel/parser": "^7.23.0",
+        "@babel/template": "^7.22.15",
+        "@babel/traverse": "^7.23.2",
+        "@babel/types": "^7.23.0",
+        "convert-source-map": "^2.0.0",
+        "debug": "^4.1.0",
+        "gensync": "^1.0.0-beta.2",
+        "json5": "^2.2.3",
+        "semver": "^6.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/babel"
+      }
+    },
+    "node_modules/@babel/core/node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@babel/core/node_modules/ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
+    "node_modules/@babel/core/node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/@babel/generator": {
+      "version": "7.23.0",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
+      "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
+      "dev": true,
+      "dependencies": {
+        "@babel/types": "^7.23.0",
+        "@jridgewell/gen-mapping": "^0.3.2",
+        "@jridgewell/trace-mapping": "^0.3.17",
+        "jsesc": "^2.5.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-compilation-targets": {
+      "version": "7.22.15",
+      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz",
+      "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/compat-data": "^7.22.9",
+        "@babel/helper-validator-option": "^7.22.15",
+        "browserslist": "^4.21.9",
+        "lru-cache": "^5.1.1",
+        "semver": "^6.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/@babel/helper-environment-visitor": {
+      "version": "7.22.20",
+      "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
+      "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-function-name": {
+      "version": "7.23.0",
+      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
+      "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/template": "^7.22.15",
+        "@babel/types": "^7.23.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-hoist-variables": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
+      "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-module-imports": {
+      "version": "7.22.15",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
+      "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
+      "dev": true,
+      "dependencies": {
+        "@babel/types": "^7.22.15"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-module-transforms": {
+      "version": "7.23.0",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz",
+      "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-environment-visitor": "^7.22.20",
+        "@babel/helper-module-imports": "^7.22.15",
+        "@babel/helper-simple-access": "^7.22.5",
+        "@babel/helper-split-export-declaration": "^7.22.6",
+        "@babel/helper-validator-identifier": "^7.22.20"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/helper-plugin-utils": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+      "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-simple-access": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
+      "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
+      "dev": true,
+      "dependencies": {
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-split-export-declaration": {
+      "version": "7.22.6",
+      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
+      "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
+      "dev": true,
+      "dependencies": {
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-string-parser": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
+      "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-identifier": {
+      "version": "7.22.20",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
+      "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-option": {
+      "version": "7.22.15",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz",
+      "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helpers": {
+      "version": "7.23.2",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz",
+      "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/template": "^7.22.15",
+        "@babel/traverse": "^7.23.2",
+        "@babel/types": "^7.23.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/highlight": {
+      "version": "7.22.20",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
+      "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-validator-identifier": "^7.22.20",
+        "chalk": "^2.4.2",
+        "js-tokens": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/highlight/node_modules/ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "dev": true,
+      "dependencies": {
+        "color-convert": "^1.9.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/@babel/highlight/node_modules/chalk": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/@babel/highlight/node_modules/color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "dev": true,
+      "dependencies": {
+        "color-name": "1.1.3"
+      }
+    },
+    "node_modules/@babel/highlight/node_modules/color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+      "dev": true
+    },
+    "node_modules/@babel/highlight/node_modules/escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.8.0"
+      }
+    },
+    "node_modules/@babel/highlight/node_modules/has-flag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/@babel/highlight/node_modules/supports-color": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/@babel/parser": {
+      "version": "7.23.0",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
+      "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
+      "dev": true,
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-async-generators": {
+      "version": "7.8.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+      "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-bigint": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
+      "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-class-properties": {
+      "version": "7.12.13",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+      "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.12.13"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-import-meta": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+      "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-json-strings": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+      "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-jsx": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz",
+      "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+      "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+      "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-numeric-separator": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+      "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-object-rest-spread": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+      "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+      "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-optional-chaining": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+      "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-top-level-await": {
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+      "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.14.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-typescript": {
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz",
+      "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/runtime": {
+      "version": "7.23.2",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz",
+      "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==",
+      "dev": true,
+      "dependencies": {
+        "regenerator-runtime": "^0.14.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/template": {
+      "version": "7.22.15",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+      "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
+      "dev": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.22.13",
+        "@babel/parser": "^7.22.15",
+        "@babel/types": "^7.22.15"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/traverse": {
+      "version": "7.23.2",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
+      "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.22.13",
+        "@babel/generator": "^7.23.0",
+        "@babel/helper-environment-visitor": "^7.22.20",
+        "@babel/helper-function-name": "^7.23.0",
+        "@babel/helper-hoist-variables": "^7.22.5",
+        "@babel/helper-split-export-declaration": "^7.22.6",
+        "@babel/parser": "^7.23.0",
+        "@babel/types": "^7.23.0",
+        "debug": "^4.1.0",
+        "globals": "^11.1.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/traverse/node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@babel/traverse/node_modules/ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
+    "node_modules/@babel/types": {
+      "version": "7.23.0",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
+      "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-string-parser": "^7.22.5",
+        "@babel/helper-validator-identifier": "^7.22.20",
+        "to-fast-properties": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@bcoe/v8-coverage": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
+      "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+      "dev": true
+    },
+    "node_modules/@eslint-community/eslint-utils": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+      "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+      "dev": true,
+      "dependencies": {
+        "eslint-visitor-keys": "^3.3.0"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "peerDependencies": {
+        "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+      }
+    },
+    "node_modules/@eslint-community/regexpp": {
+      "version": "4.9.1",
+      "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz",
+      "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==",
+      "dev": true,
+      "engines": {
+        "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+      }
+    },
+    "node_modules/@eslint/eslintrc": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz",
+      "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==",
+      "dev": true,
+      "dependencies": {
+        "ajv": "^6.12.4",
+        "debug": "^4.3.2",
+        "espree": "^9.6.0",
+        "globals": "^13.19.0",
+        "ignore": "^5.2.0",
+        "import-fresh": "^3.2.1",
+        "js-yaml": "^4.1.0",
+        "minimatch": "^3.1.2",
+        "strip-json-comments": "^3.1.1"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/@eslint/eslintrc/node_modules/argparse": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+      "dev": true
+    },
+    "node_modules/@eslint/eslintrc/node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@eslint/eslintrc/node_modules/globals": {
+      "version": "13.23.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz",
+      "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==",
+      "dev": true,
+      "dependencies": {
+        "type-fest": "^0.20.2"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@eslint/eslintrc/node_modules/js-yaml": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+      "dev": true,
+      "dependencies": {
+        "argparse": "^2.0.1"
+      },
+      "bin": {
+        "js-yaml": "bin/js-yaml.js"
+      }
+    },
+    "node_modules/@eslint/eslintrc/node_modules/ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
+    "node_modules/@eslint/eslintrc/node_modules/type-fest": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+      "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@eslint/js": {
+      "version": "8.52.0",
+      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz",
+      "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==",
+      "dev": true,
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      }
+    },
+    "node_modules/@fastify/busboy": {
+      "version": "2.0.0",
+      "license": "MIT",
+      "engines": {
+        "node": ">=14"
+      }
+    },
+    "node_modules/@hapi/hoek": {
+      "version": "9.3.0",
+      "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
+      "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==",
+      "dev": true
+    },
+    "node_modules/@hapi/topo": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz",
+      "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==",
+      "dev": true,
+      "dependencies": {
+        "@hapi/hoek": "^9.0.0"
+      }
+    },
+    "node_modules/@humanwhocodes/config-array": {
+      "version": "0.11.13",
+      "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
+      "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==",
+      "dev": true,
+      "dependencies": {
+        "@humanwhocodes/object-schema": "^2.0.1",
+        "debug": "^4.1.1",
+        "minimatch": "^3.0.5"
+      },
+      "engines": {
+        "node": ">=10.10.0"
+      }
+    },
+    "node_modules/@humanwhocodes/config-array/node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@humanwhocodes/config-array/node_modules/ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
+    "node_modules/@humanwhocodes/module-importer": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+      "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+      "dev": true,
+      "engines": {
+        "node": ">=12.22"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/nzakas"
+      }
+    },
+    "node_modules/@humanwhocodes/object-schema": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz",
+      "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==",
+      "dev": true
+    },
+    "node_modules/@istanbuljs/load-nyc-config": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+      "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+      "dev": true,
+      "dependencies": {
+        "camelcase": "^5.3.1",
+        "find-up": "^4.1.0",
+        "get-package-type": "^0.1.0",
+        "js-yaml": "^3.13.1",
+        "resolve-from": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+      "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@istanbuljs/schema": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+      "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@jest/console": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz",
+      "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==",
+      "dev": true,
+      "dependencies": {
+        "@jest/types": "^29.6.3",
+        "@types/node": "*",
+        "chalk": "^4.0.0",
+        "jest-message-util": "^29.7.0",
+        "jest-util": "^29.7.0",
+        "slash": "^3.0.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@jest/core": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz",
+      "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==",
+      "dev": true,
+      "dependencies": {
+        "@jest/console": "^29.7.0",
+        "@jest/reporters": "^29.7.0",
+        "@jest/test-result": "^29.7.0",
+        "@jest/transform": "^29.7.0",
+        "@jest/types": "^29.6.3",
+        "@types/node": "*",
+        "ansi-escapes": "^4.2.1",
+        "chalk": "^4.0.0",
+        "ci-info": "^3.2.0",
+        "exit": "^0.1.2",
+        "graceful-fs": "^4.2.9",
+        "jest-changed-files": "^29.7.0",
+        "jest-config": "^29.7.0",
+        "jest-haste-map": "^29.7.0",
+        "jest-message-util": "^29.7.0",
+        "jest-regex-util": "^29.6.3",
+        "jest-resolve": "^29.7.0",
+        "jest-resolve-dependencies": "^29.7.0",
+        "jest-runner": "^29.7.0",
+        "jest-runtime": "^29.7.0",
+        "jest-snapshot": "^29.7.0",
+        "jest-util": "^29.7.0",
+        "jest-validate": "^29.7.0",
+        "jest-watcher": "^29.7.0",
+        "micromatch": "^4.0.4",
+        "pretty-format": "^29.7.0",
+        "slash": "^3.0.0",
+        "strip-ansi": "^6.0.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      },
+      "peerDependencies": {
+        "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+      },
+      "peerDependenciesMeta": {
+        "node-notifier": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@jest/environment": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
+      "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==",
+      "dev": true,
+      "dependencies": {
+        "@jest/fake-timers": "^29.7.0",
+        "@jest/types": "^29.6.3",
+        "@types/node": "*",
+        "jest-mock": "^29.7.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@jest/expect": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz",
+      "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==",
+      "dev": true,
+      "dependencies": {
+        "expect": "^29.7.0",
+        "jest-snapshot": "^29.7.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@jest/expect-utils": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz",
+      "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==",
+      "dev": true,
+      "dependencies": {
+        "jest-get-type": "^29.6.3"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@jest/fake-timers": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
+      "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==",
+      "dev": true,
+      "dependencies": {
+        "@jest/types": "^29.6.3",
+        "@sinonjs/fake-timers": "^10.0.2",
+        "@types/node": "*",
+        "jest-message-util": "^29.7.0",
+        "jest-mock": "^29.7.0",
+        "jest-util": "^29.7.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@jest/fake-timers/node_modules/@sinonjs/fake-timers": {
+      "version": "10.3.0",
+      "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
+      "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
+      "dev": true,
+      "dependencies": {
+        "@sinonjs/commons": "^3.0.0"
+      }
+    },
+    "node_modules/@jest/globals": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz",
+      "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==",
+      "dev": true,
+      "dependencies": {
+        "@jest/environment": "^29.7.0",
+        "@jest/expect": "^29.7.0",
+        "@jest/types": "^29.6.3",
+        "jest-mock": "^29.7.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@jest/reporters": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz",
+      "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==",
+      "dev": true,
+      "dependencies": {
+        "@bcoe/v8-coverage": "^0.2.3",
+        "@jest/console": "^29.7.0",
+        "@jest/test-result": "^29.7.0",
+        "@jest/transform": "^29.7.0",
+        "@jest/types": "^29.6.3",
+        "@jridgewell/trace-mapping": "^0.3.18",
+        "@types/node": "*",
+        "chalk": "^4.0.0",
+        "collect-v8-coverage": "^1.0.0",
+        "exit": "^0.1.2",
+        "glob": "^7.1.3",
+        "graceful-fs": "^4.2.9",
+        "istanbul-lib-coverage": "^3.0.0",
+        "istanbul-lib-instrument": "^6.0.0",
+        "istanbul-lib-report": "^3.0.0",
+        "istanbul-lib-source-maps": "^4.0.0",
+        "istanbul-reports": "^3.1.3",
+        "jest-message-util": "^29.7.0",
+        "jest-util": "^29.7.0",
+        "jest-worker": "^29.7.0",
+        "slash": "^3.0.0",
+        "string-length": "^4.0.1",
+        "strip-ansi": "^6.0.0",
+        "v8-to-istanbul": "^9.0.1"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      },
+      "peerDependencies": {
+        "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+      },
+      "peerDependenciesMeta": {
+        "node-notifier": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@jest/schemas": {
+      "version": "29.6.3",
+      "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+      "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+      "dev": true,
+      "dependencies": {
+        "@sinclair/typebox": "^0.27.8"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@jest/source-map": {
+      "version": "29.6.3",
+      "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz",
+      "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/trace-mapping": "^0.3.18",
+        "callsites": "^3.0.0",
+        "graceful-fs": "^4.2.9"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@jest/test-result": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz",
+      "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==",
+      "dev": true,
+      "dependencies": {
+        "@jest/console": "^29.7.0",
+        "@jest/types": "^29.6.3",
+        "@types/istanbul-lib-coverage": "^2.0.0",
+        "collect-v8-coverage": "^1.0.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@jest/test-sequencer": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz",
+      "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==",
+      "dev": true,
+      "dependencies": {
+        "@jest/test-result": "^29.7.0",
+        "graceful-fs": "^4.2.9",
+        "jest-haste-map": "^29.7.0",
+        "slash": "^3.0.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@jest/transform": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz",
+      "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/core": "^7.11.6",
+        "@jest/types": "^29.6.3",
+        "@jridgewell/trace-mapping": "^0.3.18",
+        "babel-plugin-istanbul": "^6.1.1",
+        "chalk": "^4.0.0",
+        "convert-source-map": "^2.0.0",
+        "fast-json-stable-stringify": "^2.1.0",
+        "graceful-fs": "^4.2.9",
+        "jest-haste-map": "^29.7.0",
+        "jest-regex-util": "^29.6.3",
+        "jest-util": "^29.7.0",
+        "micromatch": "^4.0.4",
+        "pirates": "^4.0.4",
+        "slash": "^3.0.0",
+        "write-file-atomic": "^4.0.2"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@jest/types": {
+      "version": "29.6.3",
+      "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+      "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+      "dev": true,
+      "dependencies": {
+        "@jest/schemas": "^29.6.3",
+        "@types/istanbul-lib-coverage": "^2.0.0",
+        "@types/istanbul-reports": "^3.0.0",
+        "@types/node": "*",
+        "@types/yargs": "^17.0.8",
+        "chalk": "^4.0.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@jridgewell/gen-mapping": {
+      "version": "0.3.3",
+      "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
+      "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/set-array": "^1.0.1",
+        "@jridgewell/sourcemap-codec": "^1.4.10",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/resolve-uri": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
+      "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/set-array": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+      "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.4.15",
+      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+      "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
+      "dev": true
+    },
+    "node_modules/@jridgewell/trace-mapping": {
+      "version": "0.3.20",
+      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz",
+      "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/resolve-uri": "^3.1.0",
+        "@jridgewell/sourcemap-codec": "^1.4.14"
+      }
+    },
+    "node_modules/@leichtgewicht/ip-codec": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz",
+      "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
+      "dev": true
+    },
+    "node_modules/@nodelib/fs.scandir": {
+      "version": "2.1.5",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+      "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+      "dev": true,
+      "dependencies": {
+        "@nodelib/fs.stat": "2.0.5",
+        "run-parallel": "^1.1.9"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@nodelib/fs.stat": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+      "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+      "dev": true,
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@nodelib/fs.walk": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+      "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+      "dev": true,
+      "dependencies": {
+        "@nodelib/fs.scandir": "2.1.5",
+        "fastq": "^1.6.0"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@sideway/address": {
+      "version": "4.1.4",
+      "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz",
+      "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==",
+      "dev": true,
+      "dependencies": {
+        "@hapi/hoek": "^9.0.0"
+      }
+    },
+    "node_modules/@sideway/formula": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz",
+      "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==",
+      "dev": true
+    },
+    "node_modules/@sideway/pinpoint": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz",
+      "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==",
+      "dev": true
+    },
+    "node_modules/@sinclair/typebox": {
+      "version": "0.27.8",
+      "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
+      "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
+      "dev": true
+    },
+    "node_modules/@sindresorhus/is": {
+      "version": "0.14.0",
+      "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
+      "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/@sinonjs/commons": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz",
+      "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==",
+      "dev": true,
+      "dependencies": {
+        "type-detect": "4.0.8"
+      }
+    },
+    "node_modules/@sinonjs/fake-timers": {
+      "version": "11.2.2",
+      "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz",
+      "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==",
+      "dev": true,
+      "dependencies": {
+        "@sinonjs/commons": "^3.0.0"
+      }
+    },
+    "node_modules/@sinonjs/samsam": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz",
+      "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==",
+      "dev": true,
+      "dependencies": {
+        "@sinonjs/commons": "^2.0.0",
+        "lodash.get": "^4.4.2",
+        "type-detect": "^4.0.8"
+      }
+    },
+    "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz",
+      "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==",
+      "dev": true,
+      "dependencies": {
+        "type-detect": "4.0.8"
+      }
+    },
+    "node_modules/@sinonjs/text-encoding": {
+      "version": "0.7.2",
+      "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz",
+      "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==",
+      "dev": true
+    },
+    "node_modules/@szmarczak/http-timer": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz",
+      "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==",
+      "dev": true,
+      "dependencies": {
+        "defer-to-connect": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/@tootallnate/once": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
+      "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
+      "dev": true,
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tsd/typescript": {
+      "version": "5.2.2",
+      "resolved": "https://registry.npmjs.org/@tsd/typescript/-/typescript-5.2.2.tgz",
+      "integrity": "sha512-VtjHPAKJqLJoHHKBDNofzvQB2+ZVxjXU/Gw6INAS9aINLQYVsxfzrQ2s84huCeYWZRTtrr7R0J7XgpZHjNwBCw==",
+      "dev": true,
+      "engines": {
+        "node": ">=14.17"
+      }
+    },
+    "node_modules/@types/babel__core": {
+      "version": "7.20.3",
+      "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.3.tgz",
+      "integrity": "sha512-54fjTSeSHwfan8AyHWrKbfBWiEUrNTZsUwPTDSNaaP1QDQIZbeNUg3a59E9D+375MzUw/x1vx2/0F5LBz+AeYA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/parser": "^7.20.7",
+        "@babel/types": "^7.20.7",
+        "@types/babel__generator": "*",
+        "@types/babel__template": "*",
+        "@types/babel__traverse": "*"
+      }
+    },
+    "node_modules/@types/babel__generator": {
+      "version": "7.6.6",
+      "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.6.tgz",
+      "integrity": "sha512-66BXMKb/sUWbMdBNdMvajU7i/44RkrA3z/Yt1c7R5xejt8qh84iU54yUWCtm0QwGJlDcf/gg4zd/x4mpLAlb/w==",
+      "dev": true,
+      "dependencies": {
+        "@babel/types": "^7.0.0"
+      }
+    },
+    "node_modules/@types/babel__template": {
+      "version": "7.4.3",
+      "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.3.tgz",
+      "integrity": "sha512-ciwyCLeuRfxboZ4isgdNZi/tkt06m8Tw6uGbBSBgWrnnZGNXiEyM27xc/PjXGQLqlZ6ylbgHMnm7ccF9tCkOeQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/parser": "^7.1.0",
+        "@babel/types": "^7.0.0"
+      }
+    },
+    "node_modules/@types/babel__traverse": {
+      "version": "7.20.3",
+      "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.3.tgz",
+      "integrity": "sha512-Lsh766rGEFbaxMIDH7Qa+Yha8cMVI3qAK6CHt3OR0YfxOIn5Z54iHiyDRycHrBqeIiqGa20Kpsv1cavfBKkRSw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/types": "^7.20.7"
+      }
+    },
+    "node_modules/@types/escodegen": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/@types/escodegen/-/escodegen-0.0.6.tgz",
+      "integrity": "sha512-AjwI4MvWx3HAOaZqYsjKWyEObT9lcVV0Y0V8nXo6cXzN8ZiMxVhf6F3d/UNvXVGKrEzL/Dluc5p+y9GkzlTWig==",
+      "dev": true
+    },
+    "node_modules/@types/eslint": {
+      "version": "7.29.0",
+      "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz",
+      "integrity": "sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng==",
+      "dev": true,
+      "dependencies": {
+        "@types/estree": "*",
+        "@types/json-schema": "*"
+      }
+    },
+    "node_modules/@types/esprima": {
+      "version": "4.0.5",
+      "resolved": "https://registry.npmjs.org/@types/esprima/-/esprima-4.0.5.tgz",
+      "integrity": "sha512-i1/wCCoHMGLSfEn68SZvao+ICYR7clqRfUAiCkxzqB7DuOMLVAgiiAcxSixtY7NukBnbQNDt5C1zmaLqCX8jDw==",
+      "dev": true,
+      "dependencies": {
+        "@types/estree": "*"
+      }
+    },
+    "node_modules/@types/estraverse": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/@types/estraverse/-/estraverse-0.0.6.tgz",
+      "integrity": "sha512-ZwPw+fR4vniKCn94+Qtn4dKeew/5tFaTrwaEViLg5Ah/pSASj/D2taHo2RSbGIPWEPuD9DqyVtLGGT2X4OR5hQ==",
+      "dev": true,
+      "dependencies": {
+        "@types/estree": "*"
+      }
+    },
+    "node_modules/@types/estree": {
+      "version": "0.0.39",
+      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
+      "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
+      "dev": true
+    },
+    "node_modules/@types/graceful-fs": {
+      "version": "4.1.8",
+      "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.8.tgz",
+      "integrity": "sha512-NhRH7YzWq8WiNKVavKPBmtLYZHxNY19Hh+az28O/phfp68CF45pMFud+ZzJ8ewnxnC5smIdF3dqFeiSUQ5I+pw==",
+      "dev": true,
+      "dependencies": {
+        "@types/node": "*"
+      }
+    },
+    "node_modules/@types/istanbul-lib-coverage": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+      "integrity": "sha512-zONci81DZYCZjiLe0r6equvZut0b+dBRPBN5kBDjsONnutYNtJMoWQ9uR2RkL1gLG9NMTzvf+29e5RFfPbeKhQ==",
+      "dev": true
+    },
+    "node_modules/@types/istanbul-lib-report": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.2.tgz",
+      "integrity": "sha512-8toY6FgdltSdONav1XtUHl4LN1yTmLza+EuDazb/fEmRNCwjyqNVIQWs2IfC74IqjHkREs/nQ2FWq5kZU9IC0w==",
+      "dev": true,
+      "dependencies": {
+        "@types/istanbul-lib-coverage": "*"
+      }
+    },
+    "node_modules/@types/istanbul-reports": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.3.tgz",
+      "integrity": "sha512-1nESsePMBlf0RPRffLZi5ujYh7IH1BWL4y9pr+Bn3cJBdxz+RTP8bUFljLz9HvzhhOSWKdyBZ4DIivdL6rvgZg==",
+      "dev": true,
+      "dependencies": {
+        "@types/istanbul-lib-report": "*"
+      }
+    },
+    "node_modules/@types/json-schema": {
+      "version": "7.0.14",
+      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz",
+      "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==",
+      "dev": true
+    },
+    "node_modules/@types/json5": {
+      "version": "0.0.29",
+      "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+      "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+      "dev": true
+    },
+    "node_modules/@types/minimist": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.4.tgz",
+      "integrity": "sha512-Kfe/D3hxHTusnPNRbycJE1N77WHDsdS4AjUYIzlDzhDrS47NrwuL3YW4VITxwR7KCVpzwgy4Rbj829KSSQmwXQ==",
+      "dev": true
+    },
+    "node_modules/@types/node": {
+      "version": "18.18.6",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.6.tgz",
+      "integrity": "sha512-wf3Vz+jCmOQ2HV1YUJuCWdL64adYxumkrxtc+H1VUQlnQI04+5HtH+qZCOE21lBE7gIrt+CwX2Wv8Acrw5Ak6w==",
+      "dev": true
+    },
+    "node_modules/@types/normalize-package-data": {
+      "version": "2.4.3",
+      "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.3.tgz",
+      "integrity": "sha512-ehPtgRgaULsFG8x0NeYJvmyH1hmlfsNLujHe9dQEia/7MAJYdzMSi19JtchUHjmBA6XC/75dK55mzZH+RyieSg==",
+      "dev": true
+    },
+    "node_modules/@types/stack-utils": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.2.tgz",
+      "integrity": "sha512-g7CK9nHdwjK2n0ymT2CW698FuWJRIx+RP6embAzZ2Qi8/ilIrA1Imt2LVSeHUzKvpoi7BhmmQcXz95eS0f2JXw==",
+      "dev": true
+    },
+    "node_modules/@types/yargs": {
+      "version": "17.0.29",
+      "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.29.tgz",
+      "integrity": "sha512-nacjqA3ee9zRF/++a3FUY1suHTFKZeHba2n8WeDw9cCVdmzmHpIxyzOJBcpHvvEmS8E9KqWlSnWHUkOrkhWcvA==",
+      "dev": true,
+      "dependencies": {
+        "@types/yargs-parser": "*"
+      }
+    },
+    "node_modules/@types/yargs-parser": {
+      "version": "21.0.2",
+      "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.2.tgz",
+      "integrity": "sha512-5qcvofLPbfjmBfKaLfj/+f+Sbd6pN4zl7w7VSVI5uz7m9QZTuB2aZAa2uo1wHFBNN2x6g/SoTkXmd8mQnQF2Cw==",
+      "dev": true
+    },
+    "node_modules/@ungap/structured-clone": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
+      "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
+      "dev": true
+    },
+    "node_modules/abab": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
+      "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==",
+      "dev": true
+    },
+    "node_modules/abort-controller": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
+      "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
+      "dev": true,
+      "dependencies": {
+        "event-target-shim": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=6.5"
+      }
+    },
+    "node_modules/acorn": {
+      "version": "8.10.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
+      "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
+      "dev": true,
+      "bin": {
+        "acorn": "bin/acorn"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/acorn-jsx": {
+      "version": "5.3.2",
+      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+      "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+      "dev": true,
+      "peerDependencies": {
+        "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+      }
+    },
+    "node_modules/acquerello": {
+      "version": "1.0.12",
+      "resolved": "https://registry.npmjs.org/acquerello/-/acquerello-1.0.12.tgz",
+      "integrity": "sha512-6yCYGUNctkYqF7DLmm0D/CxlRmM/OrzyuHOU+mbaO6VRxHmRg4EV0phvyBexRt6jTyDtEQIb09YFiwu5LExXsA==",
+      "dev": true,
+      "engines": {
+        "node": ">=14.15.0"
+      }
+    },
+    "node_modules/agent-base": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+      "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+      "dev": true,
+      "dependencies": {
+        "debug": "4"
+      },
+      "engines": {
+        "node": ">= 6.0.0"
+      }
+    },
+    "node_modules/agent-base/node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/agent-base/node_modules/ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
+    "node_modules/aggregate-error": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+      "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+      "dev": true,
+      "dependencies": {
+        "clean-stack": "^2.0.0",
+        "indent-string": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/ajv": {
+      "version": "6.12.6",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+      "dev": true,
+      "dependencies": {
+        "fast-deep-equal": "^3.1.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/ansi-align": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
+      "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==",
+      "dev": true,
+      "dependencies": {
+        "string-width": "^4.1.0"
+      }
+    },
+    "node_modules/ansi-colors": {
+      "version": "4.1.3",
+      "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
+      "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/ansi-escapes": {
+      "version": "4.3.2",
+      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+      "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+      "dev": true,
+      "dependencies": {
+        "type-fest": "^0.21.3"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/ansi-regex": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "dev": true,
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/anymatch": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+      "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+      "dev": true,
+      "dependencies": {
+        "normalize-path": "^3.0.0",
+        "picomatch": "^2.0.4"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/append-transform": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz",
+      "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==",
+      "dev": true,
+      "dependencies": {
+        "default-require-extensions": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/archy": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz",
+      "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==",
+      "dev": true
+    },
+    "node_modules/argparse": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+      "dev": true,
+      "dependencies": {
+        "sprintf-js": "~1.0.2"
+      }
+    },
+    "node_modules/args": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/args/-/args-5.0.1.tgz",
+      "integrity": "sha512-1kqmFCFsPffavQFGt8OxJdIcETti99kySRUPMpOhaGjL6mRJn8HFU1OxKY5bMqfZKUwTQc1mZkAjmGYaVOHFtQ==",
+      "dev": true,
+      "dependencies": {
+        "camelcase": "5.0.0",
+        "chalk": "2.4.2",
+        "leven": "2.1.0",
+        "mri": "1.1.4"
+      },
+      "engines": {
+        "node": ">= 6.0.0"
+      }
+    },
+    "node_modules/args/node_modules/ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "dev": true,
+      "dependencies": {
+        "color-convert": "^1.9.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/args/node_modules/camelcase": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz",
+      "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/args/node_modules/chalk": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/args/node_modules/color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "dev": true,
+      "dependencies": {
+        "color-name": "1.1.3"
+      }
+    },
+    "node_modules/args/node_modules/color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+      "dev": true
+    },
+    "node_modules/args/node_modules/escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.8.0"
+      }
+    },
+    "node_modules/args/node_modules/has-flag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/args/node_modules/leven": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz",
+      "integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/args/node_modules/supports-color": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/array-buffer-byte-length": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
+      "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "is-array-buffer": "^3.0.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/array-includes": {
+      "version": "3.1.7",
+      "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz",
+      "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1",
+        "get-intrinsic": "^1.2.1",
+        "is-string": "^1.0.7"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/array-union": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+      "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/array.prototype.findlastindex": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz",
+      "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1",
+        "es-shim-unscopables": "^1.0.0",
+        "get-intrinsic": "^1.2.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/array.prototype.flat": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz",
+      "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1",
+        "es-shim-unscopables": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/array.prototype.flatmap": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz",
+      "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1",
+        "es-shim-unscopables": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/array.prototype.tosorted": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz",
+      "integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1",
+        "es-shim-unscopables": "^1.0.0",
+        "get-intrinsic": "^1.2.1"
+      }
+    },
+    "node_modules/arraybuffer.prototype.slice": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz",
+      "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==",
+      "dev": true,
+      "dependencies": {
+        "array-buffer-byte-length": "^1.0.0",
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1",
+        "get-intrinsic": "^1.2.1",
+        "is-array-buffer": "^3.0.2",
+        "is-shared-array-buffer": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/arrify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+      "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/assertion-error": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
+      "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
+      "dev": true,
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/astral-regex": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+      "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/async-hook-domain": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/async-hook-domain/-/async-hook-domain-2.0.4.tgz",
+      "integrity": "sha512-14LjCmlK1PK8eDtTezR6WX8TMaYNIzBIsd2D1sGoGjgx0BuNMMoSdk7i/drlbtamy0AWv9yv2tkB+ASdmeqFIw==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/asynciterator.prototype": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz",
+      "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==",
+      "dev": true,
+      "dependencies": {
+        "has-symbols": "^1.0.3"
+      }
+    },
+    "node_modules/asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+      "dev": true
+    },
+    "node_modules/atomic-sleep": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz",
+      "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8.0.0"
+      }
+    },
+    "node_modules/available-typed-arrays": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
+      "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/axios": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
+      "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
+      "dev": true,
+      "dependencies": {
+        "follow-redirects": "^1.14.9",
+        "form-data": "^4.0.0"
+      }
+    },
+    "node_modules/babel-jest": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
+      "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==",
+      "dev": true,
+      "dependencies": {
+        "@jest/transform": "^29.7.0",
+        "@types/babel__core": "^7.1.14",
+        "babel-plugin-istanbul": "^6.1.1",
+        "babel-preset-jest": "^29.6.3",
+        "chalk": "^4.0.0",
+        "graceful-fs": "^4.2.9",
+        "slash": "^3.0.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.8.0"
+      }
+    },
+    "node_modules/babel-plugin-istanbul": {
+      "version": "6.1.1",
+      "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
+      "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.0.0",
+        "@istanbuljs/load-nyc-config": "^1.0.0",
+        "@istanbuljs/schema": "^0.1.2",
+        "istanbul-lib-instrument": "^5.0.4",
+        "test-exclude": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
+      "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/core": "^7.12.3",
+        "@babel/parser": "^7.14.7",
+        "@istanbuljs/schema": "^0.1.2",
+        "istanbul-lib-coverage": "^3.2.0",
+        "semver": "^6.3.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/babel-plugin-istanbul/node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/babel-plugin-jest-hoist": {
+      "version": "29.6.3",
+      "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
+      "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/template": "^7.3.3",
+        "@babel/types": "^7.3.3",
+        "@types/babel__core": "^7.1.14",
+        "@types/babel__traverse": "^7.0.6"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/babel-preset-current-node-syntax": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz",
+      "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/plugin-syntax-async-generators": "^7.8.4",
+        "@babel/plugin-syntax-bigint": "^7.8.3",
+        "@babel/plugin-syntax-class-properties": "^7.8.3",
+        "@babel/plugin-syntax-import-meta": "^7.8.3",
+        "@babel/plugin-syntax-json-strings": "^7.8.3",
+        "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3",
+        "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+        "@babel/plugin-syntax-numeric-separator": "^7.8.3",
+        "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+        "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+        "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+        "@babel/plugin-syntax-top-level-await": "^7.8.3"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/babel-preset-jest": {
+      "version": "29.6.3",
+      "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
+      "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
+      "dev": true,
+      "dependencies": {
+        "babel-plugin-jest-hoist": "^29.6.3",
+        "babel-preset-current-node-syntax": "^1.0.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+      "dev": true
+    },
+    "node_modules/base64-js": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/basic-auth-parser": {
+      "version": "0.0.2",
+      "resolved": "https://registry.npmjs.org/basic-auth-parser/-/basic-auth-parser-0.0.2.tgz",
+      "integrity": "sha512-Y7OBvWn+JnW45JWHLY6ybYub2k9cXCMrtCyO1Hds2s6eqClqWhPnOQpgXUPjAiMHj+A8TEPIQQ1dYENnJoBOHQ==",
+      "dev": true
+    },
+    "node_modules/binary-extensions": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+      "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/bind-obj-methods": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/bind-obj-methods/-/bind-obj-methods-3.0.0.tgz",
+      "integrity": "sha512-nLEaaz3/sEzNSyPWRsN9HNsqwk1AUyECtGj+XwGdIi3xABnEqecvXtIJ0wehQXuuER5uZ/5fTs2usONgYjG+iw==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/boxen": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz",
+      "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==",
+      "dev": true,
+      "dependencies": {
+        "ansi-align": "^3.0.0",
+        "camelcase": "^5.3.1",
+        "chalk": "^3.0.0",
+        "cli-boxes": "^2.2.0",
+        "string-width": "^4.1.0",
+        "term-size": "^2.1.0",
+        "type-fest": "^0.8.1",
+        "widest-line": "^3.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/boxen/node_modules/chalk": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+      "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/boxen/node_modules/supports-color": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/boxen/node_modules/type-fest": {
+      "version": "0.8.1",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+      "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/braces": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+      "dev": true,
+      "dependencies": {
+        "fill-range": "^7.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/browser-stdout": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+      "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
+      "dev": true
+    },
+    "node_modules/browserslist": {
+      "version": "4.22.1",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz",
+      "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/browserslist"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "dependencies": {
+        "caniuse-lite": "^1.0.30001541",
+        "electron-to-chromium": "^1.4.535",
+        "node-releases": "^2.0.13",
+        "update-browserslist-db": "^1.0.13"
+      },
+      "bin": {
+        "browserslist": "cli.js"
+      },
+      "engines": {
+        "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+      }
+    },
+    "node_modules/bser": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
+      "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+      "dev": true,
+      "dependencies": {
+        "node-int64": "^0.4.0"
+      }
+    },
+    "node_modules/buffer-from": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+      "dev": true
+    },
+    "node_modules/builtins": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
+      "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==",
+      "dev": true,
+      "dependencies": {
+        "semver": "^7.0.0"
+      }
+    },
+    "node_modules/cacheable-request": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz",
+      "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==",
+      "dev": true,
+      "dependencies": {
+        "clone-response": "^1.0.2",
+        "get-stream": "^5.1.0",
+        "http-cache-semantics": "^4.0.0",
+        "keyv": "^3.0.0",
+        "lowercase-keys": "^2.0.0",
+        "normalize-url": "^4.1.0",
+        "responselike": "^1.0.2"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/cacheable-request/node_modules/get-stream": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+      "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+      "dev": true,
+      "dependencies": {
+        "pump": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/cacheable-request/node_modules/json-buffer": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
+      "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==",
+      "dev": true
+    },
+    "node_modules/cacheable-request/node_modules/keyv": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz",
+      "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==",
+      "dev": true,
+      "dependencies": {
+        "json-buffer": "3.0.0"
+      }
+    },
+    "node_modules/cacheable-request/node_modules/lowercase-keys": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
+      "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/caching-transform": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz",
+      "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==",
+      "dev": true,
+      "dependencies": {
+        "hasha": "^3.0.0",
+        "make-dir": "^2.0.0",
+        "package-hash": "^3.0.0",
+        "write-file-atomic": "^2.4.2"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/caching-transform/node_modules/make-dir": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+      "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+      "dev": true,
+      "dependencies": {
+        "pify": "^4.0.1",
+        "semver": "^5.6.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/caching-transform/node_modules/semver": {
+      "version": "5.7.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+      "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver"
+      }
+    },
+    "node_modules/caching-transform/node_modules/write-file-atomic": {
+      "version": "2.4.3",
+      "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz",
+      "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==",
+      "dev": true,
+      "dependencies": {
+        "graceful-fs": "^4.1.11",
+        "imurmurhash": "^0.1.4",
+        "signal-exit": "^3.0.2"
+      }
+    },
+    "node_modules/call-bind": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz",
+      "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==",
+      "dev": true,
+      "dependencies": {
+        "function-bind": "^1.1.2",
+        "get-intrinsic": "^1.2.1",
+        "set-function-length": "^1.1.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/callsites": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+      "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/camelcase": {
+      "version": "5.3.1",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+      "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/camelcase-keys": {
+      "version": "6.2.2",
+      "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz",
+      "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==",
+      "dev": true,
+      "dependencies": {
+        "camelcase": "^5.3.1",
+        "map-obj": "^4.0.0",
+        "quick-lru": "^4.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/caniuse-lite": {
+      "version": "1.0.30001551",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001551.tgz",
+      "integrity": "sha512-vtBAez47BoGMMzlbYhfXrMV1kvRF2WP/lqiMuDu1Sb4EE4LKEgjopFDSRtZfdVnslNRpOqV/woE+Xgrwj6VQlg==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ]
+    },
+    "node_modules/chai": {
+      "version": "4.3.10",
+      "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz",
+      "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==",
+      "dev": true,
+      "dependencies": {
+        "assertion-error": "^1.1.0",
+        "check-error": "^1.0.3",
+        "deep-eql": "^4.1.3",
+        "get-func-name": "^2.0.2",
+        "loupe": "^2.3.6",
+        "pathval": "^1.1.1",
+        "type-detect": "^4.0.8"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/chai-as-promised": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz",
+      "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==",
+      "dev": true,
+      "dependencies": {
+        "check-error": "^1.0.2"
+      },
+      "peerDependencies": {
+        "chai": ">= 2.1.2 < 5"
+      }
+    },
+    "node_modules/chai-iterator": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/chai-iterator/-/chai-iterator-3.0.2.tgz",
+      "integrity": "sha512-7ZKEmBJRNSYUBMK0QC1sTzyhHHS67d1R3W3uu9MdehvPPzOEOrtmI6lmTO3CxiuMbeEEDozF1pnlEMraxKXLcg==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependencies": {
+        "chai": "4.x"
+      }
+    },
+    "node_modules/chai-string": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/chai-string/-/chai-string-1.5.0.tgz",
+      "integrity": "sha512-sydDC3S3pNAQMYwJrs6dQX0oBQ6KfIPuOZ78n7rocW0eJJlsHPh2t3kwW7xfwYA/1Bf6/arGtSUo16rxR2JFlw==",
+      "dev": true,
+      "peerDependencies": {
+        "chai": "^4.1.2"
+      }
+    },
+    "node_modules/chalk": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
+      }
+    },
+    "node_modules/chalk/node_modules/supports-color": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/char-regex": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
+      "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/check-error": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz",
+      "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==",
+      "dev": true,
+      "dependencies": {
+        "get-func-name": "^2.0.2"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/chokidar": {
+      "version": "3.5.3",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+      "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "individual",
+          "url": "https://paulmillr.com/funding/"
+        }
+      ],
+      "dependencies": {
+        "anymatch": "~3.1.2",
+        "braces": "~3.0.2",
+        "glob-parent": "~5.1.2",
+        "is-binary-path": "~2.1.0",
+        "is-glob": "~4.0.1",
+        "normalize-path": "~3.0.0",
+        "readdirp": "~3.6.0"
+      },
+      "engines": {
+        "node": ">= 8.10.0"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.2"
+      }
+    },
+    "node_modules/ci-info": {
+      "version": "3.9.0",
+      "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+      "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/sibiraj-s"
+        }
+      ],
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/cjs-module-lexer": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz",
+      "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==",
+      "dev": true
+    },
+    "node_modules/clean-stack": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+      "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/cli-boxes": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz",
+      "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/cliui": {
+      "version": "7.0.4",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+      "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
+      "dev": true,
+      "dependencies": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.0",
+        "wrap-ansi": "^7.0.0"
+      }
+    },
+    "node_modules/clone-response": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz",
+      "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==",
+      "dev": true,
+      "dependencies": {
+        "mimic-response": "^1.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/co": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+      "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
+      "dev": true,
+      "engines": {
+        "iojs": ">= 1.0.0",
+        "node": ">= 0.12.0"
+      }
+    },
+    "node_modules/collect-v8-coverage": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz",
+      "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==",
+      "dev": true
+    },
+    "node_modules/color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "dev": true,
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+      "dev": true
+    },
+    "node_modules/color-support": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
+      "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
+      "dev": true,
+      "bin": {
+        "color-support": "bin.js"
+      }
+    },
+    "node_modules/combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "dev": true,
+      "dependencies": {
+        "delayed-stream": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/commondir": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+      "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
+      "dev": true
+    },
+    "node_modules/concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+      "dev": true
+    },
+    "node_modules/concat-stream": {
+      "version": "1.6.2",
+      "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+      "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+      "dev": true,
+      "engines": [
+        "node >= 0.8"
+      ],
+      "dependencies": {
+        "buffer-from": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^2.2.2",
+        "typedarray": "^0.0.6"
+      }
+    },
+    "node_modules/concat-stream/node_modules/isarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+      "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+      "dev": true
+    },
+    "node_modules/concat-stream/node_modules/readable-stream": {
+      "version": "2.3.8",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+      "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+      "dev": true,
+      "dependencies": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.3",
+        "isarray": "~1.0.0",
+        "process-nextick-args": "~2.0.0",
+        "safe-buffer": "~5.1.1",
+        "string_decoder": "~1.1.1",
+        "util-deprecate": "~1.0.1"
+      }
+    },
+    "node_modules/concat-stream/node_modules/safe-buffer": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+      "dev": true
+    },
+    "node_modules/concat-stream/node_modules/string_decoder": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+      "dev": true,
+      "dependencies": {
+        "safe-buffer": "~5.1.0"
+      }
+    },
+    "node_modules/concurrently": {
+      "version": "8.2.2",
+      "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz",
+      "integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==",
+      "dev": true,
+      "dependencies": {
+        "chalk": "^4.1.2",
+        "date-fns": "^2.30.0",
+        "lodash": "^4.17.21",
+        "rxjs": "^7.8.1",
+        "shell-quote": "^1.8.1",
+        "spawn-command": "0.0.2",
+        "supports-color": "^8.1.1",
+        "tree-kill": "^1.2.2",
+        "yargs": "^17.7.2"
+      },
+      "bin": {
+        "conc": "dist/bin/concurrently.js",
+        "concurrently": "dist/bin/concurrently.js"
+      },
+      "engines": {
+        "node": "^14.13.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/open-cli-tools/concurrently?sponsor=1"
+      }
+    },
+    "node_modules/configstore": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz",
+      "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==",
+      "dev": true,
+      "dependencies": {
+        "dot-prop": "^5.2.0",
+        "graceful-fs": "^4.1.2",
+        "make-dir": "^3.0.0",
+        "unique-string": "^2.0.0",
+        "write-file-atomic": "^3.0.0",
+        "xdg-basedir": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/configstore/node_modules/write-file-atomic": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
+      "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
+      "dev": true,
+      "dependencies": {
+        "imurmurhash": "^0.1.4",
+        "is-typedarray": "^1.0.0",
+        "signal-exit": "^3.0.2",
+        "typedarray-to-buffer": "^3.1.5"
+      }
+    },
+    "node_modules/connect": {
+      "version": "3.7.0",
+      "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz",
+      "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==",
+      "dev": true,
+      "dependencies": {
+        "debug": "2.6.9",
+        "finalhandler": "1.1.2",
+        "parseurl": "~1.3.3",
+        "utils-merge": "1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.10.0"
+      }
+    },
+    "node_modules/connect-history-api-fallback": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
+      "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/connect-livereload": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.6.1.tgz",
+      "integrity": "sha512-3R0kMOdL7CjJpU66fzAkCe6HNtd3AavCS4m+uW4KtJjrdGPT0SQEZieAYd+cm+lJoBznNQ4lqipYWkhBMgk00g==",
+      "dev": true,
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/convert-source-map": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+      "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+      "dev": true
+    },
+    "node_modules/core-util-is": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+      "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+      "dev": true
+    },
+    "node_modules/cp-file": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-7.0.0.tgz",
+      "integrity": "sha512-0Cbj7gyvFVApzpK/uhCtQ/9kE9UnYpxMzaq5nQQC/Dh4iaj5fxp7iEFIullrYwzj8nf0qnsI1Qsx34hAeAebvw==",
+      "dev": true,
+      "dependencies": {
+        "graceful-fs": "^4.1.2",
+        "make-dir": "^3.0.0",
+        "nested-error-stacks": "^2.0.0",
+        "p-event": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/create-jest": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz",
+      "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==",
+      "dev": true,
+      "dependencies": {
+        "@jest/types": "^29.6.3",
+        "chalk": "^4.0.0",
+        "exit": "^0.1.2",
+        "graceful-fs": "^4.2.9",
+        "jest-config": "^29.7.0",
+        "jest-util": "^29.7.0",
+        "prompts": "^2.0.1"
+      },
+      "bin": {
+        "create-jest": "bin/create-jest.js"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/cronometro": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/cronometro/-/cronometro-1.1.5.tgz",
+      "integrity": "sha512-uotkltVBg4WLAeCgbSsLhqpEyvYTn1J++bYcsq0i/RPNMHkMp4sN/7Hx+0O3UaCqIWJ4AG1dNrzDSkzt69jwQQ==",
+      "dev": true,
+      "dependencies": {
+        "acquerello": "^1.0.12",
+        "hdr-histogram-js": "^3.0.0",
+        "table": "^6.8.1"
+      },
+      "engines": {
+        "node": ">=14.15.0"
+      }
+    },
+    "node_modules/cross-spawn": {
+      "version": "7.0.3",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+      "dev": true,
+      "dependencies": {
+        "path-key": "^3.1.0",
+        "shebang-command": "^2.0.0",
+        "which": "^2.0.1"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/crypto-random-string": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
+      "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/cssstyle": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-3.0.0.tgz",
+      "integrity": "sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==",
+      "dev": true,
+      "dependencies": {
+        "rrweb-cssom": "^0.6.0"
+      },
+      "engines": {
+        "node": ">=14"
+      }
+    },
+    "node_modules/data-urls": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-4.0.0.tgz",
+      "integrity": "sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==",
+      "dev": true,
+      "dependencies": {
+        "abab": "^2.0.6",
+        "whatwg-mimetype": "^3.0.0",
+        "whatwg-url": "^12.0.0"
+      },
+      "engines": {
+        "node": ">=14"
+      }
+    },
+    "node_modules/date-fns": {
+      "version": "2.30.0",
+      "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
+      "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/runtime": "^7.21.0"
+      },
+      "engines": {
+        "node": ">=0.11"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/date-fns"
+      }
+    },
+    "node_modules/debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "dev": true,
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/decamelize": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+      "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/decamelize-keys": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz",
+      "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==",
+      "dev": true,
+      "dependencies": {
+        "decamelize": "^1.1.0",
+        "map-obj": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/decamelize-keys/node_modules/map-obj": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+      "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/decimal.js": {
+      "version": "10.4.3",
+      "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
+      "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==",
+      "dev": true
+    },
+    "node_modules/decompress-response": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
+      "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==",
+      "dev": true,
+      "dependencies": {
+        "mimic-response": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/dedent": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz",
+      "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==",
+      "dev": true,
+      "peerDependencies": {
+        "babel-plugin-macros": "^3.1.0"
+      },
+      "peerDependenciesMeta": {
+        "babel-plugin-macros": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/deep-eql": {
+      "version": "4.1.3",
+      "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz",
+      "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==",
+      "dev": true,
+      "dependencies": {
+        "type-detect": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/deep-equal": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
+      "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==",
+      "dev": true,
+      "dependencies": {
+        "is-arguments": "^1.0.4",
+        "is-date-object": "^1.0.1",
+        "is-regex": "^1.0.4",
+        "object-is": "^1.0.1",
+        "object-keys": "^1.1.1",
+        "regexp.prototype.flags": "^1.2.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/deep-extend": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+      "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4.0.0"
+      }
+    },
+    "node_modules/deep-is": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+      "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+      "dev": true
+    },
+    "node_modules/deepmerge": {
+      "version": "4.3.1",
+      "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+      "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/default-require-extensions": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz",
+      "integrity": "sha512-B0n2zDIXpzLzKeoEozorDSa1cHc1t0NjmxP0zuAxbizNU2MBqYJJKYXrrFdKuQliojXynrxgd7l4ahfg/+aA5g==",
+      "dev": true,
+      "dependencies": {
+        "strip-bom": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/default-require-extensions/node_modules/strip-bom": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+      "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/defer-to-connect": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz",
+      "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==",
+      "dev": true
+    },
+    "node_modules/define-data-property": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz",
+      "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==",
+      "dev": true,
+      "dependencies": {
+        "get-intrinsic": "^1.2.1",
+        "gopd": "^1.0.1",
+        "has-property-descriptors": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/define-properties": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+      "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+      "dev": true,
+      "dependencies": {
+        "define-data-property": "^1.0.1",
+        "has-property-descriptors": "^1.0.0",
+        "object-keys": "^1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/delay": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz",
+      "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/depd": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+      "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/destroy": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+      "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.8",
+        "npm": "1.2.8000 || >= 1.4.16"
+      }
+    },
+    "node_modules/detect-newline": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
+      "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/diff": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
+      "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.3.1"
+      }
+    },
+    "node_modules/diff-sequences": {
+      "version": "29.6.3",
+      "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
+      "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
+      "dev": true,
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/dir-glob": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+      "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+      "dev": true,
+      "dependencies": {
+        "path-type": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/dns-packet": {
+      "version": "5.6.1",
+      "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz",
+      "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==",
+      "dev": true,
+      "dependencies": {
+        "@leichtgewicht/ip-codec": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/docsify": {
+      "version": "4.13.1",
+      "resolved": "https://registry.npmjs.org/docsify/-/docsify-4.13.1.tgz",
+      "integrity": "sha512-BsDypTBhw0mfslw9kZgAspCMZSM+sUIIDg5K/t1hNLkvbem9h64ZQc71e1IpY+iWsi/KdeqfazDfg52y2Lmm0A==",
+      "dev": true,
+      "hasInstallScript": true,
+      "dependencies": {
+        "marked": "^1.2.9",
+        "medium-zoom": "^1.0.6",
+        "opencollective-postinstall": "^2.0.2",
+        "prismjs": "^1.27.0",
+        "strip-indent": "^3.0.0",
+        "tinydate": "^1.3.0",
+        "tweezer.js": "^1.4.0"
+      }
+    },
+    "node_modules/docsify-cli": {
+      "version": "4.4.4",
+      "resolved": "https://registry.npmjs.org/docsify-cli/-/docsify-cli-4.4.4.tgz",
+      "integrity": "sha512-NAZgg6b0BsDuq/Pe+P19Qb2J1d+ZVbS0eGkeCNxyu4F9/CQSsRqZqAvPJ9/0I+BCHn4sgftA2jluqhQVzKzrSA==",
+      "dev": true,
+      "dependencies": {
+        "chalk": "^2.4.2",
+        "connect": "^3.6.0",
+        "connect-history-api-fallback": "^1.6.0",
+        "connect-livereload": "^0.6.0",
+        "cp-file": "^7.0.0",
+        "docsify": "^4.12.2",
+        "docsify-server-renderer": ">=4.10.0",
+        "enquirer": "^2.3.6",
+        "fs-extra": "^8.1.0",
+        "get-port": "^5.0.0",
+        "livereload": "^0.9.2",
+        "lru-cache": "^5.1.1",
+        "open": "^6.4.0",
+        "serve-static": "^1.12.1",
+        "update-notifier": "^4.1.0",
+        "yargonaut": "^1.1.2",
+        "yargs": "^15.3.0"
+      },
+      "bin": {
+        "docsify": "bin/docsify"
+      },
+      "engines": {
+        "node": ">= 10",
+        "npm": ">= 6"
+      }
+    },
+    "node_modules/docsify-cli/node_modules/ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "dev": true,
+      "dependencies": {
+        "color-convert": "^1.9.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/docsify-cli/node_modules/chalk": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/docsify-cli/node_modules/cliui": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+      "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+      "dev": true,
+      "dependencies": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.0",
+        "wrap-ansi": "^6.2.0"
+      }
+    },
+    "node_modules/docsify-cli/node_modules/color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "dev": true,
+      "dependencies": {
+        "color-name": "1.1.3"
+      }
+    },
+    "node_modules/docsify-cli/node_modules/color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+      "dev": true
+    },
+    "node_modules/docsify-cli/node_modules/escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.8.0"
+      }
+    },
+    "node_modules/docsify-cli/node_modules/has-flag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/docsify-cli/node_modules/supports-color": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/docsify-cli/node_modules/wrap-ansi": {
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+      "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^4.0.0",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/docsify-cli/node_modules/wrap-ansi/node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "dev": true,
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/docsify-cli/node_modules/wrap-ansi/node_modules/color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "dev": true,
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/docsify-cli/node_modules/wrap-ansi/node_modules/color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+      "dev": true
+    },
+    "node_modules/docsify-cli/node_modules/y18n": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+      "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
+      "dev": true
+    },
+    "node_modules/docsify-cli/node_modules/yargs": {
+      "version": "15.4.1",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+      "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+      "dev": true,
+      "dependencies": {
+        "cliui": "^6.0.0",
+        "decamelize": "^1.2.0",
+        "find-up": "^4.1.0",
+        "get-caller-file": "^2.0.1",
+        "require-directory": "^2.1.1",
+        "require-main-filename": "^2.0.0",
+        "set-blocking": "^2.0.0",
+        "string-width": "^4.2.0",
+        "which-module": "^2.0.0",
+        "y18n": "^4.0.0",
+        "yargs-parser": "^18.1.2"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/docsify-cli/node_modules/yargs-parser": {
+      "version": "18.1.3",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+      "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+      "dev": true,
+      "dependencies": {
+        "camelcase": "^5.0.0",
+        "decamelize": "^1.2.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/docsify-server-renderer": {
+      "version": "4.13.1",
+      "resolved": "https://registry.npmjs.org/docsify-server-renderer/-/docsify-server-renderer-4.13.1.tgz",
+      "integrity": "sha512-XNJeCK3zp+mVO7JZFn0bH4hNBAMMC1MbuCU7CBsjLHYn4NHrjIgCBGmylzEan3/4Qm6kbSzQx8XzUK5T7GQxHw==",
+      "dev": true,
+      "dependencies": {
+        "debug": "^4.3.3",
+        "docsify": "^4.12.4",
+        "node-fetch": "^2.6.6",
+        "resolve-pathname": "^3.0.0"
+      }
+    },
+    "node_modules/docsify-server-renderer/node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/docsify-server-renderer/node_modules/ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
+    "node_modules/doctrine": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+      "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+      "dev": true,
+      "dependencies": {
+        "esutils": "^2.0.2"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/domexception": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz",
+      "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==",
+      "dev": true,
+      "dependencies": {
+        "webidl-conversions": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/dot-prop": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
+      "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
+      "dev": true,
+      "dependencies": {
+        "is-obj": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/duplexer3": {
+      "version": "0.1.5",
+      "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz",
+      "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==",
+      "dev": true
+    },
+    "node_modules/ee-first": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+      "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+      "dev": true
+    },
+    "node_modules/electron-to-chromium": {
+      "version": "1.4.563",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.563.tgz",
+      "integrity": "sha512-dg5gj5qOgfZNkPNeyKBZQAQitIQ/xwfIDmEQJHCbXaD9ebTZxwJXUsDYcBlAvZGZLi+/354l35J1wkmP6CqYaw==",
+      "dev": true
+    },
+    "node_modules/emittery": {
+      "version": "0.13.1",
+      "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
+      "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sindresorhus/emittery?sponsor=1"
+      }
+    },
+    "node_modules/emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+      "dev": true
+    },
+    "node_modules/encodeurl": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+      "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/end-of-stream": {
+      "version": "1.4.4",
+      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+      "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+      "dev": true,
+      "dependencies": {
+        "once": "^1.4.0"
+      }
+    },
+    "node_modules/enquirer": {
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz",
+      "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==",
+      "dev": true,
+      "dependencies": {
+        "ansi-colors": "^4.1.1",
+        "strip-ansi": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=8.6"
+      }
+    },
+    "node_modules/entities": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+      "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/error-ex": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+      "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+      "dev": true,
+      "dependencies": {
+        "is-arrayish": "^0.2.1"
+      }
+    },
+    "node_modules/es-abstract": {
+      "version": "1.22.3",
+      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz",
+      "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==",
+      "dev": true,
+      "dependencies": {
+        "array-buffer-byte-length": "^1.0.0",
+        "arraybuffer.prototype.slice": "^1.0.2",
+        "available-typed-arrays": "^1.0.5",
+        "call-bind": "^1.0.5",
+        "es-set-tostringtag": "^2.0.1",
+        "es-to-primitive": "^1.2.1",
+        "function.prototype.name": "^1.1.6",
+        "get-intrinsic": "^1.2.2",
+        "get-symbol-description": "^1.0.0",
+        "globalthis": "^1.0.3",
+        "gopd": "^1.0.1",
+        "has-property-descriptors": "^1.0.0",
+        "has-proto": "^1.0.1",
+        "has-symbols": "^1.0.3",
+        "hasown": "^2.0.0",
+        "internal-slot": "^1.0.5",
+        "is-array-buffer": "^3.0.2",
+        "is-callable": "^1.2.7",
+        "is-negative-zero": "^2.0.2",
+        "is-regex": "^1.1.4",
+        "is-shared-array-buffer": "^1.0.2",
+        "is-string": "^1.0.7",
+        "is-typed-array": "^1.1.12",
+        "is-weakref": "^1.0.2",
+        "object-inspect": "^1.13.1",
+        "object-keys": "^1.1.1",
+        "object.assign": "^4.1.4",
+        "regexp.prototype.flags": "^1.5.1",
+        "safe-array-concat": "^1.0.1",
+        "safe-regex-test": "^1.0.0",
+        "string.prototype.trim": "^1.2.8",
+        "string.prototype.trimend": "^1.0.7",
+        "string.prototype.trimstart": "^1.0.7",
+        "typed-array-buffer": "^1.0.0",
+        "typed-array-byte-length": "^1.0.0",
+        "typed-array-byte-offset": "^1.0.0",
+        "typed-array-length": "^1.0.4",
+        "unbox-primitive": "^1.0.2",
+        "which-typed-array": "^1.1.13"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/es-iterator-helpers": {
+      "version": "1.0.15",
+      "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz",
+      "integrity": "sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==",
+      "dev": true,
+      "dependencies": {
+        "asynciterator.prototype": "^1.0.0",
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.1",
+        "es-abstract": "^1.22.1",
+        "es-set-tostringtag": "^2.0.1",
+        "function-bind": "^1.1.1",
+        "get-intrinsic": "^1.2.1",
+        "globalthis": "^1.0.3",
+        "has-property-descriptors": "^1.0.0",
+        "has-proto": "^1.0.1",
+        "has-symbols": "^1.0.3",
+        "internal-slot": "^1.0.5",
+        "iterator.prototype": "^1.1.2",
+        "safe-array-concat": "^1.0.1"
+      }
+    },
+    "node_modules/es-set-tostringtag": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz",
+      "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==",
+      "dev": true,
+      "dependencies": {
+        "get-intrinsic": "^1.2.2",
+        "has-tostringtag": "^1.0.0",
+        "hasown": "^2.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-shim-unscopables": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz",
+      "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==",
+      "dev": true,
+      "dependencies": {
+        "hasown": "^2.0.0"
+      }
+    },
+    "node_modules/es-to-primitive": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+      "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+      "dev": true,
+      "dependencies": {
+        "is-callable": "^1.1.4",
+        "is-date-object": "^1.0.1",
+        "is-symbol": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/es6-error": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
+      "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
+      "dev": true
+    },
+    "node_modules/escalade": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+      "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/escape-goat": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz",
+      "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/escape-html": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+      "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+      "dev": true
+    },
+    "node_modules/escape-string-regexp": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/escodegen": {
+      "version": "1.14.3",
+      "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz",
+      "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==",
+      "dev": true,
+      "dependencies": {
+        "esprima": "^4.0.1",
+        "estraverse": "^4.2.0",
+        "esutils": "^2.0.2",
+        "optionator": "^0.8.1"
+      },
+      "bin": {
+        "escodegen": "bin/escodegen.js",
+        "esgenerate": "bin/esgenerate.js"
+      },
+      "engines": {
+        "node": ">=4.0"
+      },
+      "optionalDependencies": {
+        "source-map": "~0.6.1"
+      }
+    },
+    "node_modules/eslint": {
+      "version": "8.52.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz",
+      "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==",
+      "dev": true,
+      "dependencies": {
+        "@eslint-community/eslint-utils": "^4.2.0",
+        "@eslint-community/regexpp": "^4.6.1",
+        "@eslint/eslintrc": "^2.1.2",
+        "@eslint/js": "8.52.0",
+        "@humanwhocodes/config-array": "^0.11.13",
+        "@humanwhocodes/module-importer": "^1.0.1",
+        "@nodelib/fs.walk": "^1.2.8",
+        "@ungap/structured-clone": "^1.2.0",
+        "ajv": "^6.12.4",
+        "chalk": "^4.0.0",
+        "cross-spawn": "^7.0.2",
+        "debug": "^4.3.2",
+        "doctrine": "^3.0.0",
+        "escape-string-regexp": "^4.0.0",
+        "eslint-scope": "^7.2.2",
+        "eslint-visitor-keys": "^3.4.3",
+        "espree": "^9.6.1",
+        "esquery": "^1.4.2",
+        "esutils": "^2.0.2",
+        "fast-deep-equal": "^3.1.3",
+        "file-entry-cache": "^6.0.1",
+        "find-up": "^5.0.0",
+        "glob-parent": "^6.0.2",
+        "globals": "^13.19.0",
+        "graphemer": "^1.4.0",
+        "ignore": "^5.2.0",
+        "imurmurhash": "^0.1.4",
+        "is-glob": "^4.0.0",
+        "is-path-inside": "^3.0.3",
+        "js-yaml": "^4.1.0",
+        "json-stable-stringify-without-jsonify": "^1.0.1",
+        "levn": "^0.4.1",
+        "lodash.merge": "^4.6.2",
+        "minimatch": "^3.1.2",
+        "natural-compare": "^1.4.0",
+        "optionator": "^0.9.3",
+        "strip-ansi": "^6.0.1",
+        "text-table": "^0.2.0"
+      },
+      "bin": {
+        "eslint": "bin/eslint.js"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/eslint-config-standard": {
+      "version": "17.1.0",
+      "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz",
+      "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "engines": {
+        "node": ">=12.0.0"
+      },
+      "peerDependencies": {
+        "eslint": "^8.0.1",
+        "eslint-plugin-import": "^2.25.2",
+        "eslint-plugin-n": "^15.0.0 || ^16.0.0 ",
+        "eslint-plugin-promise": "^6.0.0"
+      }
+    },
+    "node_modules/eslint-config-standard-jsx": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-11.0.0.tgz",
+      "integrity": "sha512-+1EV/R0JxEK1L0NGolAr8Iktm3Rgotx3BKwgaX+eAuSX8D952LULKtjgZD3F+e6SvibONnhLwoTi9DPxN5LvvQ==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "peerDependencies": {
+        "eslint": "^8.8.0",
+        "eslint-plugin-react": "^7.28.0"
+      }
+    },
+    "node_modules/eslint-formatter-pretty": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/eslint-formatter-pretty/-/eslint-formatter-pretty-4.1.0.tgz",
+      "integrity": "sha512-IsUTtGxF1hrH6lMWiSl1WbGaiP01eT6kzywdY1U+zLc0MP+nwEnUiS9UI8IaOTUhTeQJLlCEWIbXINBH4YJbBQ==",
+      "dev": true,
+      "dependencies": {
+        "@types/eslint": "^7.2.13",
+        "ansi-escapes": "^4.2.1",
+        "chalk": "^4.1.0",
+        "eslint-rule-docs": "^1.1.5",
+        "log-symbols": "^4.0.0",
+        "plur": "^4.0.0",
+        "string-width": "^4.2.0",
+        "supports-hyperlinks": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/eslint-import-resolver-node": {
+      "version": "0.3.9",
+      "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
+      "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==",
+      "dev": true,
+      "dependencies": {
+        "debug": "^3.2.7",
+        "is-core-module": "^2.13.0",
+        "resolve": "^1.22.4"
+      }
+    },
+    "node_modules/eslint-import-resolver-node/node_modules/debug": {
+      "version": "3.2.7",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+      "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "^2.1.1"
+      }
+    },
+    "node_modules/eslint-import-resolver-node/node_modules/ms": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+      "dev": true
+    },
+    "node_modules/eslint-module-utils": {
+      "version": "2.8.0",
+      "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz",
+      "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==",
+      "dev": true,
+      "dependencies": {
+        "debug": "^3.2.7"
+      },
+      "engines": {
+        "node": ">=4"
+      },
+      "peerDependenciesMeta": {
+        "eslint": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/eslint-module-utils/node_modules/debug": {
+      "version": "3.2.7",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+      "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "^2.1.1"
+      }
+    },
+    "node_modules/eslint-module-utils/node_modules/ms": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+      "dev": true
+    },
+    "node_modules/eslint-plugin-es": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz",
+      "integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==",
+      "dev": true,
+      "dependencies": {
+        "eslint-utils": "^2.0.0",
+        "regexpp": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8.10.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/mysticatea"
+      },
+      "peerDependencies": {
+        "eslint": ">=4.19.1"
+      }
+    },
+    "node_modules/eslint-plugin-es/node_modules/eslint-utils": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
+      "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
+      "dev": true,
+      "dependencies": {
+        "eslint-visitor-keys": "^1.1.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/mysticatea"
+      }
+    },
+    "node_modules/eslint-plugin-es/node_modules/eslint-visitor-keys": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+      "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/eslint-plugin-import": {
+      "version": "2.28.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz",
+      "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==",
+      "dev": true,
+      "dependencies": {
+        "array-includes": "^3.1.6",
+        "array.prototype.findlastindex": "^1.2.2",
+        "array.prototype.flat": "^1.3.1",
+        "array.prototype.flatmap": "^1.3.1",
+        "debug": "^3.2.7",
+        "doctrine": "^2.1.0",
+        "eslint-import-resolver-node": "^0.3.7",
+        "eslint-module-utils": "^2.8.0",
+        "has": "^1.0.3",
+        "is-core-module": "^2.13.0",
+        "is-glob": "^4.0.3",
+        "minimatch": "^3.1.2",
+        "object.fromentries": "^2.0.6",
+        "object.groupby": "^1.0.0",
+        "object.values": "^1.1.6",
+        "semver": "^6.3.1",
+        "tsconfig-paths": "^3.14.2"
+      },
+      "engines": {
+        "node": ">=4"
+      },
+      "peerDependencies": {
+        "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
+      }
+    },
+    "node_modules/eslint-plugin-import/node_modules/debug": {
+      "version": "3.2.7",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+      "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "^2.1.1"
+      }
+    },
+    "node_modules/eslint-plugin-import/node_modules/doctrine": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+      "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+      "dev": true,
+      "dependencies": {
+        "esutils": "^2.0.2"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/eslint-plugin-import/node_modules/ms": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+      "dev": true
+    },
+    "node_modules/eslint-plugin-import/node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/eslint-plugin-n": {
+      "version": "15.7.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz",
+      "integrity": "sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==",
+      "dev": true,
+      "dependencies": {
+        "builtins": "^5.0.1",
+        "eslint-plugin-es": "^4.1.0",
+        "eslint-utils": "^3.0.0",
+        "ignore": "^5.1.1",
+        "is-core-module": "^2.11.0",
+        "minimatch": "^3.1.2",
+        "resolve": "^1.22.1",
+        "semver": "^7.3.8"
+      },
+      "engines": {
+        "node": ">=12.22.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/mysticatea"
+      },
+      "peerDependencies": {
+        "eslint": ">=7.0.0"
+      }
+    },
+    "node_modules/eslint-plugin-promise": {
+      "version": "6.1.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz",
+      "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==",
+      "dev": true,
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "peerDependencies": {
+        "eslint": "^7.0.0 || ^8.0.0"
+      }
+    },
+    "node_modules/eslint-plugin-react": {
+      "version": "7.33.2",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz",
+      "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==",
+      "dev": true,
+      "dependencies": {
+        "array-includes": "^3.1.6",
+        "array.prototype.flatmap": "^1.3.1",
+        "array.prototype.tosorted": "^1.1.1",
+        "doctrine": "^2.1.0",
+        "es-iterator-helpers": "^1.0.12",
+        "estraverse": "^5.3.0",
+        "jsx-ast-utils": "^2.4.1 || ^3.0.0",
+        "minimatch": "^3.1.2",
+        "object.entries": "^1.1.6",
+        "object.fromentries": "^2.0.6",
+        "object.hasown": "^1.1.2",
+        "object.values": "^1.1.6",
+        "prop-types": "^15.8.1",
+        "resolve": "^2.0.0-next.4",
+        "semver": "^6.3.1",
+        "string.prototype.matchall": "^4.0.8"
+      },
+      "engines": {
+        "node": ">=4"
+      },
+      "peerDependencies": {
+        "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
+      }
+    },
+    "node_modules/eslint-plugin-react/node_modules/doctrine": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+      "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+      "dev": true,
+      "dependencies": {
+        "esutils": "^2.0.2"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/eslint-plugin-react/node_modules/estraverse": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+      "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/eslint-plugin-react/node_modules/resolve": {
+      "version": "2.0.0-next.5",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
+      "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==",
+      "dev": true,
+      "dependencies": {
+        "is-core-module": "^2.13.0",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
+      },
+      "bin": {
+        "resolve": "bin/resolve"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/eslint-plugin-react/node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/eslint-rule-docs": {
+      "version": "1.1.235",
+      "resolved": "https://registry.npmjs.org/eslint-rule-docs/-/eslint-rule-docs-1.1.235.tgz",
+      "integrity": "sha512-+TQ+x4JdTnDoFEXXb3fDvfGOwnyNV7duH8fXWTPD1ieaBmB8omj7Gw/pMBBu4uI2uJCCU8APDaQJzWuXnTsH4A==",
+      "dev": true
+    },
+    "node_modules/eslint-scope": {
+      "version": "7.2.2",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+      "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+      "dev": true,
+      "dependencies": {
+        "esrecurse": "^4.3.0",
+        "estraverse": "^5.2.0"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/eslint-scope/node_modules/estraverse": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+      "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/eslint-utils": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
+      "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
+      "dev": true,
+      "dependencies": {
+        "eslint-visitor-keys": "^2.0.0"
+      },
+      "engines": {
+        "node": "^10.0.0 || ^12.0.0 || >= 14.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/mysticatea"
+      },
+      "peerDependencies": {
+        "eslint": ">=5"
+      }
+    },
+    "node_modules/eslint-utils/node_modules/eslint-visitor-keys": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+      "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/eslint-visitor-keys": {
+      "version": "3.4.3",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+      "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+      "dev": true,
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/eslint/node_modules/argparse": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+      "dev": true
+    },
+    "node_modules/eslint/node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/eslint/node_modules/find-up": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+      "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+      "dev": true,
+      "dependencies": {
+        "locate-path": "^6.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/eslint/node_modules/glob-parent": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+      "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+      "dev": true,
+      "dependencies": {
+        "is-glob": "^4.0.3"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/eslint/node_modules/globals": {
+      "version": "13.23.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz",
+      "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==",
+      "dev": true,
+      "dependencies": {
+        "type-fest": "^0.20.2"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/eslint/node_modules/js-yaml": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+      "dev": true,
+      "dependencies": {
+        "argparse": "^2.0.1"
+      },
+      "bin": {
+        "js-yaml": "bin/js-yaml.js"
+      }
+    },
+    "node_modules/eslint/node_modules/levn": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+      "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+      "dev": true,
+      "dependencies": {
+        "prelude-ls": "^1.2.1",
+        "type-check": "~0.4.0"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/eslint/node_modules/locate-path": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+      "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+      "dev": true,
+      "dependencies": {
+        "p-locate": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/eslint/node_modules/ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
+    "node_modules/eslint/node_modules/optionator": {
+      "version": "0.9.3",
+      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
+      "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
+      "dev": true,
+      "dependencies": {
+        "@aashutoshrathi/word-wrap": "^1.2.3",
+        "deep-is": "^0.1.3",
+        "fast-levenshtein": "^2.0.6",
+        "levn": "^0.4.1",
+        "prelude-ls": "^1.2.1",
+        "type-check": "^0.4.0"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/eslint/node_modules/p-locate": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+      "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+      "dev": true,
+      "dependencies": {
+        "p-limit": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/eslint/node_modules/prelude-ls": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+      "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/eslint/node_modules/type-check": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+      "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+      "dev": true,
+      "dependencies": {
+        "prelude-ls": "^1.2.1"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/eslint/node_modules/type-fest": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+      "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/espree": {
+      "version": "9.6.1",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+      "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+      "dev": true,
+      "dependencies": {
+        "acorn": "^8.9.0",
+        "acorn-jsx": "^5.3.2",
+        "eslint-visitor-keys": "^3.4.1"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/esprima": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+      "dev": true,
+      "bin": {
+        "esparse": "bin/esparse.js",
+        "esvalidate": "bin/esvalidate.js"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/esquery": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+      "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+      "dev": true,
+      "dependencies": {
+        "estraverse": "^5.1.0"
+      },
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/esquery/node_modules/estraverse": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+      "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/esrecurse": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+      "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+      "dev": true,
+      "dependencies": {
+        "estraverse": "^5.2.0"
+      },
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/esrecurse/node_modules/estraverse": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+      "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/estraverse": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+      "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+      "dev": true,
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/esutils": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/etag": {
+      "version": "1.8.1",
+      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+      "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/event-target-shim": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
+      "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/events-to-array": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/events-to-array/-/events-to-array-1.1.2.tgz",
+      "integrity": "sha512-inRWzRY7nG+aXZxBzEqYKB3HPgwflZRopAjDCHv0whhRx+MTUr1ei0ICZUypdyE0HRm4L2d5VEcIqLD6yl+BFA==",
+      "dev": true
+    },
+    "node_modules/execa": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+      "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+      "dev": true,
+      "dependencies": {
+        "cross-spawn": "^7.0.3",
+        "get-stream": "^6.0.0",
+        "human-signals": "^2.1.0",
+        "is-stream": "^2.0.0",
+        "merge-stream": "^2.0.0",
+        "npm-run-path": "^4.0.1",
+        "onetime": "^5.1.2",
+        "signal-exit": "^3.0.3",
+        "strip-final-newline": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sindresorhus/execa?sponsor=1"
+      }
+    },
+    "node_modules/exit": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+      "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/expect": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz",
+      "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==",
+      "dev": true,
+      "dependencies": {
+        "@jest/expect-utils": "^29.7.0",
+        "jest-get-type": "^29.6.3",
+        "jest-matcher-utils": "^29.7.0",
+        "jest-message-util": "^29.7.0",
+        "jest-util": "^29.7.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/fast-deep-equal": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+      "dev": true
+    },
+    "node_modules/fast-glob": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
+      "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
+      "dev": true,
+      "dependencies": {
+        "@nodelib/fs.stat": "^2.0.2",
+        "@nodelib/fs.walk": "^1.2.3",
+        "glob-parent": "^5.1.2",
+        "merge2": "^1.3.0",
+        "micromatch": "^4.0.4"
+      },
+      "engines": {
+        "node": ">=8.6.0"
+      }
+    },
+    "node_modules/fast-json-stable-stringify": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+      "dev": true
+    },
+    "node_modules/fast-levenshtein": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+      "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+      "dev": true
+    },
+    "node_modules/fastq": {
+      "version": "1.15.0",
+      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
+      "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+      "dev": true,
+      "dependencies": {
+        "reusify": "^1.0.4"
+      }
+    },
+    "node_modules/fb-watchman": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
+      "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
+      "dev": true,
+      "dependencies": {
+        "bser": "2.1.1"
+      }
+    },
+    "node_modules/figlet": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.6.0.tgz",
+      "integrity": "sha512-31EQGhCEITv6+hi2ORRPyn3bulaV9Fl4xOdR169cBzH/n1UqcxsiSB/noo6SJdD7Kfb1Ljit+IgR1USvF/XbdA==",
+      "dev": true,
+      "bin": {
+        "figlet": "bin/index.js"
+      },
+      "engines": {
+        "node": ">= 0.4.0"
+      }
+    },
+    "node_modules/file-entry-cache": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+      "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+      "dev": true,
+      "dependencies": {
+        "flat-cache": "^3.0.4"
+      },
+      "engines": {
+        "node": "^10.12.0 || >=12.0.0"
+      }
+    },
+    "node_modules/fill-keys": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz",
+      "integrity": "sha512-tcgI872xXjwFF4xgQmLxi76GnwJG3g/3isB1l4/G5Z4zrbddGpBjqZCO9oEAcB5wX0Hj/5iQB3toxfO7in1hHA==",
+      "dev": true,
+      "dependencies": {
+        "is-object": "~1.0.1",
+        "merge-descriptors": "~1.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/fill-range": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+      "dev": true,
+      "dependencies": {
+        "to-regex-range": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/finalhandler": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+      "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+      "dev": true,
+      "dependencies": {
+        "debug": "2.6.9",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "on-finished": "~2.3.0",
+        "parseurl": "~1.3.3",
+        "statuses": "~1.5.0",
+        "unpipe": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/find-cache-dir": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
+      "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
+      "dev": true,
+      "dependencies": {
+        "commondir": "^1.0.1",
+        "make-dir": "^2.0.0",
+        "pkg-dir": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/find-cache-dir/node_modules/find-up": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+      "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+      "dev": true,
+      "dependencies": {
+        "locate-path": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/find-cache-dir/node_modules/locate-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+      "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+      "dev": true,
+      "dependencies": {
+        "p-locate": "^3.0.0",
+        "path-exists": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/find-cache-dir/node_modules/make-dir": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+      "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+      "dev": true,
+      "dependencies": {
+        "pify": "^4.0.1",
+        "semver": "^5.6.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/find-cache-dir/node_modules/p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "dev": true,
+      "dependencies": {
+        "p-try": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/find-cache-dir/node_modules/p-locate": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+      "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+      "dev": true,
+      "dependencies": {
+        "p-limit": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/find-cache-dir/node_modules/path-exists": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+      "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/find-cache-dir/node_modules/pkg-dir": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
+      "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
+      "dev": true,
+      "dependencies": {
+        "find-up": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/find-cache-dir/node_modules/semver": {
+      "version": "5.7.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+      "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver"
+      }
+    },
+    "node_modules/find-up": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+      "dev": true,
+      "dependencies": {
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/findit": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/findit/-/findit-2.0.0.tgz",
+      "integrity": "sha512-ENZS237/Hr8bjczn5eKuBohLgaD0JyUd0arxretR1f9RO46vZHA1b2y0VorgGV3WaOT3c+78P8h7v4JGJ1i/rg==",
+      "dev": true
+    },
+    "node_modules/flat": {
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+      "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+      "dev": true,
+      "bin": {
+        "flat": "cli.js"
+      }
+    },
+    "node_modules/flat-cache": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz",
+      "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==",
+      "dev": true,
+      "dependencies": {
+        "flatted": "^3.2.9",
+        "keyv": "^4.5.3",
+        "rimraf": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=12.0.0"
+      }
+    },
+    "node_modules/flat-cache/node_modules/rimraf": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+      "dev": true,
+      "dependencies": {
+        "glob": "^7.1.3"
+      },
+      "bin": {
+        "rimraf": "bin.js"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/flatted": {
+      "version": "3.2.9",
+      "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
+      "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
+      "dev": true
+    },
+    "node_modules/follow-redirects": {
+      "version": "1.15.3",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",
+      "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "individual",
+          "url": "https://github.com/sponsors/RubenVerborgh"
+        }
+      ],
+      "engines": {
+        "node": ">=4.0"
+      },
+      "peerDependenciesMeta": {
+        "debug": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/for-each": {
+      "version": "0.3.3",
+      "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
+      "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+      "dev": true,
+      "dependencies": {
+        "is-callable": "^1.1.3"
+      }
+    },
+    "node_modules/foreground-child": {
+      "version": "1.5.6",
+      "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz",
+      "integrity": "sha512-3TOY+4TKV0Ml83PXJQY+JFQaHNV38lzQDIzzXYg1kWdBLenGgoZhAs0CKgzI31vi2pWEpQMq/Yi4bpKwCPkw7g==",
+      "dev": true,
+      "dependencies": {
+        "cross-spawn": "^4",
+        "signal-exit": "^3.0.0"
+      }
+    },
+    "node_modules/foreground-child/node_modules/cross-spawn": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz",
+      "integrity": "sha512-yAXz/pA1tD8Gtg2S98Ekf/sewp3Lcp3YoFKJ4Hkp5h5yLWnKVTDU0kwjKJ8NDCYcfTLfyGkzTikst+jWypT1iA==",
+      "dev": true,
+      "dependencies": {
+        "lru-cache": "^4.0.1",
+        "which": "^1.2.9"
+      }
+    },
+    "node_modules/foreground-child/node_modules/lru-cache": {
+      "version": "4.1.5",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+      "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+      "dev": true,
+      "dependencies": {
+        "pseudomap": "^1.0.2",
+        "yallist": "^2.1.2"
+      }
+    },
+    "node_modules/foreground-child/node_modules/which": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+      "dev": true,
+      "dependencies": {
+        "isexe": "^2.0.0"
+      },
+      "bin": {
+        "which": "bin/which"
+      }
+    },
+    "node_modules/foreground-child/node_modules/yallist": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+      "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==",
+      "dev": true
+    },
+    "node_modules/form-data": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+      "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+      "dev": true,
+      "dependencies": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.8",
+        "mime-types": "^2.1.12"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/formdata-node": {
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz",
+      "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==",
+      "dev": true,
+      "dependencies": {
+        "node-domexception": "1.0.0",
+        "web-streams-polyfill": "4.0.0-beta.3"
+      },
+      "engines": {
+        "node": ">= 12.20"
+      }
+    },
+    "node_modules/fresh": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+      "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/fromentries": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz",
+      "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/fs-exists-cached": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs-exists-cached/-/fs-exists-cached-1.0.0.tgz",
+      "integrity": "sha512-kSxoARUDn4F2RPXX48UXnaFKwVU7Ivd/6qpzZL29MCDmr9sTvybv4gFCp+qaI4fM9m0z9fgz/yJvi56GAz+BZg==",
+      "dev": true
+    },
+    "node_modules/fs-extra": {
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
+      "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
+      "dev": true,
+      "dependencies": {
+        "graceful-fs": "^4.2.0",
+        "jsonfile": "^4.0.0",
+        "universalify": "^0.1.0"
+      },
+      "engines": {
+        "node": ">=6 <7 || >=8"
+      }
+    },
+    "node_modules/fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+      "dev": true
+    },
+    "node_modules/fsevents": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+      "dev": true,
+      "hasInstallScript": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/function-loop": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/function-loop/-/function-loop-2.0.1.tgz",
+      "integrity": "sha512-ktIR+O6i/4h+j/ZhZJNdzeI4i9lEPeEK6UPR2EVyTVBqOwcU3Za9xYKLH64ZR9HmcROyRrOkizNyjjtWJzDDkQ==",
+      "dev": true
+    },
+    "node_modules/function.prototype.name": {
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz",
+      "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1",
+        "functions-have-names": "^1.2.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/functions-have-names": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+      "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/gensync": {
+      "version": "1.0.0-beta.2",
+      "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+      "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/get-caller-file": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+      "dev": true,
+      "engines": {
+        "node": "6.* || 8.* || >= 10.*"
+      }
+    },
+    "node_modules/get-func-name": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz",
+      "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==",
+      "dev": true,
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/get-intrinsic": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
+      "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==",
+      "dev": true,
+      "dependencies": {
+        "function-bind": "^1.1.2",
+        "has-proto": "^1.0.1",
+        "has-symbols": "^1.0.3",
+        "hasown": "^2.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-package-type": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+      "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=8.0.0"
+      }
+    },
+    "node_modules/get-port": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz",
+      "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/get-stdin": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz",
+      "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/get-stream": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+      "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/get-symbol-description": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
+      "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "get-intrinsic": "^1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/glob": {
+      "version": "7.2.3",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+      "dev": true,
+      "dependencies": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.1.1",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      },
+      "engines": {
+        "node": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/glob-parent": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+      "dev": true,
+      "dependencies": {
+        "is-glob": "^4.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/global-dirs": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz",
+      "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==",
+      "dev": true,
+      "dependencies": {
+        "ini": "1.3.7"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/globals": {
+      "version": "11.12.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+      "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/globalthis": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
+      "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
+      "dev": true,
+      "dependencies": {
+        "define-properties": "^1.1.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/globby": {
+      "version": "11.1.0",
+      "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+      "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+      "dev": true,
+      "dependencies": {
+        "array-union": "^2.1.0",
+        "dir-glob": "^3.0.1",
+        "fast-glob": "^3.2.9",
+        "ignore": "^5.2.0",
+        "merge2": "^1.4.1",
+        "slash": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/gopd": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+      "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+      "dev": true,
+      "dependencies": {
+        "get-intrinsic": "^1.1.3"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/got": {
+      "version": "9.6.0",
+      "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz",
+      "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==",
+      "dev": true,
+      "dependencies": {
+        "@sindresorhus/is": "^0.14.0",
+        "@szmarczak/http-timer": "^1.1.2",
+        "cacheable-request": "^6.0.0",
+        "decompress-response": "^3.3.0",
+        "duplexer3": "^0.1.4",
+        "get-stream": "^4.1.0",
+        "lowercase-keys": "^1.0.1",
+        "mimic-response": "^1.0.1",
+        "p-cancelable": "^1.0.0",
+        "to-readable-stream": "^1.0.0",
+        "url-parse-lax": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8.6"
+      }
+    },
+    "node_modules/got/node_modules/get-stream": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+      "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+      "dev": true,
+      "dependencies": {
+        "pump": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/graceful-fs": {
+      "version": "4.2.11",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+      "dev": true
+    },
+    "node_modules/graphemer": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+      "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+      "dev": true
+    },
+    "node_modules/hard-rejection": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz",
+      "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/has": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz",
+      "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4.0"
+      }
+    },
+    "node_modules/has-ansi": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+      "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==",
+      "dev": true,
+      "dependencies": {
+        "ansi-regex": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/has-ansi/node_modules/ansi-regex": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+      "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/has-bigints": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+      "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-flag": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/has-property-descriptors": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz",
+      "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==",
+      "dev": true,
+      "dependencies": {
+        "get-intrinsic": "^1.2.2"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
+      "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-symbols": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+      "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-tostringtag": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
+      "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+      "dev": true,
+      "dependencies": {
+        "has-symbols": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-yarn": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz",
+      "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/hasha": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz",
+      "integrity": "sha512-w0Kz8lJFBoyaurBiNrIvxPqr/gJ6fOfSkpAPOepN3oECqGJag37xPbOv57izi/KP8auHgNYxn5fXtAb+1LsJ6w==",
+      "dev": true,
+      "dependencies": {
+        "is-stream": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/hasha/node_modules/is-stream": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+      "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/hasown": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
+      "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
+      "dev": true,
+      "dependencies": {
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/hdr-histogram-js": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/hdr-histogram-js/-/hdr-histogram-js-3.0.0.tgz",
+      "integrity": "sha512-/EpvQI2/Z98mNFYEnlqJ8Ogful8OpArLG/6Tf2bPnkutBVLIeMVNHjk1ZDfshF2BUweipzbk+dB1hgSB7SIakw==",
+      "dev": true,
+      "dependencies": {
+        "@assemblyscript/loader": "^0.19.21",
+        "base64-js": "^1.2.0",
+        "pako": "^1.0.3"
+      },
+      "engines": {
+        "node": ">=14"
+      }
+    },
+    "node_modules/he": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+      "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+      "dev": true,
+      "bin": {
+        "he": "bin/he"
+      }
+    },
+    "node_modules/hosted-git-info": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
+      "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
+      "dev": true,
+      "dependencies": {
+        "lru-cache": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/hosted-git-info/node_modules/lru-cache": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+      "dev": true,
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/hosted-git-info/node_modules/yallist": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+      "dev": true
+    },
+    "node_modules/html-encoding-sniffer": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
+      "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==",
+      "dev": true,
+      "dependencies": {
+        "whatwg-encoding": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/html-escaper": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+      "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+      "dev": true
+    },
+    "node_modules/http-cache-semantics": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
+      "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==",
+      "dev": true
+    },
+    "node_modules/http-errors": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
+      "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+      "dev": true,
+      "dependencies": {
+        "depd": "2.0.0",
+        "inherits": "2.0.4",
+        "setprototypeof": "1.2.0",
+        "statuses": "2.0.1",
+        "toidentifier": "1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/http-errors/node_modules/statuses": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+      "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/http-proxy-agent": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
+      "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
+      "dev": true,
+      "dependencies": {
+        "@tootallnate/once": "2",
+        "agent-base": "6",
+        "debug": "4"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/http-proxy-agent/node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/http-proxy-agent/node_modules/ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
+    "node_modules/https-pem": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/https-pem/-/https-pem-3.0.0.tgz",
+      "integrity": "sha512-JqYVRTpk1WeXziwBaTX6eyXod6Dt70d/kehtY3DR6ygl+11XgcksTjSl4NjZbNCKK3rpTB1qH9hnu75RSOFUWQ==",
+      "dev": true,
+      "hasInstallScript": true,
+      "dependencies": {
+        "selfsigned": "^2.0.1"
+      }
+    },
+    "node_modules/https-proxy-agent": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+      "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+      "dev": true,
+      "dependencies": {
+        "agent-base": "6",
+        "debug": "4"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/https-proxy-agent/node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/https-proxy-agent/node_modules/ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
+    "node_modules/human-signals": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+      "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+      "dev": true,
+      "engines": {
+        "node": ">=10.17.0"
+      }
+    },
+    "node_modules/husky": {
+      "version": "8.0.3",
+      "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz",
+      "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==",
+      "dev": true,
+      "bin": {
+        "husky": "lib/bin.js"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/typicode"
+      }
+    },
+    "node_modules/iconv-lite": {
+      "version": "0.6.3",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+      "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+      "dev": true,
+      "dependencies": {
+        "safer-buffer": ">= 2.1.2 < 3.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/ignore": {
+      "version": "5.2.4",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+      "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
+      "dev": true,
+      "engines": {
+        "node": ">= 4"
+      }
+    },
+    "node_modules/import-fresh": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+      "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+      "dev": true,
+      "dependencies": {
+        "parent-module": "^1.0.0",
+        "resolve-from": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/import-lazy": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
+      "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/import-local": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
+      "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
+      "dev": true,
+      "dependencies": {
+        "pkg-dir": "^4.2.0",
+        "resolve-cwd": "^3.0.0"
+      },
+      "bin": {
+        "import-local-fixture": "fixtures/cli.js"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/imurmurhash": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+      "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.8.19"
+      }
+    },
+    "node_modules/indent-string": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+      "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+      "dev": true,
+      "dependencies": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "node_modules/inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "dev": true
+    },
+    "node_modules/ini": {
+      "version": "1.3.7",
+      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz",
+      "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==",
+      "dev": true
+    },
+    "node_modules/internal-slot": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz",
+      "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==",
+      "dev": true,
+      "dependencies": {
+        "get-intrinsic": "^1.2.2",
+        "hasown": "^2.0.0",
+        "side-channel": "^1.0.4"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/inversify": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/inversify/-/inversify-5.1.1.tgz",
+      "integrity": "sha512-j8grHGDzv1v+8T1sAQ+3boTCntFPfvxLCkNcxB1J8qA0lUN+fAlSyYd+RXKvaPRL4AGyPxViutBEJHNXOyUdFQ==",
+      "dev": true
+    },
+    "node_modules/irregular-plurals": {
+      "version": "3.5.0",
+      "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.5.0.tgz",
+      "integrity": "sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-arguments": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
+      "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "has-tostringtag": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-array-buffer": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
+      "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "get-intrinsic": "^1.2.0",
+        "is-typed-array": "^1.1.10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-arrayish": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+      "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+      "dev": true
+    },
+    "node_modules/is-async-function": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz",
+      "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==",
+      "dev": true,
+      "dependencies": {
+        "has-tostringtag": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-bigint": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+      "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+      "dev": true,
+      "dependencies": {
+        "has-bigints": "^1.0.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-binary-path": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+      "dev": true,
+      "dependencies": {
+        "binary-extensions": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-boolean-object": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+      "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "has-tostringtag": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-callable": {
+      "version": "1.2.7",
+      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+      "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-ci": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
+      "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
+      "dev": true,
+      "dependencies": {
+        "ci-info": "^2.0.0"
+      },
+      "bin": {
+        "is-ci": "bin.js"
+      }
+    },
+    "node_modules/is-ci/node_modules/ci-info": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
+      "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
+      "dev": true
+    },
+    "node_modules/is-core-module": {
+      "version": "2.13.1",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
+      "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
+      "dev": true,
+      "dependencies": {
+        "hasown": "^2.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-date-object": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+      "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+      "dev": true,
+      "dependencies": {
+        "has-tostringtag": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-finalizationregistry": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz",
+      "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-fullwidth-code-point": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-generator-fn": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
+      "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/is-generator-function": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
+      "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
+      "dev": true,
+      "dependencies": {
+        "has-tostringtag": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-glob": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+      "dev": true,
+      "dependencies": {
+        "is-extglob": "^2.1.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-installed-globally": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz",
+      "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==",
+      "dev": true,
+      "dependencies": {
+        "global-dirs": "^2.0.1",
+        "is-path-inside": "^3.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/is-map": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
+      "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-negative-zero": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
+      "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-npm": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz",
+      "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.12.0"
+      }
+    },
+    "node_modules/is-number-object": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+      "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+      "dev": true,
+      "dependencies": {
+        "has-tostringtag": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-obj": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
+      "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-object": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz",
+      "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-path-inside": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+      "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-plain-obj": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+      "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-potential-custom-element-name": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
+      "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
+      "dev": true
+    },
+    "node_modules/is-regex": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+      "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "has-tostringtag": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-set": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz",
+      "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-shared-array-buffer": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
+      "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-stream": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+      "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/is-string": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+      "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+      "dev": true,
+      "dependencies": {
+        "has-tostringtag": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-symbol": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+      "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+      "dev": true,
+      "dependencies": {
+        "has-symbols": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-typed-array": {
+      "version": "1.1.12",
+      "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz",
+      "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==",
+      "dev": true,
+      "dependencies": {
+        "which-typed-array": "^1.1.11"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-typedarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+      "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
+      "dev": true
+    },
+    "node_modules/is-unicode-supported": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+      "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/is-weakmap": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
+      "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-weakref": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+      "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-weakset": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz",
+      "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "get-intrinsic": "^1.1.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-windows": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+      "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-wsl": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
+      "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/is-yarn-global": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz",
+      "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==",
+      "dev": true
+    },
+    "node_modules/isarray": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+      "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==",
+      "dev": true
+    },
+    "node_modules/isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+      "dev": true
+    },
+    "node_modules/istanbul-lib-coverage": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
+      "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/istanbul-lib-hook": {
+      "version": "2.0.7",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz",
+      "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==",
+      "dev": true,
+      "dependencies": {
+        "append-transform": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/istanbul-lib-instrument": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz",
+      "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/core": "^7.12.3",
+        "@babel/parser": "^7.14.7",
+        "@istanbuljs/schema": "^0.1.2",
+        "istanbul-lib-coverage": "^3.2.0",
+        "semver": "^7.5.4"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/istanbul-lib-processinfo": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz",
+      "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==",
+      "dev": true,
+      "dependencies": {
+        "archy": "^1.0.0",
+        "cross-spawn": "^7.0.3",
+        "istanbul-lib-coverage": "^3.2.0",
+        "p-map": "^3.0.0",
+        "rimraf": "^3.0.0",
+        "uuid": "^8.3.2"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/istanbul-lib-processinfo/node_modules/rimraf": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+      "dev": true,
+      "dependencies": {
+        "glob": "^7.1.3"
+      },
+      "bin": {
+        "rimraf": "bin.js"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/istanbul-lib-processinfo/node_modules/uuid": {
+      "version": "8.3.2",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+      "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+      "dev": true,
+      "bin": {
+        "uuid": "dist/bin/uuid"
+      }
+    },
+    "node_modules/istanbul-lib-report": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+      "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
+      "dev": true,
+      "dependencies": {
+        "istanbul-lib-coverage": "^3.0.0",
+        "make-dir": "^4.0.0",
+        "supports-color": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/istanbul-lib-report/node_modules/make-dir": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+      "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
+      "dev": true,
+      "dependencies": {
+        "semver": "^7.5.3"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/istanbul-lib-report/node_modules/supports-color": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/istanbul-lib-source-maps": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
+      "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
+      "dev": true,
+      "dependencies": {
+        "debug": "^4.1.1",
+        "istanbul-lib-coverage": "^3.0.0",
+        "source-map": "^0.6.1"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/istanbul-lib-source-maps/node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/istanbul-lib-source-maps/node_modules/ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
+    "node_modules/istanbul-reports": {
+      "version": "3.1.6",
+      "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz",
+      "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==",
+      "dev": true,
+      "dependencies": {
+        "html-escaper": "^2.0.0",
+        "istanbul-lib-report": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/iterator.prototype": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz",
+      "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==",
+      "dev": true,
+      "dependencies": {
+        "define-properties": "^1.2.1",
+        "get-intrinsic": "^1.2.1",
+        "has-symbols": "^1.0.3",
+        "reflect.getprototypeof": "^1.0.4",
+        "set-function-name": "^2.0.1"
+      }
+    },
+    "node_modules/jackspeak": {
+      "version": "1.4.2",
+      "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-1.4.2.tgz",
+      "integrity": "sha512-GHeGTmnuaHnvS+ZctRB01bfxARuu9wW83ENbuiweu07SFcVlZrJpcshSre/keGT7YGBhLHg/+rXCNSrsEHKU4Q==",
+      "dev": true,
+      "dependencies": {
+        "cliui": "^7.0.4"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/jest": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz",
+      "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
+      "dev": true,
+      "dependencies": {
+        "@jest/core": "^29.7.0",
+        "@jest/types": "^29.6.3",
+        "import-local": "^3.0.2",
+        "jest-cli": "^29.7.0"
+      },
+      "bin": {
+        "jest": "bin/jest.js"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      },
+      "peerDependencies": {
+        "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+      },
+      "peerDependenciesMeta": {
+        "node-notifier": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/jest-changed-files": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz",
+      "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==",
+      "dev": true,
+      "dependencies": {
+        "execa": "^5.0.0",
+        "jest-util": "^29.7.0",
+        "p-limit": "^3.1.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-circus": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz",
+      "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==",
+      "dev": true,
+      "dependencies": {
+        "@jest/environment": "^29.7.0",
+        "@jest/expect": "^29.7.0",
+        "@jest/test-result": "^29.7.0",
+        "@jest/types": "^29.6.3",
+        "@types/node": "*",
+        "chalk": "^4.0.0",
+        "co": "^4.6.0",
+        "dedent": "^1.0.0",
+        "is-generator-fn": "^2.0.0",
+        "jest-each": "^29.7.0",
+        "jest-matcher-utils": "^29.7.0",
+        "jest-message-util": "^29.7.0",
+        "jest-runtime": "^29.7.0",
+        "jest-snapshot": "^29.7.0",
+        "jest-util": "^29.7.0",
+        "p-limit": "^3.1.0",
+        "pretty-format": "^29.7.0",
+        "pure-rand": "^6.0.0",
+        "slash": "^3.0.0",
+        "stack-utils": "^2.0.3"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-cli": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz",
+      "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==",
+      "dev": true,
+      "dependencies": {
+        "@jest/core": "^29.7.0",
+        "@jest/test-result": "^29.7.0",
+        "@jest/types": "^29.6.3",
+        "chalk": "^4.0.0",
+        "create-jest": "^29.7.0",
+        "exit": "^0.1.2",
+        "import-local": "^3.0.2",
+        "jest-config": "^29.7.0",
+        "jest-util": "^29.7.0",
+        "jest-validate": "^29.7.0",
+        "yargs": "^17.3.1"
+      },
+      "bin": {
+        "jest": "bin/jest.js"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      },
+      "peerDependencies": {
+        "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+      },
+      "peerDependenciesMeta": {
+        "node-notifier": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/jest-config": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz",
+      "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/core": "^7.11.6",
+        "@jest/test-sequencer": "^29.7.0",
+        "@jest/types": "^29.6.3",
+        "babel-jest": "^29.7.0",
+        "chalk": "^4.0.0",
+        "ci-info": "^3.2.0",
+        "deepmerge": "^4.2.2",
+        "glob": "^7.1.3",
+        "graceful-fs": "^4.2.9",
+        "jest-circus": "^29.7.0",
+        "jest-environment-node": "^29.7.0",
+        "jest-get-type": "^29.6.3",
+        "jest-regex-util": "^29.6.3",
+        "jest-resolve": "^29.7.0",
+        "jest-runner": "^29.7.0",
+        "jest-util": "^29.7.0",
+        "jest-validate": "^29.7.0",
+        "micromatch": "^4.0.4",
+        "parse-json": "^5.2.0",
+        "pretty-format": "^29.7.0",
+        "slash": "^3.0.0",
+        "strip-json-comments": "^3.1.1"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      },
+      "peerDependencies": {
+        "@types/node": "*",
+        "ts-node": ">=9.0.0"
+      },
+      "peerDependenciesMeta": {
+        "@types/node": {
+          "optional": true
+        },
+        "ts-node": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/jest-diff": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz",
+      "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==",
+      "dev": true,
+      "dependencies": {
+        "chalk": "^4.0.0",
+        "diff-sequences": "^29.6.3",
+        "jest-get-type": "^29.6.3",
+        "pretty-format": "^29.7.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-docblock": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz",
+      "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==",
+      "dev": true,
+      "dependencies": {
+        "detect-newline": "^3.0.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-each": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz",
+      "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==",
+      "dev": true,
+      "dependencies": {
+        "@jest/types": "^29.6.3",
+        "chalk": "^4.0.0",
+        "jest-get-type": "^29.6.3",
+        "jest-util": "^29.7.0",
+        "pretty-format": "^29.7.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-environment-node": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
+      "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==",
+      "dev": true,
+      "dependencies": {
+        "@jest/environment": "^29.7.0",
+        "@jest/fake-timers": "^29.7.0",
+        "@jest/types": "^29.6.3",
+        "@types/node": "*",
+        "jest-mock": "^29.7.0",
+        "jest-util": "^29.7.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-get-type": {
+      "version": "29.6.3",
+      "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
+      "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
+      "dev": true,
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-haste-map": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz",
+      "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==",
+      "dev": true,
+      "dependencies": {
+        "@jest/types": "^29.6.3",
+        "@types/graceful-fs": "^4.1.3",
+        "@types/node": "*",
+        "anymatch": "^3.0.3",
+        "fb-watchman": "^2.0.0",
+        "graceful-fs": "^4.2.9",
+        "jest-regex-util": "^29.6.3",
+        "jest-util": "^29.7.0",
+        "jest-worker": "^29.7.0",
+        "micromatch": "^4.0.4",
+        "walker": "^1.0.8"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      },
+      "optionalDependencies": {
+        "fsevents": "^2.3.2"
+      }
+    },
+    "node_modules/jest-leak-detector": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz",
+      "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==",
+      "dev": true,
+      "dependencies": {
+        "jest-get-type": "^29.6.3",
+        "pretty-format": "^29.7.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-matcher-utils": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz",
+      "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==",
+      "dev": true,
+      "dependencies": {
+        "chalk": "^4.0.0",
+        "jest-diff": "^29.7.0",
+        "jest-get-type": "^29.6.3",
+        "pretty-format": "^29.7.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-message-util": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+      "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+      "dev": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.12.13",
+        "@jest/types": "^29.6.3",
+        "@types/stack-utils": "^2.0.0",
+        "chalk": "^4.0.0",
+        "graceful-fs": "^4.2.9",
+        "micromatch": "^4.0.4",
+        "pretty-format": "^29.7.0",
+        "slash": "^3.0.0",
+        "stack-utils": "^2.0.3"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-mock": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
+      "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
+      "dev": true,
+      "dependencies": {
+        "@jest/types": "^29.6.3",
+        "@types/node": "*",
+        "jest-util": "^29.7.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-pnp-resolver": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
+      "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      },
+      "peerDependencies": {
+        "jest-resolve": "*"
+      },
+      "peerDependenciesMeta": {
+        "jest-resolve": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/jest-regex-util": {
+      "version": "29.6.3",
+      "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+      "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
+      "dev": true,
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-resolve": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz",
+      "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==",
+      "dev": true,
+      "dependencies": {
+        "chalk": "^4.0.0",
+        "graceful-fs": "^4.2.9",
+        "jest-haste-map": "^29.7.0",
+        "jest-pnp-resolver": "^1.2.2",
+        "jest-util": "^29.7.0",
+        "jest-validate": "^29.7.0",
+        "resolve": "^1.20.0",
+        "resolve.exports": "^2.0.0",
+        "slash": "^3.0.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-resolve-dependencies": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz",
+      "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==",
+      "dev": true,
+      "dependencies": {
+        "jest-regex-util": "^29.6.3",
+        "jest-snapshot": "^29.7.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-runner": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz",
+      "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==",
+      "dev": true,
+      "dependencies": {
+        "@jest/console": "^29.7.0",
+        "@jest/environment": "^29.7.0",
+        "@jest/test-result": "^29.7.0",
+        "@jest/transform": "^29.7.0",
+        "@jest/types": "^29.6.3",
+        "@types/node": "*",
+        "chalk": "^4.0.0",
+        "emittery": "^0.13.1",
+        "graceful-fs": "^4.2.9",
+        "jest-docblock": "^29.7.0",
+        "jest-environment-node": "^29.7.0",
+        "jest-haste-map": "^29.7.0",
+        "jest-leak-detector": "^29.7.0",
+        "jest-message-util": "^29.7.0",
+        "jest-resolve": "^29.7.0",
+        "jest-runtime": "^29.7.0",
+        "jest-util": "^29.7.0",
+        "jest-watcher": "^29.7.0",
+        "jest-worker": "^29.7.0",
+        "p-limit": "^3.1.0",
+        "source-map-support": "0.5.13"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-runtime": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz",
+      "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==",
+      "dev": true,
+      "dependencies": {
+        "@jest/environment": "^29.7.0",
+        "@jest/fake-timers": "^29.7.0",
+        "@jest/globals": "^29.7.0",
+        "@jest/source-map": "^29.6.3",
+        "@jest/test-result": "^29.7.0",
+        "@jest/transform": "^29.7.0",
+        "@jest/types": "^29.6.3",
+        "@types/node": "*",
+        "chalk": "^4.0.0",
+        "cjs-module-lexer": "^1.0.0",
+        "collect-v8-coverage": "^1.0.0",
+        "glob": "^7.1.3",
+        "graceful-fs": "^4.2.9",
+        "jest-haste-map": "^29.7.0",
+        "jest-message-util": "^29.7.0",
+        "jest-mock": "^29.7.0",
+        "jest-regex-util": "^29.6.3",
+        "jest-resolve": "^29.7.0",
+        "jest-snapshot": "^29.7.0",
+        "jest-util": "^29.7.0",
+        "slash": "^3.0.0",
+        "strip-bom": "^4.0.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-snapshot": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz",
+      "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/core": "^7.11.6",
+        "@babel/generator": "^7.7.2",
+        "@babel/plugin-syntax-jsx": "^7.7.2",
+        "@babel/plugin-syntax-typescript": "^7.7.2",
+        "@babel/types": "^7.3.3",
+        "@jest/expect-utils": "^29.7.0",
+        "@jest/transform": "^29.7.0",
+        "@jest/types": "^29.6.3",
+        "babel-preset-current-node-syntax": "^1.0.0",
+        "chalk": "^4.0.0",
+        "expect": "^29.7.0",
+        "graceful-fs": "^4.2.9",
+        "jest-diff": "^29.7.0",
+        "jest-get-type": "^29.6.3",
+        "jest-matcher-utils": "^29.7.0",
+        "jest-message-util": "^29.7.0",
+        "jest-util": "^29.7.0",
+        "natural-compare": "^1.4.0",
+        "pretty-format": "^29.7.0",
+        "semver": "^7.5.3"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-util": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+      "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+      "dev": true,
+      "dependencies": {
+        "@jest/types": "^29.6.3",
+        "@types/node": "*",
+        "chalk": "^4.0.0",
+        "ci-info": "^3.2.0",
+        "graceful-fs": "^4.2.9",
+        "picomatch": "^2.2.3"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-validate": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz",
+      "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==",
+      "dev": true,
+      "dependencies": {
+        "@jest/types": "^29.6.3",
+        "camelcase": "^6.2.0",
+        "chalk": "^4.0.0",
+        "jest-get-type": "^29.6.3",
+        "leven": "^3.1.0",
+        "pretty-format": "^29.7.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-validate/node_modules/camelcase": {
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+      "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/jest-watcher": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz",
+      "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==",
+      "dev": true,
+      "dependencies": {
+        "@jest/test-result": "^29.7.0",
+        "@jest/types": "^29.6.3",
+        "@types/node": "*",
+        "ansi-escapes": "^4.2.1",
+        "chalk": "^4.0.0",
+        "emittery": "^0.13.1",
+        "jest-util": "^29.7.0",
+        "string-length": "^4.0.1"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-worker": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
+      "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+      "dev": true,
+      "dependencies": {
+        "@types/node": "*",
+        "jest-util": "^29.7.0",
+        "merge-stream": "^2.0.0",
+        "supports-color": "^8.0.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/joi": {
+      "version": "17.11.0",
+      "resolved": "https://registry.npmjs.org/joi/-/joi-17.11.0.tgz",
+      "integrity": "sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==",
+      "dev": true,
+      "dependencies": {
+        "@hapi/hoek": "^9.0.0",
+        "@hapi/topo": "^5.0.0",
+        "@sideway/address": "^4.1.3",
+        "@sideway/formula": "^3.0.1",
+        "@sideway/pinpoint": "^2.0.0"
+      }
+    },
+    "node_modules/js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+      "dev": true
+    },
+    "node_modules/js-yaml": {
+      "version": "3.14.1",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+      "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+      "dev": true,
+      "dependencies": {
+        "argparse": "^1.0.7",
+        "esprima": "^4.0.0"
+      },
+      "bin": {
+        "js-yaml": "bin/js-yaml.js"
+      }
+    },
+    "node_modules/jsdom": {
+      "version": "22.1.0",
+      "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-22.1.0.tgz",
+      "integrity": "sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw==",
+      "dev": true,
+      "dependencies": {
+        "abab": "^2.0.6",
+        "cssstyle": "^3.0.0",
+        "data-urls": "^4.0.0",
+        "decimal.js": "^10.4.3",
+        "domexception": "^4.0.0",
+        "form-data": "^4.0.0",
+        "html-encoding-sniffer": "^3.0.0",
+        "http-proxy-agent": "^5.0.0",
+        "https-proxy-agent": "^5.0.1",
+        "is-potential-custom-element-name": "^1.0.1",
+        "nwsapi": "^2.2.4",
+        "parse5": "^7.1.2",
+        "rrweb-cssom": "^0.6.0",
+        "saxes": "^6.0.0",
+        "symbol-tree": "^3.2.4",
+        "tough-cookie": "^4.1.2",
+        "w3c-xmlserializer": "^4.0.0",
+        "webidl-conversions": "^7.0.0",
+        "whatwg-encoding": "^2.0.0",
+        "whatwg-mimetype": "^3.0.0",
+        "whatwg-url": "^12.0.1",
+        "ws": "^8.13.0",
+        "xml-name-validator": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=16"
+      },
+      "peerDependencies": {
+        "canvas": "^2.5.0"
+      },
+      "peerDependenciesMeta": {
+        "canvas": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/jsesc": {
+      "version": "2.5.2",
+      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+      "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+      "dev": true,
+      "bin": {
+        "jsesc": "bin/jsesc"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/jsfuzz": {
+      "version": "1.0.15",
+      "resolved": "https://registry.npmjs.org/jsfuzz/-/jsfuzz-1.0.15.tgz",
+      "integrity": "sha512-NjzL5VD/AXTfVGfCyigbXuuGh+PLbVRnLSQQM0m8SL6hiBGMclm7ylAAxQZdNhE706YWCEBh0RzfTZl+zEnlMg==",
+      "dev": true,
+      "dependencies": {
+        "@types/escodegen": "^0.0.6",
+        "@types/esprima": "^4.0.2",
+        "@types/estraverse": "^0.0.6",
+        "@types/estree": "^0.0.39",
+        "deep-equal": "^1.1.0",
+        "escodegen": "^1.12.0",
+        "esprima": "^4.0.1",
+        "estraverse": "^4.3.0",
+        "inversify": "^5.0.1",
+        "nyc": "^14.1.1",
+        "pidusage": "^2.0.17",
+        "reflect-metadata": "^0.1.13",
+        "yargs": "^14.2.0"
+      },
+      "bin": {
+        "jsfuzz": "build/src/index.js"
+      }
+    },
+    "node_modules/jsfuzz/node_modules/ansi-regex": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
+      "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/jsfuzz/node_modules/ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "dev": true,
+      "dependencies": {
+        "color-convert": "^1.9.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/jsfuzz/node_modules/cliui": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
+      "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+      "dev": true,
+      "dependencies": {
+        "string-width": "^3.1.0",
+        "strip-ansi": "^5.2.0",
+        "wrap-ansi": "^5.1.0"
+      }
+    },
+    "node_modules/jsfuzz/node_modules/color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "dev": true,
+      "dependencies": {
+        "color-name": "1.1.3"
+      }
+    },
+    "node_modules/jsfuzz/node_modules/color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+      "dev": true
+    },
+    "node_modules/jsfuzz/node_modules/emoji-regex": {
+      "version": "7.0.3",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+      "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+      "dev": true
+    },
+    "node_modules/jsfuzz/node_modules/find-up": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+      "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+      "dev": true,
+      "dependencies": {
+        "locate-path": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/jsfuzz/node_modules/is-fullwidth-code-point": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+      "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/jsfuzz/node_modules/locate-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+      "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+      "dev": true,
+      "dependencies": {
+        "p-locate": "^3.0.0",
+        "path-exists": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/jsfuzz/node_modules/p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "dev": true,
+      "dependencies": {
+        "p-try": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/jsfuzz/node_modules/p-locate": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+      "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+      "dev": true,
+      "dependencies": {
+        "p-limit": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/jsfuzz/node_modules/path-exists": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+      "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/jsfuzz/node_modules/string-width": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+      "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+      "dev": true,
+      "dependencies": {
+        "emoji-regex": "^7.0.1",
+        "is-fullwidth-code-point": "^2.0.0",
+        "strip-ansi": "^5.1.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/jsfuzz/node_modules/strip-ansi": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+      "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+      "dev": true,
+      "dependencies": {
+        "ansi-regex": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/jsfuzz/node_modules/wrap-ansi": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
+      "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^3.2.0",
+        "string-width": "^3.0.0",
+        "strip-ansi": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/jsfuzz/node_modules/y18n": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+      "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
+      "dev": true
+    },
+    "node_modules/jsfuzz/node_modules/yargs": {
+      "version": "14.2.3",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz",
+      "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==",
+      "dev": true,
+      "dependencies": {
+        "cliui": "^5.0.0",
+        "decamelize": "^1.2.0",
+        "find-up": "^3.0.0",
+        "get-caller-file": "^2.0.1",
+        "require-directory": "^2.1.1",
+        "require-main-filename": "^2.0.0",
+        "set-blocking": "^2.0.0",
+        "string-width": "^3.0.0",
+        "which-module": "^2.0.0",
+        "y18n": "^4.0.0",
+        "yargs-parser": "^15.0.1"
+      }
+    },
+    "node_modules/jsfuzz/node_modules/yargs-parser": {
+      "version": "15.0.3",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.3.tgz",
+      "integrity": "sha512-/MVEVjTXy/cGAjdtQf8dW3V9b97bPN7rNn8ETj6BmAQL7ibC7O1Q9SPJbGjgh3SlwoBNXMzj/ZGIj8mBgl12YA==",
+      "dev": true,
+      "dependencies": {
+        "camelcase": "^5.0.0",
+        "decamelize": "^1.2.0"
+      }
+    },
+    "node_modules/json-buffer": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+      "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+      "dev": true
+    },
+    "node_modules/json-parse-better-errors": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+      "dev": true
+    },
+    "node_modules/json-parse-even-better-errors": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+      "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+      "dev": true
+    },
+    "node_modules/json-schema-traverse": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+      "dev": true
+    },
+    "node_modules/json-stable-stringify-without-jsonify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+      "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+      "dev": true
+    },
+    "node_modules/json5": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+      "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+      "dev": true,
+      "bin": {
+        "json5": "lib/cli.js"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/jsonfile": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+      "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
+      "dev": true,
+      "optionalDependencies": {
+        "graceful-fs": "^4.1.6"
+      }
+    },
+    "node_modules/jsx-ast-utils": {
+      "version": "3.3.5",
+      "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
+      "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
+      "dev": true,
+      "dependencies": {
+        "array-includes": "^3.1.6",
+        "array.prototype.flat": "^1.3.1",
+        "object.assign": "^4.1.4",
+        "object.values": "^1.1.6"
+      },
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/just-extend": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz",
+      "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==",
+      "dev": true
+    },
+    "node_modules/keyv": {
+      "version": "4.5.4",
+      "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+      "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+      "dev": true,
+      "dependencies": {
+        "json-buffer": "3.0.1"
+      }
+    },
+    "node_modules/kind-of": {
+      "version": "6.0.3",
+      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+      "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/kleur": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+      "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/latest-version": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz",
+      "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==",
+      "dev": true,
+      "dependencies": {
+        "package-json": "^6.3.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/leven": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+      "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/levn": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+      "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==",
+      "dev": true,
+      "dependencies": {
+        "prelude-ls": "~1.1.2",
+        "type-check": "~0.3.2"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/libtap": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/libtap/-/libtap-1.4.1.tgz",
+      "integrity": "sha512-S9v19shLTigoMn3c02V7LZ4t09zxmVP3r3RbEAwuHFYeKgF+ESFJxoQ0PMFKW4XdgQhcjVBEwDoopG6WROq/gw==",
+      "dev": true,
+      "dependencies": {
+        "async-hook-domain": "^2.0.4",
+        "bind-obj-methods": "^3.0.0",
+        "diff": "^4.0.2",
+        "function-loop": "^2.0.1",
+        "minipass": "^3.1.5",
+        "own-or": "^1.0.0",
+        "own-or-env": "^1.0.2",
+        "signal-exit": "^3.0.4",
+        "stack-utils": "^2.0.4",
+        "tap-parser": "^11.0.0",
+        "tap-yaml": "^1.0.0",
+        "tcompare": "^5.0.6",
+        "trivial-deferred": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/libtap/node_modules/diff": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+      "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.3.1"
+      }
+    },
+    "node_modules/lines-and-columns": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+      "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+      "dev": true
+    },
+    "node_modules/livereload": {
+      "version": "0.9.3",
+      "resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.3.tgz",
+      "integrity": "sha512-q7Z71n3i4X0R9xthAryBdNGVGAO2R5X+/xXpmKeuPMrteg+W2U8VusTKV3YiJbXZwKsOlFlHe+go6uSNjfxrZw==",
+      "dev": true,
+      "dependencies": {
+        "chokidar": "^3.5.0",
+        "livereload-js": "^3.3.1",
+        "opts": ">= 1.2.0",
+        "ws": "^7.4.3"
+      },
+      "bin": {
+        "livereload": "bin/livereload.js"
+      },
+      "engines": {
+        "node": ">=8.0.0"
+      }
+    },
+    "node_modules/livereload-js": {
+      "version": "3.4.1",
+      "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-3.4.1.tgz",
+      "integrity": "sha512-5MP0uUeVCec89ZbNOT/i97Mc+q3SxXmiUGhRFOTmhrGPn//uWVQdCvcLJDy64MSBR5MidFdOR7B9viumoavy6g==",
+      "dev": true
+    },
+    "node_modules/livereload/node_modules/ws": {
+      "version": "7.5.9",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
+      "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=8.3.0"
+      },
+      "peerDependencies": {
+        "bufferutil": "^4.0.1",
+        "utf-8-validate": "^5.0.2"
+      },
+      "peerDependenciesMeta": {
+        "bufferutil": {
+          "optional": true
+        },
+        "utf-8-validate": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/load-json-file": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz",
+      "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==",
+      "dev": true,
+      "dependencies": {
+        "graceful-fs": "^4.1.15",
+        "parse-json": "^4.0.0",
+        "pify": "^4.0.1",
+        "strip-bom": "^3.0.0",
+        "type-fest": "^0.3.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/load-json-file/node_modules/parse-json": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+      "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
+      "dev": true,
+      "dependencies": {
+        "error-ex": "^1.3.1",
+        "json-parse-better-errors": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/load-json-file/node_modules/strip-bom": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+      "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/load-json-file/node_modules/type-fest": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz",
+      "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/locate-path": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+      "dev": true,
+      "dependencies": {
+        "p-locate": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/lodash": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+      "dev": true
+    },
+    "node_modules/lodash.flattendeep": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
+      "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==",
+      "dev": true
+    },
+    "node_modules/lodash.get": {
+      "version": "4.4.2",
+      "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
+      "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==",
+      "dev": true
+    },
+    "node_modules/lodash.merge": {
+      "version": "4.6.2",
+      "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+      "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+      "dev": true
+    },
+    "node_modules/lodash.truncate": {
+      "version": "4.4.2",
+      "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
+      "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==",
+      "dev": true
+    },
+    "node_modules/log-symbols": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+      "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+      "dev": true,
+      "dependencies": {
+        "chalk": "^4.1.0",
+        "is-unicode-supported": "^0.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/loose-envify": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+      "dev": true,
+      "dependencies": {
+        "js-tokens": "^3.0.0 || ^4.0.0"
+      },
+      "bin": {
+        "loose-envify": "cli.js"
+      }
+    },
+    "node_modules/loupe": {
+      "version": "2.3.7",
+      "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz",
+      "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==",
+      "dev": true,
+      "dependencies": {
+        "get-func-name": "^2.0.1"
+      }
+    },
+    "node_modules/lowercase-keys": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
+      "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/lru-cache": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+      "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+      "dev": true,
+      "dependencies": {
+        "yallist": "^3.0.2"
+      }
+    },
+    "node_modules/make-dir": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+      "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+      "dev": true,
+      "dependencies": {
+        "semver": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/make-dir/node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/makeerror": {
+      "version": "1.0.12",
+      "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
+      "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+      "dev": true,
+      "dependencies": {
+        "tmpl": "1.0.5"
+      }
+    },
+    "node_modules/map-obj": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz",
+      "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/marked": {
+      "version": "1.2.9",
+      "resolved": "https://registry.npmjs.org/marked/-/marked-1.2.9.tgz",
+      "integrity": "sha512-H8lIX2SvyitGX+TRdtS06m1jHMijKN/XjfH6Ooii9fvxMlh8QdqBfBDkGUpMWH2kQNrtixjzYUa3SH8ROTgRRw==",
+      "dev": true,
+      "bin": {
+        "marked": "bin/marked"
+      },
+      "engines": {
+        "node": ">= 8.16.2"
+      }
+    },
+    "node_modules/medium-zoom": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/medium-zoom/-/medium-zoom-1.0.8.tgz",
+      "integrity": "sha512-CjFVuFq/IfrdqesAXfg+hzlDKu6A2n80ZIq0Kl9kWjoHh9j1N9Uvk5X0/MmN0hOfm5F9YBswlClhcwnmtwz7gA==",
+      "dev": true
+    },
+    "node_modules/meow": {
+      "version": "9.0.0",
+      "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz",
+      "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==",
+      "dev": true,
+      "dependencies": {
+        "@types/minimist": "^1.2.0",
+        "camelcase-keys": "^6.2.2",
+        "decamelize": "^1.2.0",
+        "decamelize-keys": "^1.1.0",
+        "hard-rejection": "^2.1.0",
+        "minimist-options": "4.1.0",
+        "normalize-package-data": "^3.0.0",
+        "read-pkg-up": "^7.0.1",
+        "redent": "^3.0.0",
+        "trim-newlines": "^3.0.0",
+        "type-fest": "^0.18.0",
+        "yargs-parser": "^20.2.3"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/meow/node_modules/type-fest": {
+      "version": "0.18.1",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz",
+      "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/merge-descriptors": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+      "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==",
+      "dev": true
+    },
+    "node_modules/merge-source-map": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz",
+      "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==",
+      "dev": true,
+      "dependencies": {
+        "source-map": "^0.6.1"
+      }
+    },
+    "node_modules/merge-stream": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+      "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+      "dev": true
+    },
+    "node_modules/merge2": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/micromatch": {
+      "version": "4.0.5",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+      "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+      "dev": true,
+      "dependencies": {
+        "braces": "^3.0.2",
+        "picomatch": "^2.3.1"
+      },
+      "engines": {
+        "node": ">=8.6"
+      }
+    },
+    "node_modules/mime": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+      "dev": true,
+      "bin": {
+        "mime": "cli.js"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "dev": true,
+      "dependencies": {
+        "mime-db": "1.52.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mimic-fn": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+      "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/mimic-response": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
+      "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/min-indent": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
+      "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dev": true,
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/minimist": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+      "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/minimist-options": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz",
+      "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==",
+      "dev": true,
+      "dependencies": {
+        "arrify": "^1.0.1",
+        "is-plain-obj": "^1.1.0",
+        "kind-of": "^6.0.3"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/minipass": {
+      "version": "3.3.6",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+      "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+      "dev": true,
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/minipass/node_modules/yallist": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+      "dev": true
+    },
+    "node_modules/mkdirp": {
+      "version": "0.5.6",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+      "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+      "dev": true,
+      "dependencies": {
+        "minimist": "^1.2.6"
+      },
+      "bin": {
+        "mkdirp": "bin/cmd.js"
+      }
+    },
+    "node_modules/mocha": {
+      "version": "10.2.0",
+      "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz",
+      "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==",
+      "dev": true,
+      "dependencies": {
+        "ansi-colors": "4.1.1",
+        "browser-stdout": "1.3.1",
+        "chokidar": "3.5.3",
+        "debug": "4.3.4",
+        "diff": "5.0.0",
+        "escape-string-regexp": "4.0.0",
+        "find-up": "5.0.0",
+        "glob": "7.2.0",
+        "he": "1.2.0",
+        "js-yaml": "4.1.0",
+        "log-symbols": "4.1.0",
+        "minimatch": "5.0.1",
+        "ms": "2.1.3",
+        "nanoid": "3.3.3",
+        "serialize-javascript": "6.0.0",
+        "strip-json-comments": "3.1.1",
+        "supports-color": "8.1.1",
+        "workerpool": "6.2.1",
+        "yargs": "16.2.0",
+        "yargs-parser": "20.2.4",
+        "yargs-unparser": "2.0.0"
+      },
+      "bin": {
+        "_mocha": "bin/_mocha",
+        "mocha": "bin/mocha.js"
+      },
+      "engines": {
+        "node": ">= 14.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/mochajs"
+      }
+    },
+    "node_modules/mocha/node_modules/ansi-colors": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+      "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/mocha/node_modules/argparse": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+      "dev": true
+    },
+    "node_modules/mocha/node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/mocha/node_modules/debug/node_modules/ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
+    "node_modules/mocha/node_modules/find-up": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+      "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+      "dev": true,
+      "dependencies": {
+        "locate-path": "^6.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/mocha/node_modules/glob": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+      "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+      "dev": true,
+      "dependencies": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.0.4",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      },
+      "engines": {
+        "node": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/mocha/node_modules/glob/node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dev": true,
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/mocha/node_modules/js-yaml": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+      "dev": true,
+      "dependencies": {
+        "argparse": "^2.0.1"
+      },
+      "bin": {
+        "js-yaml": "bin/js-yaml.js"
+      }
+    },
+    "node_modules/mocha/node_modules/locate-path": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+      "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+      "dev": true,
+      "dependencies": {
+        "p-locate": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/mocha/node_modules/minimatch": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+      "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
+      "dev": true,
+      "dependencies": {
+        "brace-expansion": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/mocha/node_modules/minimatch/node_modules/brace-expansion": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+      "dev": true,
+      "dependencies": {
+        "balanced-match": "^1.0.0"
+      }
+    },
+    "node_modules/mocha/node_modules/ms": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+      "dev": true
+    },
+    "node_modules/mocha/node_modules/p-locate": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+      "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+      "dev": true,
+      "dependencies": {
+        "p-limit": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/mocha/node_modules/yargs": {
+      "version": "16.2.0",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+      "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
+      "dev": true,
+      "dependencies": {
+        "cliui": "^7.0.2",
+        "escalade": "^3.1.1",
+        "get-caller-file": "^2.0.5",
+        "require-directory": "^2.1.1",
+        "string-width": "^4.2.0",
+        "y18n": "^5.0.5",
+        "yargs-parser": "^20.2.2"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/module-not-found-error": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz",
+      "integrity": "sha512-pEk4ECWQXV6z2zjhRZUongnLJNUeGQJ3w6OQ5ctGwD+i5o93qjRQUk2Rt6VdNeu3sEP0AB4LcfvdebpxBRVr4g==",
+      "dev": true
+    },
+    "node_modules/mri": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.4.tgz",
+      "integrity": "sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+      "dev": true
+    },
+    "node_modules/nanoid": {
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
+      "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
+      "dev": true,
+      "bin": {
+        "nanoid": "bin/nanoid.cjs"
+      },
+      "engines": {
+        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+      }
+    },
+    "node_modules/natural-compare": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+      "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+      "dev": true
+    },
+    "node_modules/nested-error-stacks": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.1.tgz",
+      "integrity": "sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==",
+      "dev": true
+    },
+    "node_modules/nise": {
+      "version": "5.1.5",
+      "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.5.tgz",
+      "integrity": "sha512-VJuPIfUFaXNRzETTQEEItTOP8Y171ijr+JLq42wHes3DiryR8vT+1TXQW/Rx8JNUhyYYWyIvjXTU6dOhJcs9Nw==",
+      "dev": true,
+      "dependencies": {
+        "@sinonjs/commons": "^2.0.0",
+        "@sinonjs/fake-timers": "^10.0.2",
+        "@sinonjs/text-encoding": "^0.7.1",
+        "just-extend": "^4.0.2",
+        "path-to-regexp": "^1.7.0"
+      }
+    },
+    "node_modules/nise/node_modules/@sinonjs/commons": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz",
+      "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==",
+      "dev": true,
+      "dependencies": {
+        "type-detect": "4.0.8"
+      }
+    },
+    "node_modules/nise/node_modules/@sinonjs/fake-timers": {
+      "version": "10.3.0",
+      "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
+      "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
+      "dev": true,
+      "dependencies": {
+        "@sinonjs/commons": "^3.0.0"
+      }
+    },
+    "node_modules/nise/node_modules/@sinonjs/fake-timers/node_modules/@sinonjs/commons": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz",
+      "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==",
+      "dev": true,
+      "dependencies": {
+        "type-detect": "4.0.8"
+      }
+    },
+    "node_modules/node-domexception": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
+      "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/jimmywarting"
+        },
+        {
+          "type": "github",
+          "url": "https://paypal.me/jimmywarting"
+        }
+      ],
+      "engines": {
+        "node": ">=10.5.0"
+      }
+    },
+    "node_modules/node-fetch": {
+      "version": "2.7.0",
+      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+      "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+      "dev": true,
+      "dependencies": {
+        "whatwg-url": "^5.0.0"
+      },
+      "engines": {
+        "node": "4.x || >=6.0.0"
+      },
+      "peerDependencies": {
+        "encoding": "^0.1.0"
+      },
+      "peerDependenciesMeta": {
+        "encoding": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/node-fetch/node_modules/tr46": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+      "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+      "dev": true
+    },
+    "node_modules/node-fetch/node_modules/webidl-conversions": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+      "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+      "dev": true
+    },
+    "node_modules/node-fetch/node_modules/whatwg-url": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+      "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+      "dev": true,
+      "dependencies": {
+        "tr46": "~0.0.3",
+        "webidl-conversions": "^3.0.0"
+      }
+    },
+    "node_modules/node-forge": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
+      "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
+      "dev": true,
+      "engines": {
+        "node": ">= 6.13.0"
+      }
+    },
+    "node_modules/node-int64": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+      "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
+      "dev": true
+    },
+    "node_modules/node-preload": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz",
+      "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==",
+      "dev": true,
+      "dependencies": {
+        "process-on-spawn": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/node-releases": {
+      "version": "2.0.13",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
+      "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
+      "dev": true
+    },
+    "node_modules/normalize-package-data": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz",
+      "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==",
+      "dev": true,
+      "dependencies": {
+        "hosted-git-info": "^4.0.1",
+        "is-core-module": "^2.5.0",
+        "semver": "^7.3.4",
+        "validate-npm-package-license": "^3.0.1"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/normalize-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/normalize-url": {
+      "version": "4.5.1",
+      "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz",
+      "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/npm-run-path": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+      "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+      "dev": true,
+      "dependencies": {
+        "path-key": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/nwsapi": {
+      "version": "2.2.7",
+      "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz",
+      "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==",
+      "dev": true
+    },
+    "node_modules/nyc": {
+      "version": "14.1.1",
+      "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz",
+      "integrity": "sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==",
+      "dev": true,
+      "dependencies": {
+        "archy": "^1.0.0",
+        "caching-transform": "^3.0.2",
+        "convert-source-map": "^1.6.0",
+        "cp-file": "^6.2.0",
+        "find-cache-dir": "^2.1.0",
+        "find-up": "^3.0.0",
+        "foreground-child": "^1.5.6",
+        "glob": "^7.1.3",
+        "istanbul-lib-coverage": "^2.0.5",
+        "istanbul-lib-hook": "^2.0.7",
+        "istanbul-lib-instrument": "^3.3.0",
+        "istanbul-lib-report": "^2.0.8",
+        "istanbul-lib-source-maps": "^3.0.6",
+        "istanbul-reports": "^2.2.4",
+        "js-yaml": "^3.13.1",
+        "make-dir": "^2.1.0",
+        "merge-source-map": "^1.1.0",
+        "resolve-from": "^4.0.0",
+        "rimraf": "^2.6.3",
+        "signal-exit": "^3.0.2",
+        "spawn-wrap": "^1.4.2",
+        "test-exclude": "^5.2.3",
+        "uuid": "^3.3.2",
+        "yargs": "^13.2.2",
+        "yargs-parser": "^13.0.0"
+      },
+      "bin": {
+        "nyc": "bin/nyc.js"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/nyc/node_modules/ansi-regex": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
+      "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/nyc/node_modules/ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "dev": true,
+      "dependencies": {
+        "color-convert": "^1.9.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/nyc/node_modules/cliui": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
+      "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+      "dev": true,
+      "dependencies": {
+        "string-width": "^3.1.0",
+        "strip-ansi": "^5.2.0",
+        "wrap-ansi": "^5.1.0"
+      }
+    },
+    "node_modules/nyc/node_modules/color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "dev": true,
+      "dependencies": {
+        "color-name": "1.1.3"
+      }
+    },
+    "node_modules/nyc/node_modules/color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+      "dev": true
+    },
+    "node_modules/nyc/node_modules/convert-source-map": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
+      "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
+      "dev": true
+    },
+    "node_modules/nyc/node_modules/cp-file": {
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz",
+      "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==",
+      "dev": true,
+      "dependencies": {
+        "graceful-fs": "^4.1.2",
+        "make-dir": "^2.0.0",
+        "nested-error-stacks": "^2.0.0",
+        "pify": "^4.0.1",
+        "safe-buffer": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/nyc/node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/nyc/node_modules/emoji-regex": {
+      "version": "7.0.3",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+      "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+      "dev": true
+    },
+    "node_modules/nyc/node_modules/find-up": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+      "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+      "dev": true,
+      "dependencies": {
+        "locate-path": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/nyc/node_modules/has-flag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/nyc/node_modules/hosted-git-info": {
+      "version": "2.8.9",
+      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+      "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+      "dev": true
+    },
+    "node_modules/nyc/node_modules/is-fullwidth-code-point": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+      "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/nyc/node_modules/istanbul-lib-coverage": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+      "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/nyc/node_modules/istanbul-lib-instrument": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz",
+      "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/generator": "^7.4.0",
+        "@babel/parser": "^7.4.3",
+        "@babel/template": "^7.4.0",
+        "@babel/traverse": "^7.4.3",
+        "@babel/types": "^7.4.0",
+        "istanbul-lib-coverage": "^2.0.5",
+        "semver": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/nyc/node_modules/istanbul-lib-report": {
+      "version": "2.0.8",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz",
+      "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==",
+      "dev": true,
+      "dependencies": {
+        "istanbul-lib-coverage": "^2.0.5",
+        "make-dir": "^2.1.0",
+        "supports-color": "^6.1.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/nyc/node_modules/istanbul-lib-source-maps": {
+      "version": "3.0.6",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz",
+      "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==",
+      "dev": true,
+      "dependencies": {
+        "debug": "^4.1.1",
+        "istanbul-lib-coverage": "^2.0.5",
+        "make-dir": "^2.1.0",
+        "rimraf": "^2.6.3",
+        "source-map": "^0.6.1"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/nyc/node_modules/istanbul-reports": {
+      "version": "2.2.7",
+      "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz",
+      "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==",
+      "dev": true,
+      "dependencies": {
+        "html-escaper": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/nyc/node_modules/load-json-file": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+      "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==",
+      "dev": true,
+      "dependencies": {
+        "graceful-fs": "^4.1.2",
+        "parse-json": "^4.0.0",
+        "pify": "^3.0.0",
+        "strip-bom": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/nyc/node_modules/load-json-file/node_modules/pify": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+      "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/nyc/node_modules/locate-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+      "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+      "dev": true,
+      "dependencies": {
+        "p-locate": "^3.0.0",
+        "path-exists": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/nyc/node_modules/make-dir": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+      "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+      "dev": true,
+      "dependencies": {
+        "pify": "^4.0.1",
+        "semver": "^5.6.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/nyc/node_modules/make-dir/node_modules/semver": {
+      "version": "5.7.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+      "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver"
+      }
+    },
+    "node_modules/nyc/node_modules/ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
+    "node_modules/nyc/node_modules/normalize-package-data": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+      "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+      "dev": true,
+      "dependencies": {
+        "hosted-git-info": "^2.1.4",
+        "resolve": "^1.10.0",
+        "semver": "2 || 3 || 4 || 5",
+        "validate-npm-package-license": "^3.0.1"
+      }
+    },
+    "node_modules/nyc/node_modules/normalize-package-data/node_modules/semver": {
+      "version": "5.7.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+      "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver"
+      }
+    },
+    "node_modules/nyc/node_modules/p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "dev": true,
+      "dependencies": {
+        "p-try": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/nyc/node_modules/p-locate": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+      "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+      "dev": true,
+      "dependencies": {
+        "p-limit": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/nyc/node_modules/parse-json": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+      "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
+      "dev": true,
+      "dependencies": {
+        "error-ex": "^1.3.1",
+        "json-parse-better-errors": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/nyc/node_modules/path-exists": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+      "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/nyc/node_modules/path-type": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+      "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+      "dev": true,
+      "dependencies": {
+        "pify": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/nyc/node_modules/path-type/node_modules/pify": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+      "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/nyc/node_modules/read-pkg": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
+      "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==",
+      "dev": true,
+      "dependencies": {
+        "load-json-file": "^4.0.0",
+        "normalize-package-data": "^2.3.2",
+        "path-type": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/nyc/node_modules/read-pkg-up": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz",
+      "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==",
+      "dev": true,
+      "dependencies": {
+        "find-up": "^3.0.0",
+        "read-pkg": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/nyc/node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/nyc/node_modules/string-width": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+      "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+      "dev": true,
+      "dependencies": {
+        "emoji-regex": "^7.0.1",
+        "is-fullwidth-code-point": "^2.0.0",
+        "strip-ansi": "^5.1.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/nyc/node_modules/strip-ansi": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+      "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+      "dev": true,
+      "dependencies": {
+        "ansi-regex": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/nyc/node_modules/strip-bom": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+      "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/nyc/node_modules/supports-color": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+      "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/nyc/node_modules/test-exclude": {
+      "version": "5.2.3",
+      "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz",
+      "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==",
+      "dev": true,
+      "dependencies": {
+        "glob": "^7.1.3",
+        "minimatch": "^3.0.4",
+        "read-pkg-up": "^4.0.0",
+        "require-main-filename": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/nyc/node_modules/wrap-ansi": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
+      "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^3.2.0",
+        "string-width": "^3.0.0",
+        "strip-ansi": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/nyc/node_modules/y18n": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+      "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
+      "dev": true
+    },
+    "node_modules/nyc/node_modules/yargs": {
+      "version": "13.3.2",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
+      "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
+      "dev": true,
+      "dependencies": {
+        "cliui": "^5.0.0",
+        "find-up": "^3.0.0",
+        "get-caller-file": "^2.0.1",
+        "require-directory": "^2.1.1",
+        "require-main-filename": "^2.0.0",
+        "set-blocking": "^2.0.0",
+        "string-width": "^3.0.0",
+        "which-module": "^2.0.0",
+        "y18n": "^4.0.0",
+        "yargs-parser": "^13.1.2"
+      }
+    },
+    "node_modules/nyc/node_modules/yargs-parser": {
+      "version": "13.1.2",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
+      "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
+      "dev": true,
+      "dependencies": {
+        "camelcase": "^5.0.0",
+        "decamelize": "^1.2.0"
+      }
+    },
+    "node_modules/object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/object-inspect": {
+      "version": "1.13.1",
+      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
+      "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/object-is": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
+      "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.1.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/object-keys": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+      "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/object.assign": {
+      "version": "4.1.4",
+      "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
+      "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.1.4",
+        "has-symbols": "^1.0.3",
+        "object-keys": "^1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/object.entries": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz",
+      "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/object.fromentries": {
+      "version": "2.0.7",
+      "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz",
+      "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/object.groupby": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz",
+      "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1",
+        "get-intrinsic": "^1.2.1"
+      }
+    },
+    "node_modules/object.hasown": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz",
+      "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==",
+      "dev": true,
+      "dependencies": {
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/object.values": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz",
+      "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/on-finished": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+      "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
+      "dev": true,
+      "dependencies": {
+        "ee-first": "1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+      "dev": true,
+      "dependencies": {
+        "wrappy": "1"
+      }
+    },
+    "node_modules/onetime": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+      "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+      "dev": true,
+      "dependencies": {
+        "mimic-fn": "^2.1.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/open": {
+      "version": "6.4.0",
+      "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz",
+      "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==",
+      "dev": true,
+      "dependencies": {
+        "is-wsl": "^1.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/opencollective-postinstall": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
+      "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==",
+      "dev": true,
+      "bin": {
+        "opencollective-postinstall": "index.js"
+      }
+    },
+    "node_modules/opener": {
+      "version": "1.5.2",
+      "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
+      "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
+      "dev": true,
+      "bin": {
+        "opener": "bin/opener-bin.js"
+      }
+    },
+    "node_modules/optionator": {
+      "version": "0.8.3",
+      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
+      "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
+      "dev": true,
+      "dependencies": {
+        "deep-is": "~0.1.3",
+        "fast-levenshtein": "~2.0.6",
+        "levn": "~0.3.0",
+        "prelude-ls": "~1.1.2",
+        "type-check": "~0.3.2",
+        "word-wrap": "~1.2.3"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/opts": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/opts/-/opts-2.0.2.tgz",
+      "integrity": "sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==",
+      "dev": true
+    },
+    "node_modules/os-homedir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+      "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/os-shim": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz",
+      "integrity": "sha512-jd0cvB8qQ5uVt0lvCIexBaROw1KyKm5sbulg2fWOHjETisuCzWyt+eTZKEMs8v6HwzoGs8xik26jg7eCM6pS+A==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4.0"
+      }
+    },
+    "node_modules/own-or": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/own-or/-/own-or-1.0.0.tgz",
+      "integrity": "sha512-NfZr5+Tdf6MB8UI9GLvKRs4cXY8/yB0w3xtt84xFdWy8hkGjn+JFc60VhzS/hFRfbyxFcGYMTjnF4Me+RbbqrA==",
+      "dev": true
+    },
+    "node_modules/own-or-env": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/own-or-env/-/own-or-env-1.0.2.tgz",
+      "integrity": "sha512-NQ7v0fliWtK7Lkb+WdFqe6ky9XAzYmlkXthQrBbzlYbmFKoAYbDDcwmOm6q8kOuwSRXW8bdL5ORksploUJmWgw==",
+      "dev": true,
+      "dependencies": {
+        "own-or": "^1.0.0"
+      }
+    },
+    "node_modules/p-cancelable": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz",
+      "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/p-event": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz",
+      "integrity": "sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==",
+      "dev": true,
+      "dependencies": {
+        "p-timeout": "^3.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/p-finally": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+      "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/p-limit": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+      "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+      "dev": true,
+      "dependencies": {
+        "yocto-queue": "^0.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/p-locate": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+      "dev": true,
+      "dependencies": {
+        "p-limit": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/p-locate/node_modules/p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "dev": true,
+      "dependencies": {
+        "p-try": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/p-map": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz",
+      "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==",
+      "dev": true,
+      "dependencies": {
+        "aggregate-error": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/p-timeout": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz",
+      "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==",
+      "dev": true,
+      "dependencies": {
+        "p-finally": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/p-try": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/package-hash": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz",
+      "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==",
+      "dev": true,
+      "dependencies": {
+        "graceful-fs": "^4.1.15",
+        "hasha": "^3.0.0",
+        "lodash.flattendeep": "^4.4.0",
+        "release-zalgo": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/package-json": {
+      "version": "6.5.0",
+      "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz",
+      "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==",
+      "dev": true,
+      "dependencies": {
+        "got": "^9.6.0",
+        "registry-auth-token": "^4.0.0",
+        "registry-url": "^5.0.0",
+        "semver": "^6.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/package-json/node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/pako": {
+      "version": "1.0.11",
+      "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
+      "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
+      "dev": true
+    },
+    "node_modules/parent-module": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+      "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+      "dev": true,
+      "dependencies": {
+        "callsites": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/parent-require": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/parent-require/-/parent-require-1.0.0.tgz",
+      "integrity": "sha512-2MXDNZC4aXdkkap+rBBMv0lUsfJqvX5/2FiYYnfCnorZt3Pk06/IOR5KeaoghgS2w07MLWgjbsnyaq6PdHn2LQ==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4.0"
+      }
+    },
+    "node_modules/parse-json": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+      "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.0.0",
+        "error-ex": "^1.3.1",
+        "json-parse-even-better-errors": "^2.3.0",
+        "lines-and-columns": "^1.1.6"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/parse5": {
+      "version": "7.1.2",
+      "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
+      "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
+      "dev": true,
+      "dependencies": {
+        "entities": "^4.4.0"
+      },
+      "funding": {
+        "url": "https://github.com/inikulin/parse5?sponsor=1"
+      }
+    },
+    "node_modules/parseurl": {
+      "version": "1.3.3",
+      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+      "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/path-key": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+      "dev": true
+    },
+    "node_modules/path-to-regexp": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
+      "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
+      "dev": true,
+      "dependencies": {
+        "isarray": "0.0.1"
+      }
+    },
+    "node_modules/path-type": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+      "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/pathval": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
+      "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
+      "dev": true,
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/picocolors": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+      "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+      "dev": true
+    },
+    "node_modules/picomatch": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/pidusage": {
+      "version": "2.0.21",
+      "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-2.0.21.tgz",
+      "integrity": "sha512-cv3xAQos+pugVX+BfXpHsbyz/dLzX+lr44zNMsYiGxUw+kV5sgQCIcLd1z+0vq+KyC7dJ+/ts2PsfgWfSC3WXA==",
+      "dev": true,
+      "dependencies": {
+        "safe-buffer": "^5.2.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/pify": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+      "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/pirates": {
+      "version": "4.0.6",
+      "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
+      "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/pkg-conf": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz",
+      "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==",
+      "dev": true,
+      "dependencies": {
+        "find-up": "^3.0.0",
+        "load-json-file": "^5.2.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/pkg-conf/node_modules/find-up": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+      "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+      "dev": true,
+      "dependencies": {
+        "locate-path": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/pkg-conf/node_modules/locate-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+      "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+      "dev": true,
+      "dependencies": {
+        "p-locate": "^3.0.0",
+        "path-exists": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/pkg-conf/node_modules/p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "dev": true,
+      "dependencies": {
+        "p-try": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/pkg-conf/node_modules/p-locate": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+      "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+      "dev": true,
+      "dependencies": {
+        "p-limit": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/pkg-conf/node_modules/path-exists": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+      "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/pkg-dir": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+      "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+      "dev": true,
+      "dependencies": {
+        "find-up": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/plur": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/plur/-/plur-4.0.0.tgz",
+      "integrity": "sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg==",
+      "dev": true,
+      "dependencies": {
+        "irregular-plurals": "^3.2.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/pre-commit": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/pre-commit/-/pre-commit-1.2.2.tgz",
+      "integrity": "sha512-qokTiqxD6GjODy5ETAIgzsRgnBWWQHQH2ghy86PU7mIn/wuWeTwF3otyNQZxWBwVn8XNr8Tdzj/QfUXpH+gRZA==",
+      "dev": true,
+      "hasInstallScript": true,
+      "dependencies": {
+        "cross-spawn": "^5.0.1",
+        "spawn-sync": "^1.0.15",
+        "which": "1.2.x"
+      }
+    },
+    "node_modules/pre-commit/node_modules/cross-spawn": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+      "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==",
+      "dev": true,
+      "dependencies": {
+        "lru-cache": "^4.0.1",
+        "shebang-command": "^1.2.0",
+        "which": "^1.2.9"
+      }
+    },
+    "node_modules/pre-commit/node_modules/lru-cache": {
+      "version": "4.1.5",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+      "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+      "dev": true,
+      "dependencies": {
+        "pseudomap": "^1.0.2",
+        "yallist": "^2.1.2"
+      }
+    },
+    "node_modules/pre-commit/node_modules/shebang-command": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+      "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
+      "dev": true,
+      "dependencies": {
+        "shebang-regex": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/pre-commit/node_modules/shebang-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+      "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/pre-commit/node_modules/which": {
+      "version": "1.2.14",
+      "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz",
+      "integrity": "sha512-16uPglFkRPzgiUXYMi1Jf8Z5EzN1iB4V0ZtMXcHZnwsBtQhhHeCqoWw7tsUY42hJGNDWtUsVLTjakIa5BgAxCw==",
+      "dev": true,
+      "dependencies": {
+        "isexe": "^2.0.0"
+      },
+      "bin": {
+        "which": "bin/which"
+      }
+    },
+    "node_modules/pre-commit/node_modules/yallist": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+      "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==",
+      "dev": true
+    },
+    "node_modules/prelude-ls": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+      "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/prepend-http": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
+      "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/pretty-format": {
+      "version": "29.7.0",
+      "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+      "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+      "dev": true,
+      "dependencies": {
+        "@jest/schemas": "^29.6.3",
+        "ansi-styles": "^5.0.0",
+        "react-is": "^18.0.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/pretty-format/node_modules/ansi-styles": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+      "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/prismjs": {
+      "version": "1.29.0",
+      "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz",
+      "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/process-nextick-args": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+      "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+      "dev": true
+    },
+    "node_modules/process-on-spawn": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz",
+      "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==",
+      "dev": true,
+      "dependencies": {
+        "fromentries": "^1.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/prompts": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+      "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+      "dev": true,
+      "dependencies": {
+        "kleur": "^3.0.3",
+        "sisteransi": "^1.0.5"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/prop-types": {
+      "version": "15.8.1",
+      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+      "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+      "dev": true,
+      "dependencies": {
+        "loose-envify": "^1.4.0",
+        "object-assign": "^4.1.1",
+        "react-is": "^16.13.1"
+      }
+    },
+    "node_modules/prop-types/node_modules/react-is": {
+      "version": "16.13.1",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+      "dev": true
+    },
+    "node_modules/proxy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/proxy/-/proxy-1.0.2.tgz",
+      "integrity": "sha512-KNac2ueWRpjbUh77OAFPZuNdfEqNynm9DD4xHT14CccGpW8wKZwEkN0yjlb7X9G9Z9F55N0Q+1z+WfgAhwYdzQ==",
+      "dev": true,
+      "dependencies": {
+        "args": "5.0.1",
+        "basic-auth-parser": "0.0.2",
+        "debug": "^4.1.1"
+      },
+      "bin": {
+        "proxy": "bin/proxy.js"
+      }
+    },
+    "node_modules/proxy/node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/proxy/node_modules/ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
+    "node_modules/proxyquire": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-2.1.3.tgz",
+      "integrity": "sha512-BQWfCqYM+QINd+yawJz23tbBM40VIGXOdDw3X344KcclI/gtBbdWF6SlQ4nK/bYhF9d27KYug9WzljHC6B9Ysg==",
+      "dev": true,
+      "dependencies": {
+        "fill-keys": "^1.0.2",
+        "module-not-found-error": "^1.0.1",
+        "resolve": "^1.11.1"
+      }
+    },
+    "node_modules/pseudomap": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+      "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==",
+      "dev": true
+    },
+    "node_modules/psl": {
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
+      "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==",
+      "dev": true
+    },
+    "node_modules/pump": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+      "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+      "dev": true,
+      "dependencies": {
+        "end-of-stream": "^1.1.0",
+        "once": "^1.3.1"
+      }
+    },
+    "node_modules/punycode": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
+      "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/pupa": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz",
+      "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==",
+      "dev": true,
+      "dependencies": {
+        "escape-goat": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/pure-rand": {
+      "version": "6.0.4",
+      "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz",
+      "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "individual",
+          "url": "https://github.com/sponsors/dubzzz"
+        },
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/fast-check"
+        }
+      ]
+    },
+    "node_modules/querystringify": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
+      "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
+      "dev": true
+    },
+    "node_modules/queue-microtask": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/quick-lru": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz",
+      "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/randombytes": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+      "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+      "dev": true,
+      "dependencies": {
+        "safe-buffer": "^5.1.0"
+      }
+    },
+    "node_modules/range-parser": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+      "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/rc": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+      "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+      "dev": true,
+      "dependencies": {
+        "deep-extend": "^0.6.0",
+        "ini": "~1.3.0",
+        "minimist": "^1.2.0",
+        "strip-json-comments": "~2.0.1"
+      },
+      "bin": {
+        "rc": "cli.js"
+      }
+    },
+    "node_modules/rc/node_modules/strip-json-comments": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+      "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/react-is": {
+      "version": "18.2.0",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
+      "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
+      "dev": true
+    },
+    "node_modules/read-pkg": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
+      "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
+      "dev": true,
+      "dependencies": {
+        "@types/normalize-package-data": "^2.4.0",
+        "normalize-package-data": "^2.5.0",
+        "parse-json": "^5.0.0",
+        "type-fest": "^0.6.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/read-pkg-up": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
+      "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
+      "dev": true,
+      "dependencies": {
+        "find-up": "^4.1.0",
+        "read-pkg": "^5.2.0",
+        "type-fest": "^0.8.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/read-pkg-up/node_modules/type-fest": {
+      "version": "0.8.1",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+      "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/read-pkg/node_modules/hosted-git-info": {
+      "version": "2.8.9",
+      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+      "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+      "dev": true
+    },
+    "node_modules/read-pkg/node_modules/normalize-package-data": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+      "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+      "dev": true,
+      "dependencies": {
+        "hosted-git-info": "^2.1.4",
+        "resolve": "^1.10.0",
+        "semver": "2 || 3 || 4 || 5",
+        "validate-npm-package-license": "^3.0.1"
+      }
+    },
+    "node_modules/read-pkg/node_modules/semver": {
+      "version": "5.7.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+      "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver"
+      }
+    },
+    "node_modules/read-pkg/node_modules/type-fest": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
+      "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/readable-stream": {
+      "version": "3.6.2",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+      "dev": true,
+      "dependencies": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/readdirp": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+      "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+      "dev": true,
+      "dependencies": {
+        "picomatch": "^2.2.1"
+      },
+      "engines": {
+        "node": ">=8.10.0"
+      }
+    },
+    "node_modules/redent": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
+      "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==",
+      "dev": true,
+      "dependencies": {
+        "indent-string": "^4.0.0",
+        "strip-indent": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/reflect-metadata": {
+      "version": "0.1.13",
+      "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
+      "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==",
+      "dev": true
+    },
+    "node_modules/reflect.getprototypeof": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz",
+      "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1",
+        "get-intrinsic": "^1.2.1",
+        "globalthis": "^1.0.3",
+        "which-builtin-type": "^1.1.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/regenerator-runtime": {
+      "version": "0.14.0",
+      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
+      "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==",
+      "dev": true
+    },
+    "node_modules/regexp.prototype.flags": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz",
+      "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "set-function-name": "^2.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/regexpp": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+      "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/mysticatea"
+      }
+    },
+    "node_modules/registry-auth-token": {
+      "version": "4.2.2",
+      "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz",
+      "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==",
+      "dev": true,
+      "dependencies": {
+        "rc": "1.2.8"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/registry-url": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz",
+      "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==",
+      "dev": true,
+      "dependencies": {
+        "rc": "^1.2.8"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/release-zalgo": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz",
+      "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==",
+      "dev": true,
+      "dependencies": {
+        "es6-error": "^4.0.1"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/require-directory": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+      "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/require-from-string": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+      "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/require-main-filename": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+      "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+      "dev": true
+    },
+    "node_modules/requires-port": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+      "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
+      "dev": true
+    },
+    "node_modules/resolve": {
+      "version": "1.22.8",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+      "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+      "dev": true,
+      "dependencies": {
+        "is-core-module": "^2.13.0",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
+      },
+      "bin": {
+        "resolve": "bin/resolve"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/resolve-cwd": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+      "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+      "dev": true,
+      "dependencies": {
+        "resolve-from": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/resolve-cwd/node_modules/resolve-from": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+      "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/resolve-from": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+      "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/resolve-pathname": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz",
+      "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==",
+      "dev": true
+    },
+    "node_modules/resolve.exports": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz",
+      "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/responselike": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
+      "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==",
+      "dev": true,
+      "dependencies": {
+        "lowercase-keys": "^1.0.0"
+      }
+    },
+    "node_modules/reusify": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+      "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+      "dev": true,
+      "engines": {
+        "iojs": ">=1.0.0",
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/rimraf": {
+      "version": "2.7.1",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+      "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+      "dev": true,
+      "dependencies": {
+        "glob": "^7.1.3"
+      },
+      "bin": {
+        "rimraf": "bin.js"
+      }
+    },
+    "node_modules/rrweb-cssom": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz",
+      "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==",
+      "dev": true
+    },
+    "node_modules/run-parallel": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "dependencies": {
+        "queue-microtask": "^1.2.2"
+      }
+    },
+    "node_modules/rxjs": {
+      "version": "7.8.1",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
+      "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
+      "dev": true,
+      "dependencies": {
+        "tslib": "^2.1.0"
+      }
+    },
+    "node_modules/safe-array-concat": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz",
+      "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "get-intrinsic": "^1.2.1",
+        "has-symbols": "^1.0.3",
+        "isarray": "^2.0.5"
+      },
+      "engines": {
+        "node": ">=0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/safe-array-concat/node_modules/isarray": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+      "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+      "dev": true
+    },
+    "node_modules/safe-buffer": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/safe-regex-test": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
+      "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "get-intrinsic": "^1.1.3",
+        "is-regex": "^1.1.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+      "dev": true
+    },
+    "node_modules/saxes": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
+      "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
+      "dev": true,
+      "dependencies": {
+        "xmlchars": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=v12.22.7"
+      }
+    },
+    "node_modules/selfsigned": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz",
+      "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==",
+      "dev": true,
+      "dependencies": {
+        "node-forge": "^1"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/semver": {
+      "version": "7.5.4",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+      "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+      "dev": true,
+      "dependencies": {
+        "lru-cache": "^6.0.0"
+      },
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/semver-diff": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz",
+      "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==",
+      "dev": true,
+      "dependencies": {
+        "semver": "^6.3.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/semver-diff/node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/semver/node_modules/lru-cache": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+      "dev": true,
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/semver/node_modules/yallist": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+      "dev": true
+    },
+    "node_modules/send": {
+      "version": "0.18.0",
+      "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
+      "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
+      "dev": true,
+      "dependencies": {
+        "debug": "2.6.9",
+        "depd": "2.0.0",
+        "destroy": "1.2.0",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "etag": "~1.8.1",
+        "fresh": "0.5.2",
+        "http-errors": "2.0.0",
+        "mime": "1.6.0",
+        "ms": "2.1.3",
+        "on-finished": "2.4.1",
+        "range-parser": "~1.2.1",
+        "statuses": "2.0.1"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/send/node_modules/ms": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+      "dev": true
+    },
+    "node_modules/send/node_modules/on-finished": {
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+      "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+      "dev": true,
+      "dependencies": {
+        "ee-first": "1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/send/node_modules/statuses": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+      "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/serialize-javascript": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
+      "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
+      "dev": true,
+      "dependencies": {
+        "randombytes": "^2.1.0"
+      }
+    },
+    "node_modules/serve-static": {
+      "version": "1.15.0",
+      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
+      "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
+      "dev": true,
+      "dependencies": {
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "parseurl": "~1.3.3",
+        "send": "0.18.0"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/set-blocking": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+      "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
+      "dev": true
+    },
+    "node_modules/set-function-length": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz",
+      "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==",
+      "dev": true,
+      "dependencies": {
+        "define-data-property": "^1.1.1",
+        "get-intrinsic": "^1.2.1",
+        "gopd": "^1.0.1",
+        "has-property-descriptors": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/set-function-name": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz",
+      "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==",
+      "dev": true,
+      "dependencies": {
+        "define-data-property": "^1.0.1",
+        "functions-have-names": "^1.2.3",
+        "has-property-descriptors": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/setprototypeof": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+      "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+      "dev": true
+    },
+    "node_modules/shebang-command": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+      "dev": true,
+      "dependencies": {
+        "shebang-regex": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/shebang-regex": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/shell-quote": {
+      "version": "1.8.1",
+      "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz",
+      "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/side-channel": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+      "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.0",
+        "get-intrinsic": "^1.0.2",
+        "object-inspect": "^1.9.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/signal-exit": {
+      "version": "3.0.7",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+      "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+      "dev": true
+    },
+    "node_modules/sinon": {
+      "version": "16.1.3",
+      "resolved": "https://registry.npmjs.org/sinon/-/sinon-16.1.3.tgz",
+      "integrity": "sha512-mjnWWeyxcAf9nC0bXcPmiDut+oE8HYridTNzBbF98AYVLmWwGRp2ISEpyhYflG1ifILT+eNn3BmKUJPxjXUPlA==",
+      "dev": true,
+      "dependencies": {
+        "@sinonjs/commons": "^3.0.0",
+        "@sinonjs/fake-timers": "^10.3.0",
+        "@sinonjs/samsam": "^8.0.0",
+        "diff": "^5.1.0",
+        "nise": "^5.1.4",
+        "supports-color": "^7.2.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/sinon"
+      }
+    },
+    "node_modules/sinon/node_modules/@sinonjs/fake-timers": {
+      "version": "10.3.0",
+      "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
+      "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
+      "dev": true,
+      "dependencies": {
+        "@sinonjs/commons": "^3.0.0"
+      }
+    },
+    "node_modules/sinon/node_modules/diff": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz",
+      "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.3.1"
+      }
+    },
+    "node_modules/sinon/node_modules/supports-color": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/sisteransi": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+      "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+      "dev": true
+    },
+    "node_modules/slash": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+      "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/slice-ansi": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+      "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^4.0.0",
+        "astral-regex": "^2.0.0",
+        "is-fullwidth-code-point": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+      }
+    },
+    "node_modules/snazzy": {
+      "version": "9.0.0",
+      "resolved": "https://registry.npmjs.org/snazzy/-/snazzy-9.0.0.tgz",
+      "integrity": "sha512-8QZmJb11OiYaUP90Nnjqcj/LEpO8CLgChnP87Wqjv5tNB4djwHaz27VO2usSRR0NmViapeGW04p0aWAMhxxLXg==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "dependencies": {
+        "chalk": "^4.1.0",
+        "inherits": "^2.0.4",
+        "minimist": "^1.2.5",
+        "readable-stream": "^3.6.0",
+        "standard-json": "^1.1.0",
+        "strip-ansi": "^6.0.0",
+        "text-table": "^0.2.0"
+      },
+      "bin": {
+        "snazzy": "bin/cmd.js"
+      }
+    },
+    "node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/source-map-support": {
+      "version": "0.5.13",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
+      "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
+      "dev": true,
+      "dependencies": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      }
+    },
+    "node_modules/spawn-command": {
+      "version": "0.0.2",
+      "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz",
+      "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==",
+      "dev": true
+    },
+    "node_modules/spawn-sync": {
+      "version": "1.0.15",
+      "resolved": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz",
+      "integrity": "sha512-9DWBgrgYZzNghseho0JOuh+5fg9u6QWhAWa51QC7+U5rCheZ/j1DrEZnyE0RBBRqZ9uEXGPgSSM0nky6burpVw==",
+      "dev": true,
+      "hasInstallScript": true,
+      "dependencies": {
+        "concat-stream": "^1.4.7",
+        "os-shim": "^0.1.2"
+      }
+    },
+    "node_modules/spawn-wrap": {
+      "version": "1.4.3",
+      "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz",
+      "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==",
+      "dev": true,
+      "dependencies": {
+        "foreground-child": "^1.5.6",
+        "mkdirp": "^0.5.0",
+        "os-homedir": "^1.0.1",
+        "rimraf": "^2.6.2",
+        "signal-exit": "^3.0.2",
+        "which": "^1.3.0"
+      }
+    },
+    "node_modules/spawn-wrap/node_modules/which": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+      "dev": true,
+      "dependencies": {
+        "isexe": "^2.0.0"
+      },
+      "bin": {
+        "which": "bin/which"
+      }
+    },
+    "node_modules/spdx-correct": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
+      "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
+      "dev": true,
+      "dependencies": {
+        "spdx-expression-parse": "^3.0.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "node_modules/spdx-exceptions": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+      "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+      "dev": true
+    },
+    "node_modules/spdx-expression-parse": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+      "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+      "dev": true,
+      "dependencies": {
+        "spdx-exceptions": "^2.1.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "node_modules/spdx-license-ids": {
+      "version": "3.0.16",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz",
+      "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==",
+      "dev": true
+    },
+    "node_modules/sprintf-js": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+      "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+      "dev": true
+    },
+    "node_modules/stack-utils": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
+      "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
+      "dev": true,
+      "dependencies": {
+        "escape-string-regexp": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/stack-utils/node_modules/escape-string-regexp": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+      "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/standard": {
+      "version": "17.1.0",
+      "resolved": "https://registry.npmjs.org/standard/-/standard-17.1.0.tgz",
+      "integrity": "sha512-jaDqlNSzLtWYW4lvQmU0EnxWMUGQiwHasZl5ZEIwx3S/ijZDjZOzs1y1QqKwKs5vqnFpGtizo4NOYX2s0Voq/g==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "dependencies": {
+        "eslint": "^8.41.0",
+        "eslint-config-standard": "17.1.0",
+        "eslint-config-standard-jsx": "^11.0.0",
+        "eslint-plugin-import": "^2.27.5",
+        "eslint-plugin-n": "^15.7.0",
+        "eslint-plugin-promise": "^6.1.1",
+        "eslint-plugin-react": "^7.32.2",
+        "standard-engine": "^15.0.0",
+        "version-guard": "^1.1.1"
+      },
+      "bin": {
+        "standard": "bin/cmd.cjs"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      }
+    },
+    "node_modules/standard-engine": {
+      "version": "15.1.0",
+      "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-15.1.0.tgz",
+      "integrity": "sha512-VHysfoyxFu/ukT+9v49d4BRXIokFRZuH3z1VRxzFArZdjSCFpro6rEIU3ji7e4AoAtuSfKBkiOmsrDqKW5ZSRw==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "dependencies": {
+        "get-stdin": "^8.0.0",
+        "minimist": "^1.2.6",
+        "pkg-conf": "^3.1.0",
+        "xdg-basedir": "^4.0.0"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      }
+    },
+    "node_modules/standard-json": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/standard-json/-/standard-json-1.1.0.tgz",
+      "integrity": "sha512-nkonX+n5g3pyVBvJZmvRlFtT/7JyLbNh4CtrYC3Qfxihgs8PKX52f6ONKQXORStuBWJ5PI83EUrNXme7LKfiTQ==",
+      "dev": true,
+      "dependencies": {
+        "concat-stream": "^2.0.0"
+      },
+      "bin": {
+        "standard-json": "bin.js"
+      }
+    },
+    "node_modules/standard-json/node_modules/concat-stream": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
+      "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
+      "dev": true,
+      "engines": [
+        "node >= 6.0"
+      ],
+      "dependencies": {
+        "buffer-from": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^3.0.2",
+        "typedarray": "^0.0.6"
+      }
+    },
+    "node_modules/statuses": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+      "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/string_decoder": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+      "dev": true,
+      "dependencies": {
+        "safe-buffer": "~5.2.0"
+      }
+    },
+    "node_modules/string-length": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
+      "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
+      "dev": true,
+      "dependencies": {
+        "char-regex": "^1.0.2",
+        "strip-ansi": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/string-width": {
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+      "dev": true,
+      "dependencies": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/string.prototype.matchall": {
+      "version": "4.0.10",
+      "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz",
+      "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1",
+        "get-intrinsic": "^1.2.1",
+        "has-symbols": "^1.0.3",
+        "internal-slot": "^1.0.5",
+        "regexp.prototype.flags": "^1.5.0",
+        "set-function-name": "^2.0.0",
+        "side-channel": "^1.0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/string.prototype.trim": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz",
+      "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/string.prototype.trimend": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz",
+      "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/string.prototype.trimstart": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz",
+      "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.2.0",
+        "es-abstract": "^1.22.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/strip-ansi": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+      "dev": true,
+      "dependencies": {
+        "ansi-regex": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/strip-bom": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+      "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/strip-final-newline": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+      "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/strip-indent": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
+      "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
+      "dev": true,
+      "dependencies": {
+        "min-indent": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/strip-json-comments": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+      "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/supports-color": {
+      "version": "8.1.1",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+      "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/supports-color?sponsor=1"
+      }
+    },
+    "node_modules/supports-hyperlinks": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz",
+      "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^4.0.0",
+        "supports-color": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/supports-hyperlinks/node_modules/supports-color": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/supports-preserve-symlinks-flag": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/symbol-tree": {
+      "version": "3.2.4",
+      "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
+      "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
+      "dev": true
+    },
+    "node_modules/table": {
+      "version": "6.8.1",
+      "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz",
+      "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==",
+      "dev": true,
+      "dependencies": {
+        "ajv": "^8.0.1",
+        "lodash.truncate": "^4.4.2",
+        "slice-ansi": "^4.0.0",
+        "string-width": "^4.2.3",
+        "strip-ansi": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=10.0.0"
+      }
+    },
+    "node_modules/table/node_modules/ajv": {
+      "version": "8.12.0",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+      "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+      "dev": true,
+      "dependencies": {
+        "fast-deep-equal": "^3.1.1",
+        "json-schema-traverse": "^1.0.0",
+        "require-from-string": "^2.0.2",
+        "uri-js": "^4.2.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/table/node_modules/json-schema-traverse": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+      "dev": true
+    },
+    "node_modules/tap": {
+      "version": "16.3.9",
+      "resolved": "https://registry.npmjs.org/tap/-/tap-16.3.9.tgz",
+      "integrity": "sha512-KKmu12hRJhb/kGvVV/UKBOJ90sNoGbcXF0E+VmNqej1DqaCmZHyOXR8R7E66qg2Wor33XhSHGrku5MPYWSRNWw==",
+      "bundleDependencies": [
+        "ink",
+        "treport",
+        "@types/react",
+        "@isaacs/import-jsx",
+        "react"
+      ],
+      "dev": true,
+      "dependencies": {
+        "@isaacs/import-jsx": "^4.0.1",
+        "@types/react": "^17.0.52",
+        "chokidar": "^3.3.0",
+        "findit": "^2.0.0",
+        "foreground-child": "^2.0.0",
+        "fs-exists-cached": "^1.0.0",
+        "glob": "^7.2.3",
+        "ink": "^3.2.0",
+        "isexe": "^2.0.0",
+        "istanbul-lib-processinfo": "^2.0.3",
+        "jackspeak": "^1.4.2",
+        "libtap": "^1.4.0",
+        "minipass": "^3.3.4",
+        "mkdirp": "^1.0.4",
+        "nyc": "^15.1.0",
+        "opener": "^1.5.1",
+        "react": "^17.0.2",
+        "rimraf": "^3.0.0",
+        "signal-exit": "^3.0.6",
+        "source-map-support": "^0.5.16",
+        "tap-mocha-reporter": "^5.0.3",
+        "tap-parser": "^11.0.2",
+        "tap-yaml": "^1.0.2",
+        "tcompare": "^5.0.7",
+        "treport": "^3.0.4",
+        "which": "^2.0.2"
+      },
+      "bin": {
+        "tap": "bin/run.js"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      },
+      "peerDependencies": {
+        "coveralls": "^3.1.1",
+        "flow-remove-types": ">=2.112.0",
+        "ts-node": ">=8.5.2",
+        "typescript": ">=3.7.2"
+      },
+      "peerDependenciesMeta": {
+        "coveralls": {
+          "optional": true
+        },
+        "flow-remove-types": {
+          "optional": true
+        },
+        "ts-node": {
+          "optional": true
+        },
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/tap-mocha-reporter": {
+      "version": "5.0.4",
+      "resolved": "https://registry.npmjs.org/tap-mocha-reporter/-/tap-mocha-reporter-5.0.4.tgz",
+      "integrity": "sha512-J+YMO8B7lq1O6Zxd/jeuG27vJ+Y4tLiRMKPSb7KR6FVh86k3Rq1TwYc2GKPyIjCbzzdMdReh3Vfz9L5cg1Z2Bw==",
+      "dev": true,
+      "dependencies": {
+        "color-support": "^1.1.0",
+        "debug": "^4.1.1",
+        "diff": "^4.0.1",
+        "escape-string-regexp": "^2.0.0",
+        "glob": "^7.0.5",
+        "tap-parser": "^11.0.0",
+        "tap-yaml": "^1.0.0",
+        "unicode-length": "^2.0.2"
+      },
+      "bin": {
+        "tap-mocha-reporter": "index.js"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/tap-mocha-reporter/node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/tap-mocha-reporter/node_modules/diff": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+      "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.3.1"
+      }
+    },
+    "node_modules/tap-mocha-reporter/node_modules/escape-string-regexp": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+      "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap-mocha-reporter/node_modules/ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
+    "node_modules/tap-parser": {
+      "version": "11.0.2",
+      "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-11.0.2.tgz",
+      "integrity": "sha512-6qGlC956rcORw+fg7Fv1iCRAY8/bU9UabUAhs3mXRH6eRmVZcNPLheSXCYaVaYeSwx5xa/1HXZb1537YSvwDZg==",
+      "dev": true,
+      "dependencies": {
+        "events-to-array": "^1.0.1",
+        "minipass": "^3.1.6",
+        "tap-yaml": "^1.0.0"
+      },
+      "bin": {
+        "tap-parser": "bin/cmd.js"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/tap-yaml": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/tap-yaml/-/tap-yaml-1.0.2.tgz",
+      "integrity": "sha512-GegASpuqBnRNdT1U+yuUPZ8rEU64pL35WPBpCISWwff4dErS2/438barz7WFJl4Nzh3Y05tfPidZnH+GaV1wMg==",
+      "dev": true,
+      "dependencies": {
+        "yaml": "^1.10.2"
+      }
+    },
+    "node_modules/tap/node_modules/@ampproject/remapping": {
+      "version": "2.2.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.0",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/code-frame": {
+      "version": "7.22.5",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/highlight": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/compat-data": {
+      "version": "7.22.9",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/core": {
+      "version": "7.22.9",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@ampproject/remapping": "^2.2.0",
+        "@babel/code-frame": "^7.22.5",
+        "@babel/generator": "^7.22.9",
+        "@babel/helper-compilation-targets": "^7.22.9",
+        "@babel/helper-module-transforms": "^7.22.9",
+        "@babel/helpers": "^7.22.6",
+        "@babel/parser": "^7.22.7",
+        "@babel/template": "^7.22.5",
+        "@babel/traverse": "^7.22.8",
+        "@babel/types": "^7.22.5",
+        "convert-source-map": "^1.7.0",
+        "debug": "^4.1.0",
+        "gensync": "^1.0.0-beta.2",
+        "json5": "^2.2.2",
+        "semver": "^6.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/babel"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/generator": {
+      "version": "7.22.9",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/types": "^7.22.5",
+        "@jridgewell/gen-mapping": "^0.3.2",
+        "@jridgewell/trace-mapping": "^0.3.17",
+        "jsesc": "^2.5.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/helper-annotate-as-pure": {
+      "version": "7.22.5",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/helper-compilation-targets": {
+      "version": "7.22.9",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/compat-data": "^7.22.9",
+        "@babel/helper-validator-option": "^7.22.5",
+        "browserslist": "^4.21.9",
+        "lru-cache": "^5.1.1",
+        "semver": "^6.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/helper-environment-visitor": {
+      "version": "7.22.5",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/helper-function-name": {
+      "version": "7.22.5",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/template": "^7.22.5",
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/helper-hoist-variables": {
+      "version": "7.22.5",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/helper-module-imports": {
+      "version": "7.22.5",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/helper-module-transforms": {
+      "version": "7.22.9",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-environment-visitor": "^7.22.5",
+        "@babel/helper-module-imports": "^7.22.5",
+        "@babel/helper-simple-access": "^7.22.5",
+        "@babel/helper-split-export-declaration": "^7.22.6",
+        "@babel/helper-validator-identifier": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/helper-plugin-utils": {
+      "version": "7.22.5",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/helper-simple-access": {
+      "version": "7.22.5",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/helper-split-export-declaration": {
+      "version": "7.22.6",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/helper-string-parser": {
+      "version": "7.22.5",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/helper-validator-identifier": {
+      "version": "7.22.5",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/helper-validator-option": {
+      "version": "7.22.5",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/helpers": {
+      "version": "7.22.6",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/template": "^7.22.5",
+        "@babel/traverse": "^7.22.6",
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/highlight": {
+      "version": "7.22.5",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-validator-identifier": "^7.22.5",
+        "chalk": "^2.0.0",
+        "js-tokens": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/parser": {
+      "version": "7.22.7",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/plugin-proposal-object-rest-spread": {
+      "version": "7.20.7",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/compat-data": "^7.20.5",
+        "@babel/helper-compilation-targets": "^7.20.7",
+        "@babel/helper-plugin-utils": "^7.20.2",
+        "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+        "@babel/plugin-transform-parameters": "^7.20.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/plugin-syntax-jsx": {
+      "version": "7.22.5",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/plugin-syntax-object-rest-spread": {
+      "version": "7.8.3",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/plugin-transform-destructuring": {
+      "version": "7.22.5",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/plugin-transform-parameters": {
+      "version": "7.22.5",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/plugin-transform-react-jsx": {
+      "version": "7.22.5",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-annotate-as-pure": "^7.22.5",
+        "@babel/helper-module-imports": "^7.22.5",
+        "@babel/helper-plugin-utils": "^7.22.5",
+        "@babel/plugin-syntax-jsx": "^7.22.5",
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/template": {
+      "version": "7.22.5",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/code-frame": "^7.22.5",
+        "@babel/parser": "^7.22.5",
+        "@babel/types": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/traverse": {
+      "version": "7.22.8",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/code-frame": "^7.22.5",
+        "@babel/generator": "^7.22.7",
+        "@babel/helper-environment-visitor": "^7.22.5",
+        "@babel/helper-function-name": "^7.22.5",
+        "@babel/helper-hoist-variables": "^7.22.5",
+        "@babel/helper-split-export-declaration": "^7.22.6",
+        "@babel/parser": "^7.22.7",
+        "@babel/types": "^7.22.5",
+        "debug": "^4.1.0",
+        "globals": "^11.1.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/tap/node_modules/@babel/types": {
+      "version": "7.22.5",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-string-parser": "^7.22.5",
+        "@babel/helper-validator-identifier": "^7.22.5",
+        "to-fast-properties": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/tap/node_modules/@isaacs/import-jsx": {
+      "version": "4.0.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/core": "^7.5.5",
+        "@babel/plugin-proposal-object-rest-spread": "^7.5.5",
+        "@babel/plugin-transform-destructuring": "^7.5.0",
+        "@babel/plugin-transform-react-jsx": "^7.3.0",
+        "caller-path": "^3.0.1",
+        "find-cache-dir": "^3.2.0",
+        "make-dir": "^3.0.2",
+        "resolve-from": "^3.0.0",
+        "rimraf": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/tap/node_modules/@jridgewell/gen-mapping": {
+      "version": "0.3.3",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/set-array": "^1.0.1",
+        "@jridgewell/sourcemap-codec": "^1.4.10",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/tap/node_modules/@jridgewell/resolve-uri": {
+      "version": "3.1.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/tap/node_modules/@jridgewell/set-array": {
+      "version": "1.1.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/tap/node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.4.15",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/@jridgewell/trace-mapping": {
+      "version": "0.3.18",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/resolve-uri": "3.1.0",
+        "@jridgewell/sourcemap-codec": "1.4.14"
+      }
+    },
+    "node_modules/tap/node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.4.14",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/@types/prop-types": {
+      "version": "15.7.5",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/@types/react": {
+      "version": "17.0.62",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/prop-types": "*",
+        "@types/scheduler": "*",
+        "csstype": "^3.0.2"
+      }
+    },
+    "node_modules/tap/node_modules/@types/scheduler": {
+      "version": "0.16.3",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/@types/yoga-layout": {
+      "version": "1.9.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/ansi-escapes": {
+      "version": "4.3.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "type-fest": "^0.21.3"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/tap/node_modules/ansi-escapes/node_modules/type-fest": {
+      "version": "0.21.3",
+      "dev": true,
+      "inBundle": true,
+      "license": "(MIT OR CC0-1.0)",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/tap/node_modules/ansi-regex": {
+      "version": "5.0.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/ansi-styles": {
+      "version": "3.2.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "color-convert": "^1.9.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/tap/node_modules/ansicolors": {
+      "version": "0.3.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/append-transform": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz",
+      "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==",
+      "dev": true,
+      "dependencies": {
+        "default-require-extensions": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/astral-regex": {
+      "version": "2.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/auto-bind": {
+      "version": "4.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/tap/node_modules/balanced-match": {
+      "version": "1.0.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/tap/node_modules/browserslist": {
+      "version": "4.21.9",
+      "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/browserslist"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "caniuse-lite": "^1.0.30001503",
+        "electron-to-chromium": "^1.4.431",
+        "node-releases": "^2.0.12",
+        "update-browserslist-db": "^1.0.11"
+      },
+      "bin": {
+        "browserslist": "cli.js"
+      },
+      "engines": {
+        "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+      }
+    },
+    "node_modules/tap/node_modules/caching-transform": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz",
+      "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==",
+      "dev": true,
+      "dependencies": {
+        "hasha": "^5.0.0",
+        "make-dir": "^3.0.0",
+        "package-hash": "^4.0.0",
+        "write-file-atomic": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/caller-callsite": {
+      "version": "4.1.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "callsites": "^3.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/caller-path": {
+      "version": "3.0.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "caller-callsite": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/callsites": {
+      "version": "3.1.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/tap/node_modules/caniuse-lite": {
+      "version": "1.0.30001517",
+      "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "inBundle": true,
+      "license": "CC-BY-4.0"
+    },
+    "node_modules/tap/node_modules/cardinal": {
+      "version": "2.1.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "ansicolors": "~0.3.2",
+        "redeyed": "~2.1.0"
+      },
+      "bin": {
+        "cdl": "bin/cdl.js"
+      }
+    },
+    "node_modules/tap/node_modules/chalk": {
+      "version": "2.4.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/tap/node_modules/ci-info": {
+      "version": "2.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/cli-boxes": {
+      "version": "2.2.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/tap/node_modules/cli-cursor": {
+      "version": "3.1.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "restore-cursor": "^3.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/cli-truncate": {
+      "version": "2.1.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "slice-ansi": "^3.0.0",
+        "string-width": "^4.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/tap/node_modules/cliui": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+      "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+      "dev": true,
+      "dependencies": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.0",
+        "wrap-ansi": "^6.2.0"
+      }
+    },
+    "node_modules/tap/node_modules/code-excerpt": {
+      "version": "3.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "convert-to-spaces": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/tap/node_modules/color-convert": {
+      "version": "1.9.3",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "color-name": "1.1.3"
+      }
+    },
+    "node_modules/tap/node_modules/color-name": {
+      "version": "1.1.3",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/commondir": {
+      "version": "1.0.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/concat-map": {
+      "version": "0.0.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/convert-source-map": {
+      "version": "1.9.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/convert-to-spaces": {
+      "version": "1.0.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 4"
+      }
+    },
+    "node_modules/tap/node_modules/csstype": {
+      "version": "3.1.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/debug": {
+      "version": "4.3.4",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/tap/node_modules/default-require-extensions": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz",
+      "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==",
+      "dev": true,
+      "dependencies": {
+        "strip-bom": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/tap/node_modules/electron-to-chromium": {
+      "version": "1.4.477",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC"
+    },
+    "node_modules/tap/node_modules/emoji-regex": {
+      "version": "8.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/escalade": {
+      "version": "3.1.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/tap/node_modules/escape-string-regexp": {
+      "version": "1.0.5",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.8.0"
+      }
+    },
+    "node_modules/tap/node_modules/esprima": {
+      "version": "4.0.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "BSD-2-Clause",
+      "bin": {
+        "esparse": "bin/esparse.js",
+        "esvalidate": "bin/esvalidate.js"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/tap/node_modules/events-to-array": {
+      "version": "1.1.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC"
+    },
+    "node_modules/tap/node_modules/find-cache-dir": {
+      "version": "3.3.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "commondir": "^1.0.1",
+        "make-dir": "^3.0.2",
+        "pkg-dir": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/avajs/find-cache-dir?sponsor=1"
+      }
+    },
+    "node_modules/tap/node_modules/find-up": {
+      "version": "4.1.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/foreground-child": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz",
+      "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==",
+      "dev": true,
+      "dependencies": {
+        "cross-spawn": "^7.0.0",
+        "signal-exit": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=8.0.0"
+      }
+    },
+    "node_modules/tap/node_modules/fs.realpath": {
+      "version": "1.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC"
+    },
+    "node_modules/tap/node_modules/gensync": {
+      "version": "1.0.0-beta.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/tap/node_modules/glob": {
+      "version": "7.2.3",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC",
+      "dependencies": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.1.1",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      },
+      "engines": {
+        "node": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/tap/node_modules/globals": {
+      "version": "11.12.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/tap/node_modules/has-flag": {
+      "version": "3.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/tap/node_modules/hasha": {
+      "version": "5.2.2",
+      "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz",
+      "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==",
+      "dev": true,
+      "dependencies": {
+        "is-stream": "^2.0.0",
+        "type-fest": "^0.8.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/tap/node_modules/hasha/node_modules/type-fest": {
+      "version": "0.8.1",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+      "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/indent-string": {
+      "version": "4.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/inflight": {
+      "version": "1.0.6",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC",
+      "dependencies": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "node_modules/tap/node_modules/inherits": {
+      "version": "2.0.4",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC"
+    },
+    "node_modules/tap/node_modules/ink": {
+      "version": "3.2.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "ansi-escapes": "^4.2.1",
+        "auto-bind": "4.0.0",
+        "chalk": "^4.1.0",
+        "cli-boxes": "^2.2.0",
+        "cli-cursor": "^3.1.0",
+        "cli-truncate": "^2.1.0",
+        "code-excerpt": "^3.0.0",
+        "indent-string": "^4.0.0",
+        "is-ci": "^2.0.0",
+        "lodash": "^4.17.20",
+        "patch-console": "^1.0.0",
+        "react-devtools-core": "^4.19.1",
+        "react-reconciler": "^0.26.2",
+        "scheduler": "^0.20.2",
+        "signal-exit": "^3.0.2",
+        "slice-ansi": "^3.0.0",
+        "stack-utils": "^2.0.2",
+        "string-width": "^4.2.2",
+        "type-fest": "^0.12.0",
+        "widest-line": "^3.1.0",
+        "wrap-ansi": "^6.2.0",
+        "ws": "^7.5.5",
+        "yoga-layout-prebuilt": "^1.9.6"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "peerDependencies": {
+        "@types/react": ">=16.8.0",
+        "react": ">=16.8.0"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/tap/node_modules/ink/node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/tap/node_modules/ink/node_modules/chalk": {
+      "version": "4.1.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
+      }
+    },
+    "node_modules/tap/node_modules/ink/node_modules/color-convert": {
+      "version": "2.0.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/tap/node_modules/ink/node_modules/color-name": {
+      "version": "1.1.4",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/ink/node_modules/has-flag": {
+      "version": "4.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/ink/node_modules/supports-color": {
+      "version": "7.2.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/is-ci": {
+      "version": "2.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "ci-info": "^2.0.0"
+      },
+      "bin": {
+        "is-ci": "bin.js"
+      }
+    },
+    "node_modules/tap/node_modules/is-fullwidth-code-point": {
+      "version": "3.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/istanbul-lib-hook": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz",
+      "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==",
+      "dev": true,
+      "dependencies": {
+        "append-transform": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/istanbul-lib-instrument": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz",
+      "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/core": "^7.7.5",
+        "@istanbuljs/schema": "^0.1.2",
+        "istanbul-lib-coverage": "^3.0.0",
+        "semver": "^6.3.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/js-tokens": {
+      "version": "4.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/jsesc": {
+      "version": "2.5.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "bin": {
+        "jsesc": "bin/jsesc"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/tap/node_modules/json5": {
+      "version": "2.2.3",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "bin": {
+        "json5": "lib/cli.js"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/tap/node_modules/locate-path": {
+      "version": "5.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "p-locate": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/lodash": {
+      "version": "4.17.21",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/loose-envify": {
+      "version": "1.4.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "js-tokens": "^3.0.0 || ^4.0.0"
+      },
+      "bin": {
+        "loose-envify": "cli.js"
+      }
+    },
+    "node_modules/tap/node_modules/lru-cache": {
+      "version": "5.1.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC",
+      "dependencies": {
+        "yallist": "^3.0.2"
+      }
+    },
+    "node_modules/tap/node_modules/make-dir": {
+      "version": "3.1.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "semver": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/tap/node_modules/mimic-fn": {
+      "version": "2.1.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/tap/node_modules/minimatch": {
+      "version": "3.1.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC",
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/tap/node_modules/minipass": {
+      "version": "3.3.6",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC",
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/minipass/node_modules/yallist": {
+      "version": "4.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC"
+    },
+    "node_modules/tap/node_modules/mkdirp": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+      "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+      "dev": true,
+      "bin": {
+        "mkdirp": "bin/cmd.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/tap/node_modules/ms": {
+      "version": "2.1.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/node-releases": {
+      "version": "2.0.13",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/nyc": {
+      "version": "15.1.0",
+      "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz",
+      "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==",
+      "dev": true,
+      "dependencies": {
+        "@istanbuljs/load-nyc-config": "^1.0.0",
+        "@istanbuljs/schema": "^0.1.2",
+        "caching-transform": "^4.0.0",
+        "convert-source-map": "^1.7.0",
+        "decamelize": "^1.2.0",
+        "find-cache-dir": "^3.2.0",
+        "find-up": "^4.1.0",
+        "foreground-child": "^2.0.0",
+        "get-package-type": "^0.1.0",
+        "glob": "^7.1.6",
+        "istanbul-lib-coverage": "^3.0.0",
+        "istanbul-lib-hook": "^3.0.0",
+        "istanbul-lib-instrument": "^4.0.0",
+        "istanbul-lib-processinfo": "^2.0.2",
+        "istanbul-lib-report": "^3.0.0",
+        "istanbul-lib-source-maps": "^4.0.0",
+        "istanbul-reports": "^3.0.2",
+        "make-dir": "^3.0.0",
+        "node-preload": "^0.2.1",
+        "p-map": "^3.0.0",
+        "process-on-spawn": "^1.0.0",
+        "resolve-from": "^5.0.0",
+        "rimraf": "^3.0.0",
+        "signal-exit": "^3.0.2",
+        "spawn-wrap": "^2.0.0",
+        "test-exclude": "^6.0.0",
+        "yargs": "^15.0.2"
+      },
+      "bin": {
+        "nyc": "bin/nyc.js"
+      },
+      "engines": {
+        "node": ">=8.9"
+      }
+    },
+    "node_modules/tap/node_modules/nyc/node_modules/resolve-from": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+      "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/object-assign": {
+      "version": "4.1.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/tap/node_modules/once": {
+      "version": "1.4.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC",
+      "dependencies": {
+        "wrappy": "1"
+      }
+    },
+    "node_modules/tap/node_modules/onetime": {
+      "version": "5.1.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "mimic-fn": "^2.1.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/tap/node_modules/p-limit": {
+      "version": "2.3.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "p-try": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/tap/node_modules/p-locate": {
+      "version": "4.1.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "p-limit": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/p-try": {
+      "version": "2.2.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/tap/node_modules/package-hash": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz",
+      "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==",
+      "dev": true,
+      "dependencies": {
+        "graceful-fs": "^4.1.15",
+        "hasha": "^5.0.0",
+        "lodash.flattendeep": "^4.4.0",
+        "release-zalgo": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/patch-console": {
+      "version": "1.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/tap/node_modules/path-exists": {
+      "version": "4.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/path-is-absolute": {
+      "version": "1.0.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/tap/node_modules/picocolors": {
+      "version": "1.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC"
+    },
+    "node_modules/tap/node_modules/pkg-dir": {
+      "version": "4.2.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "find-up": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/punycode": {
+      "version": "2.3.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/tap/node_modules/react": {
+      "version": "17.0.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "loose-envify": "^1.1.0",
+        "object-assign": "^4.1.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/tap/node_modules/react-devtools-core": {
+      "version": "4.28.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "shell-quote": "^1.6.1",
+        "ws": "^7"
+      }
+    },
+    "node_modules/tap/node_modules/react-reconciler": {
+      "version": "0.26.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "loose-envify": "^1.1.0",
+        "object-assign": "^4.1.1",
+        "scheduler": "^0.20.2"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      },
+      "peerDependencies": {
+        "react": "^17.0.2"
+      }
+    },
+    "node_modules/tap/node_modules/redeyed": {
+      "version": "2.1.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "esprima": "~4.0.0"
+      }
+    },
+    "node_modules/tap/node_modules/resolve-from": {
+      "version": "3.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/tap/node_modules/restore-cursor": {
+      "version": "3.1.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "onetime": "^5.1.0",
+        "signal-exit": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/rimraf": {
+      "version": "3.0.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC",
+      "dependencies": {
+        "glob": "^7.1.3"
+      },
+      "bin": {
+        "rimraf": "bin.js"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/tap/node_modules/scheduler": {
+      "version": "0.20.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "loose-envify": "^1.1.0",
+        "object-assign": "^4.1.1"
+      }
+    },
+    "node_modules/tap/node_modules/semver": {
+      "version": "6.3.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC",
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/tap/node_modules/shell-quote": {
+      "version": "1.8.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/tap/node_modules/signal-exit": {
+      "version": "3.0.7",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC"
+    },
+    "node_modules/tap/node_modules/slice-ansi": {
+      "version": "3.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "ansi-styles": "^4.0.0",
+        "astral-regex": "^2.0.0",
+        "is-fullwidth-code-point": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/slice-ansi/node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/tap/node_modules/slice-ansi/node_modules/color-convert": {
+      "version": "2.0.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/tap/node_modules/slice-ansi/node_modules/color-name": {
+      "version": "1.1.4",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/source-map-support": {
+      "version": "0.5.21",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+      "dev": true,
+      "dependencies": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      }
+    },
+    "node_modules/tap/node_modules/spawn-wrap": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz",
+      "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==",
+      "dev": true,
+      "dependencies": {
+        "foreground-child": "^2.0.0",
+        "is-windows": "^1.0.2",
+        "make-dir": "^3.0.0",
+        "rimraf": "^3.0.0",
+        "signal-exit": "^3.0.2",
+        "which": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/stack-utils": {
+      "version": "2.0.6",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "escape-string-regexp": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/tap/node_modules/stack-utils/node_modules/escape-string-regexp": {
+      "version": "2.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/string-width": {
+      "version": "4.2.3",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/strip-ansi": {
+      "version": "6.0.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "ansi-regex": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/supports-color": {
+      "version": "5.5.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "has-flag": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/tap/node_modules/tap-parser": {
+      "version": "11.0.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "events-to-array": "^1.0.1",
+        "minipass": "^3.1.6",
+        "tap-yaml": "^1.0.0"
+      },
+      "bin": {
+        "tap-parser": "bin/cmd.js"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/tap/node_modules/tap-yaml": {
+      "version": "1.0.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC",
+      "dependencies": {
+        "yaml": "^1.10.2"
+      }
+    },
+    "node_modules/tap/node_modules/to-fast-properties": {
+      "version": "2.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/tap/node_modules/treport": {
+      "version": "3.0.4",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC",
+      "dependencies": {
+        "@isaacs/import-jsx": "^4.0.1",
+        "cardinal": "^2.1.1",
+        "chalk": "^3.0.0",
+        "ink": "^3.2.0",
+        "ms": "^2.1.2",
+        "tap-parser": "^11.0.0",
+        "tap-yaml": "^1.0.0",
+        "unicode-length": "^2.0.2"
+      },
+      "peerDependencies": {
+        "react": "^17.0.2"
+      }
+    },
+    "node_modules/tap/node_modules/treport/node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/tap/node_modules/treport/node_modules/chalk": {
+      "version": "3.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/treport/node_modules/color-convert": {
+      "version": "2.0.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/tap/node_modules/treport/node_modules/color-name": {
+      "version": "1.1.4",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/treport/node_modules/has-flag": {
+      "version": "4.0.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/treport/node_modules/supports-color": {
+      "version": "7.2.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/type-fest": {
+      "version": "0.12.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "(MIT OR CC0-1.0)",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/tap/node_modules/unicode-length": {
+      "version": "2.1.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "punycode": "^2.0.0"
+      }
+    },
+    "node_modules/tap/node_modules/update-browserslist-db": {
+      "version": "1.0.11",
+      "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/browserslist"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "escalade": "^3.1.1",
+        "picocolors": "^1.0.0"
+      },
+      "bin": {
+        "update-browserslist-db": "cli.js"
+      },
+      "peerDependencies": {
+        "browserslist": ">= 4.21.0"
+      }
+    },
+    "node_modules/tap/node_modules/widest-line": {
+      "version": "3.1.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "string-width": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/wrap-ansi": {
+      "version": "6.2.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "ansi-styles": "^4.0.0",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/wrap-ansi/node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/tap/node_modules/wrap-ansi/node_modules/color-convert": {
+      "version": "2.0.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/tap/node_modules/wrap-ansi/node_modules/color-name": {
+      "version": "1.1.4",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT"
+    },
+    "node_modules/tap/node_modules/wrappy": {
+      "version": "1.0.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC"
+    },
+    "node_modules/tap/node_modules/write-file-atomic": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
+      "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
+      "dev": true,
+      "dependencies": {
+        "imurmurhash": "^0.1.4",
+        "is-typedarray": "^1.0.0",
+        "signal-exit": "^3.0.2",
+        "typedarray-to-buffer": "^3.1.5"
+      }
+    },
+    "node_modules/tap/node_modules/ws": {
+      "version": "7.5.9",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8.3.0"
+      },
+      "peerDependencies": {
+        "bufferutil": "^4.0.1",
+        "utf-8-validate": "^5.0.2"
+      },
+      "peerDependenciesMeta": {
+        "bufferutil": {
+          "optional": true
+        },
+        "utf-8-validate": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/tap/node_modules/y18n": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+      "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
+      "dev": true
+    },
+    "node_modules/tap/node_modules/yallist": {
+      "version": "3.1.1",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC"
+    },
+    "node_modules/tap/node_modules/yaml": {
+      "version": "1.10.2",
+      "dev": true,
+      "inBundle": true,
+      "license": "ISC",
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/tap/node_modules/yargs": {
+      "version": "15.4.1",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+      "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+      "dev": true,
+      "dependencies": {
+        "cliui": "^6.0.0",
+        "decamelize": "^1.2.0",
+        "find-up": "^4.1.0",
+        "get-caller-file": "^2.0.1",
+        "require-directory": "^2.1.1",
+        "require-main-filename": "^2.0.0",
+        "set-blocking": "^2.0.0",
+        "string-width": "^4.2.0",
+        "which-module": "^2.0.0",
+        "y18n": "^4.0.0",
+        "yargs-parser": "^18.1.2"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tap/node_modules/yargs-parser": {
+      "version": "18.1.3",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+      "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+      "dev": true,
+      "dependencies": {
+        "camelcase": "^5.0.0",
+        "decamelize": "^1.2.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/tap/node_modules/yoga-layout-prebuilt": {
+      "version": "1.10.0",
+      "dev": true,
+      "inBundle": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/yoga-layout": "1.9.2"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tcompare": {
+      "version": "5.0.7",
+      "resolved": "https://registry.npmjs.org/tcompare/-/tcompare-5.0.7.tgz",
+      "integrity": "sha512-d9iddt6YYGgyxJw5bjsN7UJUO1kGOtjSlNy/4PoGYAjQS5pAT/hzIoLf1bZCw+uUxRmZJh7Yy1aA7xKVRT9B4w==",
+      "dev": true,
+      "dependencies": {
+        "diff": "^4.0.2"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/tcompare/node_modules/diff": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+      "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.3.1"
+      }
+    },
+    "node_modules/term-size": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz",
+      "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/test-exclude": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+      "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+      "dev": true,
+      "dependencies": {
+        "@istanbuljs/schema": "^0.1.2",
+        "glob": "^7.1.4",
+        "minimatch": "^3.0.4"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/text-table": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+      "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+      "dev": true
+    },
+    "node_modules/tinydate": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/tinydate/-/tinydate-1.3.0.tgz",
+      "integrity": "sha512-7cR8rLy2QhYHpsBDBVYnnWXm8uRTr38RoZakFSW7Bs7PzfMPNZthuMLkwqZv7MTu8lhQ91cOFYS5a7iFj2oR3w==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/tmpl": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
+      "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
+      "dev": true
+    },
+    "node_modules/to-fast-properties": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+      "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/to-readable-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz",
+      "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "dev": true,
+      "dependencies": {
+        "is-number": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=8.0"
+      }
+    },
+    "node_modules/toidentifier": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+      "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.6"
+      }
+    },
+    "node_modules/tough-cookie": {
+      "version": "4.1.3",
+      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz",
+      "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==",
+      "dev": true,
+      "dependencies": {
+        "psl": "^1.1.33",
+        "punycode": "^2.1.1",
+        "universalify": "^0.2.0",
+        "url-parse": "^1.5.3"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/tough-cookie/node_modules/universalify": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
+      "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 4.0.0"
+      }
+    },
+    "node_modules/tr46": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz",
+      "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==",
+      "dev": true,
+      "dependencies": {
+        "punycode": "^2.3.0"
+      },
+      "engines": {
+        "node": ">=14"
+      }
+    },
+    "node_modules/tree-kill": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
+      "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
+      "dev": true,
+      "bin": {
+        "tree-kill": "cli.js"
+      }
+    },
+    "node_modules/trim-newlines": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz",
+      "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/trivial-deferred": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/trivial-deferred/-/trivial-deferred-1.1.2.tgz",
+      "integrity": "sha512-vDPiDBC3hyP6O4JrJYMImW3nl3c03Tsj9fEXc7Qc/XKa1O7gf5ZtFfIR/E0dun9SnDHdwjna1Z2rSzYgqpxh/g==",
+      "dev": true,
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/tsconfig-paths": {
+      "version": "3.14.2",
+      "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz",
+      "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==",
+      "dev": true,
+      "dependencies": {
+        "@types/json5": "^0.0.29",
+        "json5": "^1.0.2",
+        "minimist": "^1.2.6",
+        "strip-bom": "^3.0.0"
+      }
+    },
+    "node_modules/tsconfig-paths/node_modules/json5": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+      "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+      "dev": true,
+      "dependencies": {
+        "minimist": "^1.2.0"
+      },
+      "bin": {
+        "json5": "lib/cli.js"
+      }
+    },
+    "node_modules/tsconfig-paths/node_modules/strip-bom": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+      "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/tsd": {
+      "version": "0.29.0",
+      "resolved": "https://registry.npmjs.org/tsd/-/tsd-0.29.0.tgz",
+      "integrity": "sha512-5B7jbTj+XLMg6rb9sXRBGwzv7h8KJlGOkTHxY63eWpZJiQ5vJbXEjL0u7JkIxwi5EsrRE1kRVUWmy6buK/ii8A==",
+      "dev": true,
+      "dependencies": {
+        "@tsd/typescript": "~5.2.2",
+        "eslint-formatter-pretty": "^4.1.0",
+        "globby": "^11.0.1",
+        "jest-diff": "^29.0.3",
+        "meow": "^9.0.0",
+        "path-exists": "^4.0.0",
+        "read-pkg-up": "^7.0.0"
+      },
+      "bin": {
+        "tsd": "dist/cli.js"
+      },
+      "engines": {
+        "node": ">=14.16"
+      }
+    },
+    "node_modules/tslib": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+      "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
+      "dev": true
+    },
+    "node_modules/tweezer.js": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/tweezer.js/-/tweezer.js-1.5.0.tgz",
+      "integrity": "sha512-aSiJz7rGWNAQq7hjMK9ZYDuEawXupcCWgl3woQQSoDP2Oh8O4srWb/uO1PzzHIsrPEOqrjJ2sUb9FERfzuBabQ==",
+      "dev": true
+    },
+    "node_modules/type-check": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+      "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==",
+      "dev": true,
+      "dependencies": {
+        "prelude-ls": "~1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/type-detect": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+      "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/type-fest": {
+      "version": "0.21.3",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+      "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/typed-array-buffer": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz",
+      "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "get-intrinsic": "^1.2.1",
+        "is-typed-array": "^1.1.10"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/typed-array-byte-length": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz",
+      "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "for-each": "^0.3.3",
+        "has-proto": "^1.0.1",
+        "is-typed-array": "^1.1.10"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/typed-array-byte-offset": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz",
+      "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==",
+      "dev": true,
+      "dependencies": {
+        "available-typed-arrays": "^1.0.5",
+        "call-bind": "^1.0.2",
+        "for-each": "^0.3.3",
+        "has-proto": "^1.0.1",
+        "is-typed-array": "^1.1.10"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/typed-array-length": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
+      "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "for-each": "^0.3.3",
+        "is-typed-array": "^1.1.9"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/typedarray": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+      "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
+      "dev": true
+    },
+    "node_modules/typedarray-to-buffer": {
+      "version": "3.1.5",
+      "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
+      "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
+      "dev": true,
+      "dependencies": {
+        "is-typedarray": "^1.0.0"
+      }
+    },
+    "node_modules/typescript": {
+      "version": "5.2.2",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
+      "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
+      "dev": true,
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=14.17"
+      }
+    },
+    "node_modules/unbox-primitive": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+      "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "has-bigints": "^1.0.2",
+        "has-symbols": "^1.0.3",
+        "which-boxed-primitive": "^1.0.2"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/unicode-length": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/unicode-length/-/unicode-length-2.1.0.tgz",
+      "integrity": "sha512-4bV582zTV9Q02RXBxSUMiuN/KHo5w4aTojuKTNT96DIKps/SIawFp7cS5Mu25VuY1AioGXrmYyzKZUzh8OqoUw==",
+      "dev": true,
+      "dependencies": {
+        "punycode": "^2.0.0"
+      }
+    },
+    "node_modules/unique-string": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz",
+      "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==",
+      "dev": true,
+      "dependencies": {
+        "crypto-random-string": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/universalify": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+      "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 4.0.0"
+      }
+    },
+    "node_modules/unpipe": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+      "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/update-browserslist-db": {
+      "version": "1.0.13",
+      "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
+      "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/browserslist"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "dependencies": {
+        "escalade": "^3.1.1",
+        "picocolors": "^1.0.0"
+      },
+      "bin": {
+        "update-browserslist-db": "cli.js"
+      },
+      "peerDependencies": {
+        "browserslist": ">= 4.21.0"
+      }
+    },
+    "node_modules/update-notifier": {
+      "version": "4.1.3",
+      "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz",
+      "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==",
+      "dev": true,
+      "dependencies": {
+        "boxen": "^4.2.0",
+        "chalk": "^3.0.0",
+        "configstore": "^5.0.1",
+        "has-yarn": "^2.1.0",
+        "import-lazy": "^2.1.0",
+        "is-ci": "^2.0.0",
+        "is-installed-globally": "^0.3.1",
+        "is-npm": "^4.0.0",
+        "is-yarn-global": "^0.3.0",
+        "latest-version": "^5.0.0",
+        "pupa": "^2.0.1",
+        "semver-diff": "^3.1.1",
+        "xdg-basedir": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/yeoman/update-notifier?sponsor=1"
+      }
+    },
+    "node_modules/update-notifier/node_modules/chalk": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+      "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/update-notifier/node_modules/supports-color": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/uri-js": {
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+      "dev": true,
+      "dependencies": {
+        "punycode": "^2.1.0"
+      }
+    },
+    "node_modules/url-parse": {
+      "version": "1.5.10",
+      "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
+      "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
+      "dev": true,
+      "dependencies": {
+        "querystringify": "^2.1.1",
+        "requires-port": "^1.0.0"
+      }
+    },
+    "node_modules/url-parse-lax": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz",
+      "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==",
+      "dev": true,
+      "dependencies": {
+        "prepend-http": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+      "dev": true
+    },
+    "node_modules/utils-merge": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+      "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4.0"
+      }
+    },
+    "node_modules/uuid": {
+      "version": "3.4.0",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+      "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+      "deprecated": "Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.",
+      "dev": true,
+      "bin": {
+        "uuid": "bin/uuid"
+      }
+    },
+    "node_modules/v8-to-istanbul": {
+      "version": "9.1.3",
+      "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz",
+      "integrity": "sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/trace-mapping": "^0.3.12",
+        "@types/istanbul-lib-coverage": "^2.0.1",
+        "convert-source-map": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10.12.0"
+      }
+    },
+    "node_modules/validate-npm-package-license": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+      "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+      "dev": true,
+      "dependencies": {
+        "spdx-correct": "^3.0.0",
+        "spdx-expression-parse": "^3.0.0"
+      }
+    },
+    "node_modules/version-guard": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/version-guard/-/version-guard-1.1.1.tgz",
+      "integrity": "sha512-MGQLX89UxmYHgDvcXyjBI0cbmoW+t/dANDppNPrno64rYr8nH4SHSuElQuSYdXGEs0mUzdQe1BY+FhVPNsAmJQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.48"
+      }
+    },
+    "node_modules/w3c-xmlserializer": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
+      "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==",
+      "dev": true,
+      "dependencies": {
+        "xml-name-validator": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=14"
+      }
+    },
+    "node_modules/wait-on": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-7.0.1.tgz",
+      "integrity": "sha512-9AnJE9qTjRQOlTZIldAaf/da2eW0eSRSgcqq85mXQja/DW3MriHxkpODDSUEg+Gri/rKEcXUZHe+cevvYItaog==",
+      "dev": true,
+      "dependencies": {
+        "axios": "^0.27.2",
+        "joi": "^17.7.0",
+        "lodash": "^4.17.21",
+        "minimist": "^1.2.7",
+        "rxjs": "^7.8.0"
+      },
+      "bin": {
+        "wait-on": "bin/wait-on"
+      },
+      "engines": {
+        "node": ">=12.0.0"
+      }
+    },
+    "node_modules/walker": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
+      "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+      "dev": true,
+      "dependencies": {
+        "makeerror": "1.0.12"
+      }
+    },
+    "node_modules/web-streams-polyfill": {
+      "version": "4.0.0-beta.3",
+      "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz",
+      "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==",
+      "dev": true,
+      "engines": {
+        "node": ">= 14"
+      }
+    },
+    "node_modules/webidl-conversions": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
+      "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/whatwg-encoding": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
+      "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==",
+      "dev": true,
+      "dependencies": {
+        "iconv-lite": "0.6.3"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/whatwg-mimetype": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz",
+      "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/whatwg-url": {
+      "version": "12.0.1",
+      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-12.0.1.tgz",
+      "integrity": "sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==",
+      "dev": true,
+      "dependencies": {
+        "tr46": "^4.1.1",
+        "webidl-conversions": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=14"
+      }
+    },
+    "node_modules/which": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+      "dev": true,
+      "dependencies": {
+        "isexe": "^2.0.0"
+      },
+      "bin": {
+        "node-which": "bin/node-which"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/which-boxed-primitive": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+      "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+      "dev": true,
+      "dependencies": {
+        "is-bigint": "^1.0.1",
+        "is-boolean-object": "^1.1.0",
+        "is-number-object": "^1.0.4",
+        "is-string": "^1.0.5",
+        "is-symbol": "^1.0.3"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/which-builtin-type": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz",
+      "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==",
+      "dev": true,
+      "dependencies": {
+        "function.prototype.name": "^1.1.5",
+        "has-tostringtag": "^1.0.0",
+        "is-async-function": "^2.0.0",
+        "is-date-object": "^1.0.5",
+        "is-finalizationregistry": "^1.0.2",
+        "is-generator-function": "^1.0.10",
+        "is-regex": "^1.1.4",
+        "is-weakref": "^1.0.2",
+        "isarray": "^2.0.5",
+        "which-boxed-primitive": "^1.0.2",
+        "which-collection": "^1.0.1",
+        "which-typed-array": "^1.1.9"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/which-builtin-type/node_modules/isarray": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+      "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+      "dev": true
+    },
+    "node_modules/which-collection": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz",
+      "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==",
+      "dev": true,
+      "dependencies": {
+        "is-map": "^2.0.1",
+        "is-set": "^2.0.1",
+        "is-weakmap": "^2.0.1",
+        "is-weakset": "^2.0.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/which-module": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
+      "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
+      "dev": true
+    },
+    "node_modules/which-typed-array": {
+      "version": "1.1.13",
+      "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz",
+      "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==",
+      "dev": true,
+      "dependencies": {
+        "available-typed-arrays": "^1.0.5",
+        "call-bind": "^1.0.4",
+        "for-each": "^0.3.3",
+        "gopd": "^1.0.1",
+        "has-tostringtag": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/widest-line": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
+      "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==",
+      "dev": true,
+      "dependencies": {
+        "string-width": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/word-wrap": {
+      "version": "1.2.5",
+      "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+      "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/workerpool": {
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
+      "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
+      "dev": true
+    },
+    "node_modules/wrap-ansi": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+      "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^4.0.0",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+      }
+    },
+    "node_modules/wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+      "dev": true
+    },
+    "node_modules/write-file-atomic": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+      "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
+      "dev": true,
+      "dependencies": {
+        "imurmurhash": "^0.1.4",
+        "signal-exit": "^3.0.7"
+      },
+      "engines": {
+        "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+      }
+    },
+    "node_modules/ws": {
+      "version": "8.14.2",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz",
+      "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==",
+      "dev": true,
+      "engines": {
+        "node": ">=10.0.0"
+      },
+      "peerDependencies": {
+        "bufferutil": "^4.0.1",
+        "utf-8-validate": ">=5.0.2"
+      },
+      "peerDependenciesMeta": {
+        "bufferutil": {
+          "optional": true
+        },
+        "utf-8-validate": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/xdg-basedir": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz",
+      "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/xml-name-validator": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
+      "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/xmlchars": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
+      "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
+      "dev": true
+    },
+    "node_modules/y18n": {
+      "version": "5.0.8",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+      "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/yallist": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+      "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+      "dev": true
+    },
+    "node_modules/yaml": {
+      "version": "1.10.2",
+      "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+      "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/yargonaut": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/yargonaut/-/yargonaut-1.1.4.tgz",
+      "integrity": "sha512-rHgFmbgXAAzl+1nngqOcwEljqHGG9uUZoPjsdZEs1w5JW9RXYzrSvH/u70C1JE5qFi0qjsdhnUX/dJRpWqitSA==",
+      "dev": true,
+      "dependencies": {
+        "chalk": "^1.1.1",
+        "figlet": "^1.1.1",
+        "parent-require": "^1.0.0"
+      }
+    },
+    "node_modules/yargonaut/node_modules/ansi-regex": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+      "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/yargonaut/node_modules/ansi-styles": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+      "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/yargonaut/node_modules/chalk": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+      "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^2.2.1",
+        "escape-string-regexp": "^1.0.2",
+        "has-ansi": "^2.0.0",
+        "strip-ansi": "^3.0.0",
+        "supports-color": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/yargonaut/node_modules/escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.8.0"
+      }
+    },
+    "node_modules/yargonaut/node_modules/strip-ansi": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+      "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
+      "dev": true,
+      "dependencies": {
+        "ansi-regex": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/yargonaut/node_modules/supports-color": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+      "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.8.0"
+      }
+    },
+    "node_modules/yargs": {
+      "version": "17.7.2",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+      "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+      "dev": true,
+      "dependencies": {
+        "cliui": "^8.0.1",
+        "escalade": "^3.1.1",
+        "get-caller-file": "^2.0.5",
+        "require-directory": "^2.1.1",
+        "string-width": "^4.2.3",
+        "y18n": "^5.0.5",
+        "yargs-parser": "^21.1.1"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/yargs-parser": {
+      "version": "20.2.4",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
+      "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/yargs-unparser": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
+      "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
+      "dev": true,
+      "dependencies": {
+        "camelcase": "^6.0.0",
+        "decamelize": "^4.0.0",
+        "flat": "^5.0.2",
+        "is-plain-obj": "^2.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/yargs-unparser/node_modules/camelcase": {
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+      "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/yargs-unparser/node_modules/decamelize": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
+      "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/yargs-unparser/node_modules/is-plain-obj": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+      "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/yargs/node_modules/cliui": {
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+      "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+      "dev": true,
+      "dependencies": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.1",
+        "wrap-ansi": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/yargs/node_modules/yargs-parser": {
+      "version": "21.1.1",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+      "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/yocto-queue": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+      "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    }
+  }
+}
diff --git a/deps/undici/src/package.json b/deps/undici/src/package.json
index 67046ad68a3541..31e157de002b20 100644
--- a/deps/undici/src/package.json
+++ b/deps/undici/src/package.json
@@ -1,6 +1,6 @@
 {
   "name": "undici",
-  "version": "5.26.3",
+  "version": "5.26.4",
   "description": "An HTTP/1.1 client, written from scratch for Node.js",
   "homepage": "https://undici.nodejs.org",
   "bugs": {
@@ -67,11 +67,10 @@
     "index-fetch.js",
     "lib",
     "types",
-    "docs",
-    "scripts/esbuild-build.mjs"
+    "docs"
   ],
   "scripts": {
-    "build:node": "node scripts/esbuild-build.mjs",
+    "build:node": "npx esbuild@0.19.4 index-fetch.js --bundle --platform=node --outfile=undici-fetch.js --define:esbuildDetection=1 --keep-names",
     "prebuild:wasm": "node build/wasm.js --prebuild",
     "build:wasm": "node build/wasm.js --docker",
     "lint": "standard | snazzy",
@@ -85,7 +84,7 @@
     "test:tdd": "tap test/*.js test/diagnostics-channel/*.js -w",
     "test:typescript": "node scripts/verifyVersion.js 14 || tsd && tsc --skipLibCheck test/imports/undici-import.ts",
     "test:websocket": "node scripts/verifyVersion.js 18 || tap test/websocket/*.js",
-    "test:wpt": "node scripts/verifyVersion 18 || (node test/wpt/start-fetch.mjs && node test/wpt/start-FileAPI.mjs && node test/wpt/start-mimesniff.mjs && node test/wpt/start-xhr.mjs && node --no-warnings test/wpt/start-websockets.mjs)",
+    "test:wpt": "node scripts/verifyVersion 18 || (node test/wpt/start-fetch.mjs && node test/wpt/start-FileAPI.mjs && node test/wpt/start-mimesniff.mjs && node test/wpt/start-xhr.mjs && node --no-warnings --expose-internals test/wpt/start-websockets.mjs)",
     "coverage": "nyc --reporter=text --reporter=html npm run test",
     "coverage:ci": "nyc --reporter=lcov npm run test",
     "bench": "PORT=3042 concurrently -k -s first npm:bench:server npm:bench:run",
@@ -110,7 +109,6 @@
     "delay": "^5.0.0",
     "dns-packet": "^5.4.0",
     "docsify-cli": "^4.4.3",
-    "esbuild": "^0.19.4",
     "form-data": "^4.0.0",
     "formdata-node": "^4.3.1",
     "https-pem": "^3.0.0",
diff --git a/deps/undici/src/scripts/esbuild-build.mjs b/deps/undici/src/scripts/esbuild-build.mjs
deleted file mode 100644
index ca5886c1a2b861..00000000000000
--- a/deps/undici/src/scripts/esbuild-build.mjs
+++ /dev/null
@@ -1,24 +0,0 @@
-import * as esbuild from 'esbuild'
-import fs from 'node:fs'
-
-const bundle = {
-  name: 'bundle',
-  setup (build) {
-    build.onLoad({ filter: /lib(\/|\\)fetch(\/|\\)index.js/ }, async (args) => {
-      const text = await fs.promises.readFile(args.path, 'utf8')
-
-      return {
-        contents: `var esbuildDetection = 1;${text}`,
-        loader: 'js'
-      }
-    })
-  }
-}
-
-await esbuild.build({
-  entryPoints: ['index-fetch.js'],
-  bundle: true,
-  outfile: 'undici-fetch.js',
-  plugins: [bundle],
-  platform: 'node'
-})
diff --git a/deps/undici/undici.js b/deps/undici/undici.js
index 0c3dc7ebfc149b..068edd28b16ee5 100644
--- a/deps/undici/undici.js
+++ b/deps/undici/undici.js
@@ -1,5 +1,7 @@
 "use strict";
+var __defProp = Object.defineProperty;
 var __getOwnPropNames = Object.getOwnPropertyNames;
+var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
 var __commonJS = (cb, mod) => function __require() {
   return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
 };
@@ -91,6 +93,9 @@ var require_errors = __commonJS({
   "lib/core/errors.js"(exports2, module2) {
     "use strict";
     var UndiciError = class extends Error {
+      static {
+        __name(this, "UndiciError");
+      }
       constructor(message) {
         super(message);
         this.name = "UndiciError";
@@ -98,6 +103,9 @@ var require_errors = __commonJS({
       }
     };
     var ConnectTimeoutError = class _ConnectTimeoutError extends UndiciError {
+      static {
+        __name(this, "ConnectTimeoutError");
+      }
       constructor(message) {
         super(message);
         Error.captureStackTrace(this, _ConnectTimeoutError);
@@ -107,6 +115,9 @@ var require_errors = __commonJS({
       }
     };
     var HeadersTimeoutError = class _HeadersTimeoutError extends UndiciError {
+      static {
+        __name(this, "HeadersTimeoutError");
+      }
       constructor(message) {
         super(message);
         Error.captureStackTrace(this, _HeadersTimeoutError);
@@ -116,6 +127,9 @@ var require_errors = __commonJS({
       }
     };
     var HeadersOverflowError = class _HeadersOverflowError extends UndiciError {
+      static {
+        __name(this, "HeadersOverflowError");
+      }
       constructor(message) {
         super(message);
         Error.captureStackTrace(this, _HeadersOverflowError);
@@ -125,6 +139,9 @@ var require_errors = __commonJS({
       }
     };
     var BodyTimeoutError = class _BodyTimeoutError extends UndiciError {
+      static {
+        __name(this, "BodyTimeoutError");
+      }
       constructor(message) {
         super(message);
         Error.captureStackTrace(this, _BodyTimeoutError);
@@ -134,6 +151,9 @@ var require_errors = __commonJS({
       }
     };
     var ResponseStatusCodeError = class _ResponseStatusCodeError extends UndiciError {
+      static {
+        __name(this, "ResponseStatusCodeError");
+      }
       constructor(message, statusCode, headers, body) {
         super(message);
         Error.captureStackTrace(this, _ResponseStatusCodeError);
@@ -147,6 +167,9 @@ var require_errors = __commonJS({
       }
     };
     var InvalidArgumentError = class _InvalidArgumentError extends UndiciError {
+      static {
+        __name(this, "InvalidArgumentError");
+      }
       constructor(message) {
         super(message);
         Error.captureStackTrace(this, _InvalidArgumentError);
@@ -156,6 +179,9 @@ var require_errors = __commonJS({
       }
     };
     var InvalidReturnValueError = class _InvalidReturnValueError extends UndiciError {
+      static {
+        __name(this, "InvalidReturnValueError");
+      }
       constructor(message) {
         super(message);
         Error.captureStackTrace(this, _InvalidReturnValueError);
@@ -165,6 +191,9 @@ var require_errors = __commonJS({
       }
     };
     var RequestAbortedError = class _RequestAbortedError extends UndiciError {
+      static {
+        __name(this, "RequestAbortedError");
+      }
       constructor(message) {
         super(message);
         Error.captureStackTrace(this, _RequestAbortedError);
@@ -174,6 +203,9 @@ var require_errors = __commonJS({
       }
     };
     var InformationalError = class _InformationalError extends UndiciError {
+      static {
+        __name(this, "InformationalError");
+      }
       constructor(message) {
         super(message);
         Error.captureStackTrace(this, _InformationalError);
@@ -183,6 +215,9 @@ var require_errors = __commonJS({
       }
     };
     var RequestContentLengthMismatchError = class _RequestContentLengthMismatchError extends UndiciError {
+      static {
+        __name(this, "RequestContentLengthMismatchError");
+      }
       constructor(message) {
         super(message);
         Error.captureStackTrace(this, _RequestContentLengthMismatchError);
@@ -192,6 +227,9 @@ var require_errors = __commonJS({
       }
     };
     var ResponseContentLengthMismatchError = class _ResponseContentLengthMismatchError extends UndiciError {
+      static {
+        __name(this, "ResponseContentLengthMismatchError");
+      }
       constructor(message) {
         super(message);
         Error.captureStackTrace(this, _ResponseContentLengthMismatchError);
@@ -201,6 +239,9 @@ var require_errors = __commonJS({
       }
     };
     var ClientDestroyedError = class _ClientDestroyedError extends UndiciError {
+      static {
+        __name(this, "ClientDestroyedError");
+      }
       constructor(message) {
         super(message);
         Error.captureStackTrace(this, _ClientDestroyedError);
@@ -210,6 +251,9 @@ var require_errors = __commonJS({
       }
     };
     var ClientClosedError = class _ClientClosedError extends UndiciError {
+      static {
+        __name(this, "ClientClosedError");
+      }
       constructor(message) {
         super(message);
         Error.captureStackTrace(this, _ClientClosedError);
@@ -219,6 +263,9 @@ var require_errors = __commonJS({
       }
     };
     var SocketError = class _SocketError extends UndiciError {
+      static {
+        __name(this, "SocketError");
+      }
       constructor(message, socket) {
         super(message);
         Error.captureStackTrace(this, _SocketError);
@@ -229,6 +276,9 @@ var require_errors = __commonJS({
       }
     };
     var NotSupportedError = class _NotSupportedError extends UndiciError {
+      static {
+        __name(this, "NotSupportedError");
+      }
       constructor(message) {
         super(message);
         Error.captureStackTrace(this, _NotSupportedError);
@@ -238,6 +288,9 @@ var require_errors = __commonJS({
       }
     };
     var BalancedPoolMissingUpstreamError = class extends UndiciError {
+      static {
+        __name(this, "BalancedPoolMissingUpstreamError");
+      }
       constructor(message) {
         super(message);
         Error.captureStackTrace(this, NotSupportedError);
@@ -247,6 +300,9 @@ var require_errors = __commonJS({
       }
     };
     var HTTPParserError = class _HTTPParserError extends Error {
+      static {
+        __name(this, "HTTPParserError");
+      }
       constructor(message, code, data) {
         super(message);
         Error.captureStackTrace(this, _HTTPParserError);
@@ -256,6 +312,9 @@ var require_errors = __commonJS({
       }
     };
     var ResponseExceededMaxSizeError = class _ResponseExceededMaxSizeError extends UndiciError {
+      static {
+        __name(this, "ResponseExceededMaxSizeError");
+      }
       constructor(message) {
         super(message);
         Error.captureStackTrace(this, _ResponseExceededMaxSizeError);
@@ -304,12 +363,15 @@ var require_util = __commonJS({
     var [nodeMajor, nodeMinor] = process.versions.node.split(".").map((v) => Number(v));
     function nop() {
     }
+    __name(nop, "nop");
     function isStream(obj) {
       return obj && typeof obj === "object" && typeof obj.pipe === "function" && typeof obj.on === "function";
     }
+    __name(isStream, "isStream");
     function isBlobLike(object) {
       return Blob2 && object instanceof Blob2 || object && typeof object === "object" && (typeof object.stream === "function" || typeof object.arrayBuffer === "function") && /^(Blob|File)$/.test(object[Symbol.toStringTag]);
     }
+    __name(isBlobLike, "isBlobLike");
     function buildURL(url, queryParams) {
       if (url.includes("?") || url.includes("#")) {
         throw new Error('Query params cannot be passed when url already contains "?" or "#".');
@@ -320,6 +382,7 @@ var require_util = __commonJS({
       }
       return url;
     }
+    __name(buildURL, "buildURL");
     function parseURL(url) {
       if (typeof url === "string") {
         url = new URL(url);
@@ -363,6 +426,7 @@ var require_util = __commonJS({
       }
       return url;
     }
+    __name(parseURL, "parseURL");
     function parseOrigin(url) {
       url = parseURL(url);
       if (url.pathname !== "/" || url.search || url.hash) {
@@ -370,6 +434,7 @@ var require_util = __commonJS({
       }
       return url;
     }
+    __name(parseOrigin, "parseOrigin");
     function getHostname(host) {
       if (host[0] === "[") {
         const idx2 = host.indexOf("]");
@@ -381,6 +446,7 @@ var require_util = __commonJS({
         return host;
       return host.substr(0, idx);
     }
+    __name(getHostname, "getHostname");
     function getServerName(host) {
       if (!host) {
         return null;
@@ -392,15 +458,19 @@ var require_util = __commonJS({
       }
       return servername;
     }
+    __name(getServerName, "getServerName");
     function deepClone(obj) {
       return JSON.parse(JSON.stringify(obj));
     }
+    __name(deepClone, "deepClone");
     function isAsyncIterable(obj) {
       return !!(obj != null && typeof obj[Symbol.asyncIterator] === "function");
     }
+    __name(isAsyncIterable, "isAsyncIterable");
     function isIterable(obj) {
       return !!(obj != null && (typeof obj[Symbol.iterator] === "function" || typeof obj[Symbol.asyncIterator] === "function"));
     }
+    __name(isIterable, "isIterable");
     function bodyLength(body) {
       if (body == null) {
         return 0;
@@ -414,13 +484,16 @@ var require_util = __commonJS({
       }
       return null;
     }
+    __name(bodyLength, "bodyLength");
     function isDestroyed(stream2) {
       return !stream2 || !!(stream2.destroyed || stream2[kDestroyed]);
     }
+    __name(isDestroyed, "isDestroyed");
     function isReadableAborted(stream2) {
       const state = stream2 && stream2._readableState;
       return isDestroyed(stream2) && state && !state.endEmitted;
     }
+    __name(isReadableAborted, "isReadableAborted");
     function destroy(stream2, err) {
       if (!isStream(stream2) || isDestroyed(stream2)) {
         return;
@@ -439,11 +512,13 @@ var require_util = __commonJS({
         stream2[kDestroyed] = true;
       }
     }
+    __name(destroy, "destroy");
     var KEEPALIVE_TIMEOUT_EXPR = /timeout=(\d+)/;
     function parseKeepAliveTimeout(val) {
       const m = val.toString().match(KEEPALIVE_TIMEOUT_EXPR);
       return m ? parseInt(m[1], 10) * 1e3 : null;
     }
+    __name(parseKeepAliveTimeout, "parseKeepAliveTimeout");
     function parseHeaders(headers, obj = {}) {
       if (!Array.isArray(headers))
         return headers;
@@ -469,6 +544,7 @@ var require_util = __commonJS({
       }
       return obj;
     }
+    __name(parseHeaders, "parseHeaders");
     function parseRawHeaders(headers) {
       const ret = [];
       let hasContentLength = false;
@@ -490,9 +566,11 @@ var require_util = __commonJS({
       }
       return ret;
     }
+    __name(parseRawHeaders, "parseRawHeaders");
     function isBuffer(buffer) {
       return buffer instanceof Uint8Array || Buffer.isBuffer(buffer);
     }
+    __name(isBuffer, "isBuffer");
     function validateHandler(handler, method, upgrade) {
       if (!handler || typeof handler !== "object") {
         throw new InvalidArgumentError("handler must be an object");
@@ -522,19 +600,23 @@ var require_util = __commonJS({
         }
       }
     }
+    __name(validateHandler, "validateHandler");
     function isDisturbed(body) {
       return !!(body && (stream.isDisturbed ? stream.isDisturbed(body) || body[kBodyUsed] : body[kBodyUsed] || body.readableDidRead || body._readableState && body._readableState.dataEmitted || isReadableAborted(body)));
     }
+    __name(isDisturbed, "isDisturbed");
     function isErrored(body) {
       return !!(body && (stream.isErrored ? stream.isErrored(body) : /state: 'errored'/.test(
         nodeUtil.inspect(body)
       )));
     }
+    __name(isErrored, "isErrored");
     function isReadable(body) {
       return !!(body && (stream.isReadable ? stream.isReadable(body) : /state: 'readable'/.test(
         nodeUtil.inspect(body)
       )));
     }
+    __name(isReadable, "isReadable");
     function getSocketInfo(socket) {
       return {
         localAddress: socket.localAddress,
@@ -547,11 +629,13 @@ var require_util = __commonJS({
         bytesRead: socket.bytesRead
       };
     }
+    __name(getSocketInfo, "getSocketInfo");
     async function* convertIterableToBuffer(iterable) {
       for await (const chunk of iterable) {
         yield Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
       }
     }
+    __name(convertIterableToBuffer, "convertIterableToBuffer");
     var ReadableStream;
     function ReadableStreamFrom(iterable) {
       if (!ReadableStream) {
@@ -585,9 +669,11 @@ var require_util = __commonJS({
         0
       );
     }
+    __name(ReadableStreamFrom, "ReadableStreamFrom");
     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";
     }
+    __name(isFormDataLike, "isFormDataLike");
     function throwIfAborted(signal) {
       if (!signal) {
         return;
@@ -602,6 +688,7 @@ var require_util = __commonJS({
         }
       }
     }
+    __name(throwIfAborted, "throwIfAborted");
     var events;
     function addAbortListener(signal, listener) {
       if (typeof Symbol.dispose === "symbol") {
@@ -619,6 +706,7 @@ var require_util = __commonJS({
       signal.addListener("abort", listener);
       return () => signal.removeListener("abort", listener);
     }
+    __name(addAbortListener, "addAbortListener");
     var hasToWellFormed = !!String.prototype.toWellFormed;
     function toUSVString(val) {
       if (hasToWellFormed) {
@@ -628,6 +716,7 @@ var require_util = __commonJS({
       }
       return `${val}`;
     }
+    __name(toUSVString, "toUSVString");
     var kEnumerableProperty = /* @__PURE__ */ Object.create(null);
     kEnumerableProperty.enumerable = true;
     module2.exports = {
@@ -819,7 +908,7 @@ var require_constants = __commonJS({
     var channel;
     var 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 structuredClone2(value, options = void 0) {
+    /* @__PURE__ */ __name(function structuredClone2(value, options = void 0) {
       if (arguments.length === 0) {
         throw new TypeError("missing argument");
       }
@@ -830,7 +919,7 @@ var require_constants = __commonJS({
       channel.port2.unref();
       channel.port1.postMessage(value, options?.transfer);
       return receiveMessageOnPort(channel.port2).message;
-    };
+    }, "structuredClone");
     module2.exports = {
       DOMException,
       structuredClone,
@@ -860,6 +949,7 @@ var require_global = __commonJS({
     function getGlobalOrigin() {
       return globalThis[globalOrigin];
     }
+    __name(getGlobalOrigin, "getGlobalOrigin");
     function setGlobalOrigin(newOrigin) {
       if (newOrigin === void 0) {
         Object.defineProperty(globalThis, globalOrigin, {
@@ -881,6 +971,7 @@ var require_global = __commonJS({
         configurable: false
       });
     }
+    __name(setGlobalOrigin, "setGlobalOrigin");
     module2.exports = {
       getGlobalOrigin,
       setGlobalOrigin
@@ -908,6 +999,7 @@ var require_util2 = __commonJS({
       const length = urlList.length;
       return length === 0 ? null : urlList[length - 1].toString();
     }
+    __name(responseURL, "responseURL");
     function responseLocationURL(response, requestFragment) {
       if (!redirectStatus.includes(response.status)) {
         return null;
@@ -921,9 +1013,11 @@ var require_util2 = __commonJS({
       }
       return location;
     }
+    __name(responseLocationURL, "responseLocationURL");
     function requestCurrentURL(request) {
       return request.urlList[request.urlList.length - 1];
     }
+    __name(requestCurrentURL, "requestCurrentURL");
     function requestBadPort(request) {
       const url = requestCurrentURL(request);
       if (urlIsHttpHttpsScheme(url) && badPorts.includes(url.port)) {
@@ -931,9 +1025,11 @@ var require_util2 = __commonJS({
       }
       return "allowed";
     }
+    __name(requestBadPort, "requestBadPort");
     function isErrorLike(object) {
       return object instanceof Error || (object?.constructor?.name === "Error" || object?.constructor?.name === "DOMException");
     }
+    __name(isErrorLike, "isErrorLike");
     function isValidReasonPhrase(statusText) {
       for (let i = 0; i < statusText.length; ++i) {
         const c = statusText.charCodeAt(i);
@@ -945,9 +1041,11 @@ var require_util2 = __commonJS({
       }
       return true;
     }
+    __name(isValidReasonPhrase, "isValidReasonPhrase");
     function isTokenChar(c) {
       return !(c >= 127 || c <= 32 || c === "(" || c === ")" || c === "<" || c === ">" || c === "@" || c === "," || c === ";" || c === ":" || c === "\\" || c === '"' || c === "/" || c === "[" || c === "]" || c === "?" || c === "=" || c === "{" || c === "}");
     }
+    __name(isTokenChar, "isTokenChar");
     function isValidHTTPToken(characters) {
       if (!characters || typeof characters !== "string") {
         return false;
@@ -960,12 +1058,14 @@ var require_util2 = __commonJS({
       }
       return true;
     }
+    __name(isValidHTTPToken, "isValidHTTPToken");
     function isValidHeaderName(potentialValue) {
       if (potentialValue.length === 0) {
         return false;
       }
       return isValidHTTPToken(potentialValue);
     }
+    __name(isValidHeaderName, "isValidHeaderName");
     function isValidHeaderValue(potentialValue) {
       if (potentialValue.startsWith("	") || potentialValue.startsWith(" ") || potentialValue.endsWith("	") || potentialValue.endsWith(" ")) {
         return false;
@@ -975,6 +1075,7 @@ var require_util2 = __commonJS({
       }
       return true;
     }
+    __name(isValidHeaderValue, "isValidHeaderValue");
     function setRequestReferrerPolicyOnRedirect(request, actualResponse) {
       const { headersList } = actualResponse;
       const policyHeader = (headersList.get("referrer-policy") ?? "").split(",");
@@ -992,20 +1093,25 @@ var require_util2 = __commonJS({
         request.referrerPolicy = policy;
       }
     }
+    __name(setRequestReferrerPolicyOnRedirect, "setRequestReferrerPolicyOnRedirect");
     function crossOriginResourcePolicyCheck() {
       return "allowed";
     }
+    __name(crossOriginResourcePolicyCheck, "crossOriginResourcePolicyCheck");
     function corsCheck() {
       return "success";
     }
+    __name(corsCheck, "corsCheck");
     function TAOCheck() {
       return "success";
     }
+    __name(TAOCheck, "TAOCheck");
     function appendFetchMetadata(httpRequest) {
       let header = null;
       header = httpRequest.mode;
       httpRequest.headersList.set("sec-fetch-mode", header);
     }
+    __name(appendFetchMetadata, "appendFetchMetadata");
     function appendRequestOriginHeader(request) {
       let serializedOrigin = request.origin;
       if (request.responseTainting === "cors" || request.mode === "websocket") {
@@ -1036,9 +1142,11 @@ var require_util2 = __commonJS({
         }
       }
     }
+    __name(appendRequestOriginHeader, "appendRequestOriginHeader");
     function coarsenedSharedCurrentTime(crossOriginIsolatedCapability) {
       return performance2.now();
     }
+    __name(coarsenedSharedCurrentTime, "coarsenedSharedCurrentTime");
     function createOpaqueTimingInfo(timingInfo) {
       return {
         startTime: timingInfo.startTime ?? 0,
@@ -1054,16 +1162,19 @@ var require_util2 = __commonJS({
         finalConnectionTimingInfo: null
       };
     }
+    __name(createOpaqueTimingInfo, "createOpaqueTimingInfo");
     function makePolicyContainer() {
       return {
         referrerPolicy: "strict-origin-when-cross-origin"
       };
     }
+    __name(makePolicyContainer, "makePolicyContainer");
     function clonePolicyContainer(policyContainer) {
       return {
         referrerPolicy: policyContainer.referrerPolicy
       };
     }
+    __name(clonePolicyContainer, "clonePolicyContainer");
     function determineRequestsReferrer(request) {
       const policy = request.referrerPolicy;
       assert(policy);
@@ -1109,6 +1220,7 @@ var require_util2 = __commonJS({
           return isNonPotentiallyTrustWorthy ? "no-referrer" : referrerOrigin;
       }
     }
+    __name(determineRequestsReferrer, "determineRequestsReferrer");
     function stripURLForReferrer(url, originOnly) {
       assert(url instanceof URL);
       if (url.protocol === "file:" || url.protocol === "about:" || url.protocol === "blank:") {
@@ -1123,6 +1235,7 @@ var require_util2 = __commonJS({
       }
       return url;
     }
+    __name(stripURLForReferrer, "stripURLForReferrer");
     function isURLPotentiallyTrustworthy(url) {
       if (!(url instanceof URL)) {
         return false;
@@ -1147,7 +1260,9 @@ var require_util2 = __commonJS({
         }
         return false;
       }
+      __name(isOriginPotentiallyTrustworthy, "isOriginPotentiallyTrustworthy");
     }
+    __name(isURLPotentiallyTrustworthy, "isURLPotentiallyTrustworthy");
     function bytesMatch(bytes, metadataList) {
       if (crypto === void 0) {
         return true;
@@ -1185,6 +1300,7 @@ var require_util2 = __commonJS({
       }
       return false;
     }
+    __name(bytesMatch, "bytesMatch");
     var parseHashWithOptions = /((?sha256|sha384|sha512)-(?[A-z0-9+/]{1}.*={0,2}))( +[\x21-\x7e]?)?/i;
     function parseMetadata(metadata) {
       const result = [];
@@ -1206,8 +1322,10 @@ var require_util2 = __commonJS({
       }
       return result;
     }
+    __name(parseMetadata, "parseMetadata");
     function tryUpgradeRequestToAPotentiallyTrustworthyURL(request) {
     }
+    __name(tryUpgradeRequestToAPotentiallyTrustworthyURL, "tryUpgradeRequestToAPotentiallyTrustworthyURL");
     function sameOrigin(A, B) {
       if (A.origin === B.origin && A.origin === "null") {
         return true;
@@ -1217,6 +1335,7 @@ var require_util2 = __commonJS({
       }
       return false;
     }
+    __name(sameOrigin, "sameOrigin");
     function createDeferredPromise() {
       let res;
       let rej;
@@ -1226,15 +1345,19 @@ var require_util2 = __commonJS({
       });
       return { promise, resolve: res, reject: rej };
     }
+    __name(createDeferredPromise, "createDeferredPromise");
     function isAborted(fetchParams) {
       return fetchParams.controller.state === "aborted";
     }
+    __name(isAborted, "isAborted");
     function isCancelled(fetchParams) {
       return fetchParams.controller.state === "aborted" || fetchParams.controller.state === "terminated";
     }
+    __name(isCancelled, "isCancelled");
     function normalizeMethod(method) {
       return /^(DELETE|GET|HEAD|OPTIONS|POST|PUT)$/i.test(method) ? method.toUpperCase() : method;
     }
+    __name(normalizeMethod, "normalizeMethod");
     function serializeJavascriptValueToJSONString(value) {
       const result = JSON.stringify(value);
       if (result === void 0) {
@@ -1243,6 +1366,7 @@ var require_util2 = __commonJS({
       assert(typeof result === "string");
       return result;
     }
+    __name(serializeJavascriptValueToJSONString, "serializeJavascriptValueToJSONString");
     var esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
     function makeIterator(iterator, name, kind) {
       const object = {
@@ -1274,6 +1398,7 @@ var require_util2 = __commonJS({
       Object.setPrototypeOf(i, esIteratorPrototype);
       return Object.setPrototypeOf({}, i);
     }
+    __name(makeIterator, "makeIterator");
     function iteratorResult(pair, kind) {
       let result;
       switch (kind) {
@@ -1292,6 +1417,7 @@ var require_util2 = __commonJS({
       }
       return { value: result, done: false };
     }
+    __name(iteratorResult, "iteratorResult");
     async function fullyReadBody(body, processBody, processBodyError) {
       const successSteps = processBody;
       const errorSteps = processBodyError;
@@ -1309,6 +1435,7 @@ var require_util2 = __commonJS({
         errorSteps(e);
       }
     }
+    __name(fullyReadBody, "fullyReadBody");
     var ReadableStream = globalThis.ReadableStream;
     function isReadableStreamLike(stream) {
       if (!ReadableStream) {
@@ -1316,6 +1443,7 @@ var require_util2 = __commonJS({
       }
       return stream instanceof ReadableStream || stream[Symbol.toStringTag] === "ReadableStream" && typeof stream.tee === "function";
     }
+    __name(isReadableStreamLike, "isReadableStreamLike");
     var MAXIMUM_ARGUMENT_LENGTH = 65535;
     function isomorphicDecode(input) {
       if (input.length < MAXIMUM_ARGUMENT_LENGTH) {
@@ -1323,6 +1451,7 @@ var require_util2 = __commonJS({
       }
       return input.reduce((previous, current) => previous + String.fromCharCode(current), "");
     }
+    __name(isomorphicDecode, "isomorphicDecode");
     function readableStreamClose(controller) {
       try {
         controller.close();
@@ -1332,12 +1461,14 @@ var require_util2 = __commonJS({
         }
       }
     }
+    __name(readableStreamClose, "readableStreamClose");
     function isomorphicEncode(input) {
       for (let i = 0; i < input.length; i++) {
         assert(input.charCodeAt(i) <= 255);
       }
       return input;
     }
+    __name(isomorphicEncode, "isomorphicEncode");
     async function readAllBytes(reader) {
       const bytes = [];
       let byteLength = 0;
@@ -1353,22 +1484,26 @@ var require_util2 = __commonJS({
         byteLength += chunk.length;
       }
     }
+    __name(readAllBytes, "readAllBytes");
     function urlIsLocal(url) {
       assert("protocol" in url);
       const protocol = url.protocol;
       return protocol === "about:" || protocol === "blob:" || protocol === "data:";
     }
+    __name(urlIsLocal, "urlIsLocal");
     function urlHasHttpsScheme(url) {
       if (typeof url === "string") {
         return url.startsWith("https:");
       }
       return url.protocol === "https:";
     }
+    __name(urlHasHttpsScheme, "urlHasHttpsScheme");
     function urlIsHttpHttpsScheme(url) {
       assert("protocol" in url);
       const protocol = url.protocol;
       return protocol === "http:" || protocol === "https:";
     }
+    __name(urlIsHttpHttpsScheme, "urlIsHttpHttpsScheme");
     var hasOwn = Object.hasOwn || ((dict, key) => Object.prototype.hasOwnProperty.call(dict, key));
     module2.exports = {
       isAborted,
@@ -1810,6 +1945,7 @@ var require_headers = __commonJS({
         ;
       return potentialValue.slice(0, i + 1).replace(/^[\r\n\t ]+/, "");
     }
+    __name(headerValueNormalize, "headerValueNormalize");
     function fill(headers, object) {
       if (Array.isArray(object)) {
         for (const header of object) {
@@ -1833,7 +1969,11 @@ var require_headers = __commonJS({
         });
       }
     }
+    __name(fill, "fill");
     var HeadersList = class _HeadersList {
+      static {
+        __name(this, "HeadersList");
+      }
       /** @type {[string, string][]|null} */
       cookies = null;
       constructor(init) {
@@ -1916,6 +2056,9 @@ var require_headers = __commonJS({
       }
     };
     var Headers = class _Headers {
+      static {
+        __name(this, "Headers");
+      }
       constructor(init = void 0) {
         this[kHeadersList] = new HeadersList();
         this[kGuard] = "none";
@@ -2170,6 +2313,7 @@ var require_sbmh = __commonJS({
         this._occ[needle[i]] = needleLength - 1 - i;
       }
     }
+    __name(SBMH, "SBMH");
     inherits(SBMH, EventEmitter);
     SBMH.prototype.reset = function() {
       this._lookbehind_size = 0;
@@ -2285,6 +2429,7 @@ var require_PartStream = __commonJS({
     function PartStream(opts) {
       ReadableStream.call(this, opts);
     }
+    __name(PartStream, "PartStream");
     inherits(PartStream, ReadableStream);
     PartStream.prototype._read = function(n) {
     };
@@ -2296,7 +2441,7 @@ var require_PartStream = __commonJS({
 var require_getLimit = __commonJS({
   "node_modules/@fastify/busboy/lib/utils/getLimit.js"(exports2, module2) {
     "use strict";
-    module2.exports = function getLimit(limits, name, defaultLimit) {
+    module2.exports = /* @__PURE__ */ __name(function getLimit(limits, name, defaultLimit) {
       if (!limits || limits[name] === void 0 || limits[name] === null) {
         return defaultLimit;
       }
@@ -2304,7 +2449,7 @@ var require_getLimit = __commonJS({
         throw new TypeError("Limit " + name + " is not a valid number");
       }
       return limits[name];
-    };
+    }, "getLimit");
   }
 });
 
@@ -2348,6 +2493,7 @@ var require_HeaderParser = __commonJS({
         }
       });
     }
+    __name(HeaderParser, "HeaderParser");
     inherits(HeaderParser, EventEmitter);
     HeaderParser.prototype.push = function(data) {
       const r = this.ss.push(data);
@@ -2420,8 +2566,8 @@ var require_Dicer = __commonJS({
     var DASH = 45;
     var B_ONEDASH = Buffer.from("-");
     var B_CRLF = Buffer.from("\r\n");
-    var EMPTY_FN = function() {
-    };
+    var EMPTY_FN = /* @__PURE__ */ __name(function() {
+    }, "EMPTY_FN");
     function Dicer(cfg) {
       if (!(this instanceof Dicer)) {
         return new Dicer(cfg);
@@ -2456,6 +2602,7 @@ var require_Dicer = __commonJS({
         self._part.emit("header", header);
       });
     }
+    __name(Dicer, "Dicer");
     inherits(Dicer, WritableStream);
     Dicer.prototype.emit = function(ev) {
       if (ev === "finish" && !this._realFinish) {
@@ -2674,6 +2821,7 @@ var require_decodeText = __commonJS({
       }
       return text;
     }
+    __name(decodeText, "decodeText");
     module2.exports = decodeText;
   }
 });
@@ -2687,6 +2835,7 @@ var require_parseParams = __commonJS({
     function encodedReplacer(match, byte) {
       return String.fromCharCode(parseInt(byte, 16));
     }
+    __name(encodedReplacer, "encodedReplacer");
     function parseParams(str) {
       const res = [];
       let state = "key";
@@ -2785,6 +2934,7 @@ var require_parseParams = __commonJS({
       }
       return res;
     }
+    __name(parseParams, "parseParams");
     module2.exports = parseParams;
   }
 });
@@ -2793,7 +2943,7 @@ var require_parseParams = __commonJS({
 var require_basename = __commonJS({
   "node_modules/@fastify/busboy/lib/utils/basename.js"(exports2, module2) {
     "use strict";
-    module2.exports = function basename(path) {
+    module2.exports = /* @__PURE__ */ __name(function basename(path) {
       if (typeof path !== "string") {
         return "";
       }
@@ -2806,7 +2956,7 @@ var require_basename = __commonJS({
         }
       }
       return path === ".." || path === "." ? "" : path;
-    };
+    }, "basename");
   }
 });
 
@@ -2850,6 +3000,7 @@ var require_multipart = __commonJS({
           self.end();
         }
       }
+      __name(checkFinished, "checkFinished");
       if (typeof boundary !== "string") {
         throw new Error("Multipart: Boundary not found");
       }
@@ -2886,7 +3037,7 @@ var require_multipart = __commonJS({
           self._cb = void 0;
           cb();
         }
-      }).on("part", function onPart(part) {
+      }).on("part", /* @__PURE__ */ __name(function onPart(part) {
         if (++self._nparts > partsLimit) {
           self.parser.removeListener("part", onPart);
           self.parser.on("part", skipPart);
@@ -2987,7 +3138,7 @@ var require_multipart = __commonJS({
               }
             };
             boy.emit("file", fieldname, file, filename, encoding, contype);
-            onData = function(data) {
+            onData = /* @__PURE__ */ __name(function(data) {
               if ((nsize += data.length) > fileSizeLimit) {
                 const extralen = fileSizeLimit - nsize + data.length;
                 if (extralen > 0) {
@@ -3002,11 +3153,11 @@ var require_multipart = __commonJS({
                 self._pause = true;
               }
               file.bytesRead = nsize;
-            };
-            onEnd = function() {
+            }, "onData");
+            onEnd = /* @__PURE__ */ __name(function() {
               curFile = void 0;
               file.push(null);
-            };
+            }, "onEnd");
           } else {
             if (nfields === fieldsLimit) {
               if (!boy.hitFieldsLimit) {
@@ -3020,7 +3171,7 @@ var require_multipart = __commonJS({
             let buffer = "";
             let truncated = false;
             curField = part;
-            onData = function(data) {
+            onData = /* @__PURE__ */ __name(function(data) {
               if ((nsize += data.length) > fieldSizeLimit) {
                 const extralen = fieldSizeLimit - (nsize - data.length);
                 buffer += data.toString("binary", 0, extralen);
@@ -3029,8 +3180,8 @@ var require_multipart = __commonJS({
               } else {
                 buffer += data.toString("binary");
               }
-            };
-            onEnd = function() {
+            }, "onData");
+            onEnd = /* @__PURE__ */ __name(function() {
               curField = void 0;
               if (buffer.length) {
                 buffer = decodeText(buffer, "binary", charset);
@@ -3038,7 +3189,7 @@ var require_multipart = __commonJS({
               boy.emit("field", fieldname, buffer, false, truncated, encoding, contype);
               --nends;
               checkFinished();
-            };
+            }, "onEnd");
           }
           part._readableState.sync = false;
           part.on("data", onData);
@@ -3048,13 +3199,14 @@ var require_multipart = __commonJS({
             curFile.emit("error", err);
           }
         });
-      }).on("error", function(err) {
+      }, "onPart")).on("error", function(err) {
         boy.emit("error", err);
       }).on("finish", function() {
         finished = true;
         checkFinished();
       });
     }
+    __name(Multipart, "Multipart");
     Multipart.prototype.write = function(chunk, cb) {
       const r = this.parser.write(chunk);
       if (r && !this._pause) {
@@ -3078,11 +3230,13 @@ var require_multipart = __commonJS({
     function skipPart(part) {
       part.resume();
     }
+    __name(skipPart, "skipPart");
     function FileStream(opts) {
       Readable.call(this, opts);
       this.bytesRead = 0;
       this.truncated = false;
     }
+    __name(FileStream, "FileStream");
     inherits(FileStream, Readable);
     FileStream.prototype._read = function(n) {
     };
@@ -3228,6 +3382,7 @@ var require_Decoder = __commonJS({
     function Decoder() {
       this.buffer = void 0;
     }
+    __name(Decoder, "Decoder");
     Decoder.prototype.write = function(str) {
       str = str.replace(RE_PLUS, " ");
       let res = "";
@@ -3308,6 +3463,7 @@ var require_urlencoded = __commonJS({
       this._valTrunc = false;
       this._hitLimit = false;
     }
+    __name(UrlEncoded, "UrlEncoded");
     UrlEncoded.prototype.write = function(data, cb) {
       if (this._fields === this.fieldsLimit) {
         if (!this.boy.hitFieldsLimit) {
@@ -3520,6 +3676,7 @@ var require_main = __commonJS({
       this._parser = this.getParserByHeaders(headers);
       this._finished = false;
     }
+    __name(Busboy, "Busboy");
     inherits(Busboy, WritableStream);
     Busboy.prototype.emit = function(ev) {
       if (ev === "finish") {
@@ -3610,6 +3767,7 @@ var require_dataURL = __commonJS({
       }
       return { mimeType: mimeTypeRecord, body };
     }
+    __name(dataURLProcessor, "dataURLProcessor");
     function URLSerializer(url, excludeFragment = false) {
       const href = url.href;
       if (!excludeFragment) {
@@ -3621,6 +3779,7 @@ var require_dataURL = __commonJS({
       }
       return href.slice(0, hash);
     }
+    __name(URLSerializer, "URLSerializer");
     function collectASequenceOfCodePoints(condition, input, position) {
       let result = "";
       while (position.position < input.length && condition(input[position.position])) {
@@ -3629,6 +3788,7 @@ var require_dataURL = __commonJS({
       }
       return result;
     }
+    __name(collectASequenceOfCodePoints, "collectASequenceOfCodePoints");
     function collectASequenceOfCodePointsFast(char, input, position) {
       const idx = input.indexOf(char, position.position);
       const start = position.position;
@@ -3639,10 +3799,12 @@ var require_dataURL = __commonJS({
       position.position = idx;
       return input.slice(start, position.position);
     }
+    __name(collectASequenceOfCodePointsFast, "collectASequenceOfCodePointsFast");
     function stringPercentDecode(input) {
       const bytes = encoder.encode(input);
       return percentDecode(bytes);
     }
+    __name(stringPercentDecode, "stringPercentDecode");
     function percentDecode(input) {
       const output = [];
       for (let i = 0; i < input.length; i++) {
@@ -3660,6 +3822,7 @@ var require_dataURL = __commonJS({
       }
       return Uint8Array.from(output);
     }
+    __name(percentDecode, "percentDecode");
     function parseMIMEType(input) {
       input = removeHTTPWhitespace(input, true, true);
       const position = { position: 0 };
@@ -3742,6 +3905,7 @@ var require_dataURL = __commonJS({
       }
       return mimeType;
     }
+    __name(parseMIMEType, "parseMIMEType");
     function forgivingBase64(data) {
       data = data.replace(/[\u0009\u000A\u000C\u000D\u0020]/g, "");
       if (data.length % 4 === 0) {
@@ -3760,6 +3924,7 @@ var require_dataURL = __commonJS({
       }
       return bytes;
     }
+    __name(forgivingBase64, "forgivingBase64");
     function collectAnHTTPQuotedString(input, position, extractValue) {
       const positionStart = position.position;
       let value = "";
@@ -3793,6 +3958,7 @@ var require_dataURL = __commonJS({
       }
       return input.slice(positionStart, position.position);
     }
+    __name(collectAnHTTPQuotedString, "collectAnHTTPQuotedString");
     function serializeAMimeType(mimeType) {
       assert(mimeType !== "failure");
       const { parameters, essence } = mimeType;
@@ -3810,9 +3976,11 @@ var require_dataURL = __commonJS({
       }
       return serialization;
     }
+    __name(serializeAMimeType, "serializeAMimeType");
     function isHTTPWhiteSpace(char) {
       return char === "\r" || char === "\n" || char === "	" || char === " ";
     }
+    __name(isHTTPWhiteSpace, "isHTTPWhiteSpace");
     function removeHTTPWhitespace(str, leading = true, trailing = true) {
       let lead = 0;
       let trail = str.length - 1;
@@ -3826,9 +3994,11 @@ var require_dataURL = __commonJS({
       }
       return str.slice(lead, trail + 1);
     }
+    __name(removeHTTPWhitespace, "removeHTTPWhitespace");
     function isASCIIWhitespace(char) {
       return char === "\r" || char === "\n" || char === "	" || char === "\f" || char === " ";
     }
+    __name(isASCIIWhitespace, "isASCIIWhitespace");
     function removeASCIIWhitespace(str, leading = true, trailing = true) {
       let lead = 0;
       let trail = str.length - 1;
@@ -3842,6 +4012,7 @@ var require_dataURL = __commonJS({
       }
       return str.slice(lead, trail + 1);
     }
+    __name(removeASCIIWhitespace, "removeASCIIWhitespace");
     module2.exports = {
       dataURLProcessor,
       URLSerializer,
@@ -3867,6 +4038,9 @@ var require_file = __commonJS({
     var { parseMIMEType, serializeAMimeType } = require_dataURL();
     var { kEnumerableProperty } = require_util();
     var File = class _File extends Blob2 {
+      static {
+        __name(this, "File");
+      }
       constructor(fileBits, fileName, options = {}) {
         webidl.argumentLengthCheck(arguments, 2, { header: "File constructor" });
         fileBits = webidl.converters["sequence"](fileBits);
@@ -3907,6 +4081,9 @@ var require_file = __commonJS({
       }
     };
     var FileLike = class _FileLike {
+      static {
+        __name(this, "FileLike");
+      }
       constructor(blobLike, fileName, options = {}) {
         const n = fileName;
         const t = options.type;
@@ -4026,6 +4203,7 @@ var require_file = __commonJS({
       }
       return bytes;
     }
+    __name(processBlobParts, "processBlobParts");
     function convertLineEndingsNative(s) {
       let nativeLineEnding = "\n";
       if (process.platform === "win32") {
@@ -4033,9 +4211,11 @@ var require_file = __commonJS({
       }
       return s.replace(/\r?\n/g, nativeLineEnding);
     }
+    __name(convertLineEndingsNative, "convertLineEndingsNative");
     function isFileLike(object) {
       return NativeFile && object instanceof NativeFile || object instanceof File || object && (typeof object.stream === "function" || typeof object.arrayBuffer === "function") && object[Symbol.toStringTag] === "File";
     }
+    __name(isFileLike, "isFileLike");
     module2.exports = { File, FileLike, isFileLike };
   }
 });
@@ -4051,6 +4231,9 @@ var require_formdata = __commonJS({
     var { Blob: Blob2, File: NativeFile } = require("buffer");
     var File = NativeFile ?? UndiciFile;
     var FormData = class _FormData {
+      static {
+        __name(this, "FormData");
+      }
       constructor(form) {
         if (form !== void 0) {
           throw webidl.errors.conversionFailed({
@@ -4192,6 +4375,7 @@ var require_formdata = __commonJS({
       }
       return { name, value };
     }
+    __name(makeEntry, "makeEntry");
     module2.exports = { FormData };
   }
 });
@@ -4264,8 +4448,8 @@ var require_body = __commonJS({
         const boundary = `----formdata-undici-0${`${Math.floor(Math.random() * 1e11)}`.padStart(11, "0")}`;
         const prefix = `--${boundary}\r
 Content-Disposition: form-data`;
-        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");
+        const escape = /* @__PURE__ */ __name((str) => str.replace(/\n/g, "%0A").replace(/\r/g, "%0D").replace(/"/g, "%22"), "escape");
+        const normalizeLinefeeds = /* @__PURE__ */ __name((value) => value.replace(/\r?\n|\r/g, "\r\n"), "normalizeLinefeeds");
         const enc = new TextEncoder();
         const blobParts = [];
         const rn = new Uint8Array([13, 10]);
@@ -4299,7 +4483,7 @@ Content-Type: ${value.type || "application/octet-stream"}\r
           length = null;
         }
         source = object;
-        action = async function* () {
+        action = /* @__PURE__ */ __name(async function* () {
           for (const part of blobParts) {
             if (part.stream) {
               yield* part.stream();
@@ -4307,7 +4491,7 @@ Content-Type: ${value.type || "application/octet-stream"}\r
               yield part;
             }
           }
-        };
+        }, "action");
         type = "multipart/form-data; boundary=" + boundary;
       } else if (isBlobLike(object)) {
         source = object;
@@ -4357,6 +4541,7 @@ Content-Type: ${value.type || "application/octet-stream"}\r
       const body = { stream, source, length };
       return [body, type];
     }
+    __name(extractBody, "extractBody");
     function safelyExtractBody(object, keepalive = false) {
       if (!ReadableStream) {
         ReadableStream = require("stream/web").ReadableStream;
@@ -4367,6 +4552,7 @@ Content-Type: ${value.type || "application/octet-stream"}\r
       }
       return extractBody(object, keepalive);
     }
+    __name(safelyExtractBody, "safelyExtractBody");
     function cloneBody(body) {
       const [out1, out2] = body.stream.tee();
       const out2Clone = structuredClone(out2, { transfer: [out2] });
@@ -4378,6 +4564,7 @@ Content-Type: ${value.type || "application/octet-stream"}\r
         source: body.source
       };
     }
+    __name(cloneBody, "cloneBody");
     async function* consumeBody(body) {
       if (body) {
         if (isUint8Array(body)) {
@@ -4395,11 +4582,13 @@ Content-Type: ${value.type || "application/octet-stream"}\r
         }
       }
     }
+    __name(consumeBody, "consumeBody");
     function throwIfAborted(state) {
       if (state.aborted) {
         throw new DOMException("The operation was aborted.", "AbortError");
       }
     }
+    __name(throwIfAborted, "throwIfAborted");
     function bodyMixinMethods(instance) {
       const methods = {
         blob() {
@@ -4511,9 +4700,11 @@ Content-Type: ${value.type || "application/octet-stream"}\r
       };
       return methods;
     }
+    __name(bodyMixinMethods, "bodyMixinMethods");
     function mixinBody(prototype) {
       Object.assign(prototype.prototype, bodyMixinMethods(prototype));
     }
+    __name(mixinBody, "mixinBody");
     async function specConsumeBody(object, convertBytesToJSValue, instance) {
       webidl.brandCheck(object, instance);
       throwIfAborted(object[kState]);
@@ -4521,14 +4712,14 @@ Content-Type: ${value.type || "application/octet-stream"}\r
         throw new TypeError("Body is unusable");
       }
       const promise = createDeferredPromise();
-      const errorSteps = (error) => promise.reject(error);
-      const successSteps = (data) => {
+      const errorSteps = /* @__PURE__ */ __name((error) => promise.reject(error), "errorSteps");
+      const successSteps = /* @__PURE__ */ __name((data) => {
         try {
           promise.resolve(convertBytesToJSValue(data));
         } catch (e) {
           errorSteps(e);
         }
-      };
+      }, "successSteps");
       if (object[kState].body == null) {
         successSteps(new Uint8Array());
         return promise.promise;
@@ -4536,9 +4727,11 @@ Content-Type: ${value.type || "application/octet-stream"}\r
       await fullyReadBody(object[kState].body, successSteps, errorSteps);
       return promise.promise;
     }
+    __name(specConsumeBody, "specConsumeBody");
     function bodyUnusable(body) {
       return body != null && (body.stream.locked || util.isDisturbed(body.stream));
     }
+    __name(bodyUnusable, "bodyUnusable");
     function utf8DecodeBytes(buffer) {
       if (buffer.length === 0) {
         return "";
@@ -4549,9 +4742,11 @@ Content-Type: ${value.type || "application/octet-stream"}\r
       const output = new TextDecoder().decode(buffer);
       return output;
     }
+    __name(utf8DecodeBytes, "utf8DecodeBytes");
     function parseJSONFromBytes(bytes) {
       return JSON.parse(utf8DecodeBytes(bytes));
     }
+    __name(parseJSONFromBytes, "parseJSONFromBytes");
     function bodyMimeType(object) {
       const { headersList } = object[kState];
       const contentType = headersList.get("content-type");
@@ -4560,6 +4755,7 @@ Content-Type: ${value.type || "application/octet-stream"}\r
       }
       return parseMIMEType(contentType);
     }
+    __name(bodyMimeType, "bodyMimeType");
     module2.exports = {
       extractBody,
       safelyExtractBody,
@@ -4601,6 +4797,9 @@ var require_response = __commonJS({
     var { types } = require("util");
     var ReadableStream = globalThis.ReadableStream || require("stream/web").ReadableStream;
     var Response = class _Response {
+      static {
+        __name(this, "Response");
+      }
       // Creates network error Response.
       static error() {
         const relevantRealm = { settingsObject: {} };
@@ -4777,6 +4976,7 @@ var require_response = __commonJS({
       }
       return newResponse;
     }
+    __name(cloneResponse, "cloneResponse");
     function makeResponse(init) {
       return {
         aborted: false,
@@ -4793,6 +4993,7 @@ var require_response = __commonJS({
         urlList: init.urlList ? [...init.urlList] : []
       };
     }
+    __name(makeResponse, "makeResponse");
     function makeNetworkError(reason) {
       const isError = isErrorLike(reason);
       return makeResponse({
@@ -4802,6 +5003,7 @@ var require_response = __commonJS({
         aborted: reason && reason.name === "AbortError"
       });
     }
+    __name(makeNetworkError, "makeNetworkError");
     function makeFilteredResponse(response, state) {
       state = {
         internalResponse: response,
@@ -4818,6 +5020,7 @@ var require_response = __commonJS({
         }
       });
     }
+    __name(makeFilteredResponse, "makeFilteredResponse");
     function filterResponse(response, type) {
       if (type === "basic") {
         return makeFilteredResponse(response, {
@@ -4849,10 +5052,12 @@ var require_response = __commonJS({
         assert(false);
       }
     }
+    __name(filterResponse, "filterResponse");
     function makeAppropriateNetworkError(fetchParams, err = null) {
       assert(isCancelled(fetchParams));
       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 }));
     }
+    __name(makeAppropriateNetworkError, "makeAppropriateNetworkError");
     function initializeResponse(response, init, body) {
       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.');
@@ -4884,6 +5089,7 @@ var require_response = __commonJS({
         }
       }
     }
+    __name(initializeResponse, "initializeResponse");
     webidl.converters.ReadableStream = webidl.interfaceConverter(
       ReadableStream
     );
@@ -4953,6 +5159,9 @@ var require_dispatcher_weakref = __commonJS({
     "use strict";
     var { kConnected, kSize } = require_symbols();
     var CompatWeakRef = class {
+      static {
+        __name(this, "CompatWeakRef");
+      }
       constructor(value) {
         this.value = value;
       }
@@ -4961,6 +5170,9 @@ var require_dispatcher_weakref = __commonJS({
       }
     };
     var CompatFinalizer = class {
+      static {
+        __name(this, "CompatFinalizer");
+      }
       constructor(finalizer) {
         this.finalizer = finalizer;
       }
@@ -5028,6 +5240,9 @@ var require_request = __commonJS({
       signal.removeEventListener("abort", abort);
     });
     var Request = class _Request {
+      static {
+        __name(this, "Request");
+      }
       // https://fetch.spec.whatwg.org/#dom-request
       constructor(input, init = {}) {
         if (input === kInit) {
@@ -5219,12 +5434,12 @@ var require_request = __commonJS({
           } else {
             this[kAbortController] = ac;
             const acRef = new WeakRef(ac);
-            const abort = function() {
+            const abort = /* @__PURE__ */ __name(function() {
               const ac2 = acRef.deref();
               if (ac2 !== void 0) {
                 ac2.abort(this.reason);
               }
-            };
+            }, "abort");
             try {
               if (typeof getMaxListeners === "function" && getMaxListeners(signal) === defaultMaxListeners) {
                 setMaxListeners(100, signal);
@@ -5500,6 +5715,7 @@ var require_request = __commonJS({
       request.url = request.urlList[0];
       return request;
     }
+    __name(makeRequest, "makeRequest");
     function cloneRequest(request) {
       const newRequest = makeRequest({ ...request, body: null });
       if (request.body != null) {
@@ -5507,6 +5723,7 @@ var require_request = __commonJS({
       }
       return newRequest;
     }
+    __name(cloneRequest, "cloneRequest");
     Object.defineProperties(Request.prototype, {
       method: kEnumerableProperty,
       url: kEnumerableProperty,
@@ -5634,6 +5851,9 @@ var require_dispatcher = __commonJS({
     "use strict";
     var EventEmitter = require("events");
     var Dispatcher = class extends EventEmitter {
+      static {
+        __name(this, "Dispatcher");
+      }
       dispatch() {
         throw new Error("not implemented");
       }
@@ -5665,6 +5885,9 @@ var require_dispatcher_base = __commonJS({
     var kOnClosed = Symbol("onClosed");
     var kInterceptedDispatch = Symbol("Intercepted Dispatch");
     var DispatcherBase = class extends Dispatcher {
+      static {
+        __name(this, "DispatcherBase");
+      }
       constructor() {
         super();
         this[kDestroyed] = false;
@@ -5717,13 +5940,13 @@ var require_dispatcher_base = __commonJS({
         }
         this[kClosed] = true;
         this[kOnClosed].push(callback);
-        const onClosed = () => {
+        const onClosed = /* @__PURE__ */ __name(() => {
           const callbacks = this[kOnClosed];
           this[kOnClosed] = null;
           for (let i = 0; i < callbacks.length; i++) {
             callbacks[i](null, null);
           }
-        };
+        }, "onClosed");
         this[kClose]().then(() => this.destroy()).then(() => {
           queueMicrotask(onClosed);
         });
@@ -5760,13 +5983,13 @@ var require_dispatcher_base = __commonJS({
         this[kDestroyed] = true;
         this[kOnDestroyed] = this[kOnDestroyed] || [];
         this[kOnDestroyed].push(callback);
-        const onDestroyed = () => {
+        const onDestroyed = /* @__PURE__ */ __name(() => {
           const callbacks = this[kOnDestroyed];
           this[kOnDestroyed] = null;
           for (let i = 0; i < callbacks.length; i++) {
             callbacks[i](null, null);
           }
-        };
+        }, "onDestroyed");
         this[kDestroy](err).then(() => {
           queueMicrotask(onDestroyed);
         });
@@ -5818,6 +6041,9 @@ var require_fixed_queue = __commonJS({
     var kSize = 2048;
     var kMask = kSize - 1;
     var FixedCircularBuffer = class {
+      static {
+        __name(this, "FixedCircularBuffer");
+      }
       constructor() {
         this.bottom = 0;
         this.top = 0;
@@ -5844,6 +6070,9 @@ var require_fixed_queue = __commonJS({
       }
     };
     module2.exports = class FixedQueue {
+      static {
+        __name(this, "FixedQueue");
+      }
       constructor() {
         this.head = this.tail = new FixedCircularBuffer();
       }
@@ -5874,6 +6103,9 @@ var require_pool_stats = __commonJS({
     var { kFree, kConnected, kPending, kQueued, kRunning, kSize } = require_symbols();
     var kPool = Symbol("pool");
     var PoolStats = class {
+      static {
+        __name(this, "PoolStats");
+      }
       constructor(pool) {
         this[kPool] = pool;
       }
@@ -5921,13 +6153,16 @@ var require_pool_base = __commonJS({
     var kRemoveClient = Symbol("remove client");
     var kStats = Symbol("stats");
     var PoolBase = class extends DispatcherBase {
+      static {
+        __name(this, "PoolBase");
+      }
       constructor() {
         super();
         this[kQueue] = new FixedQueue();
         this[kClients] = [];
         this[kQueued] = 0;
         const pool = this;
-        this[kOnDrain] = function onDrain(origin, targets) {
+        this[kOnDrain] = /* @__PURE__ */ __name(function onDrain(origin, targets) {
           const queue = pool[kQueue];
           let needDrain = false;
           while (!needDrain) {
@@ -5946,7 +6181,7 @@ var require_pool_base = __commonJS({
           if (pool[kClosedResolve] && queue.isEmpty()) {
             Promise.all(pool[kClients].map((c) => c.close())).then(pool[kClosedResolve]);
           }
-        };
+        }, "onDrain");
         this[kOnConnect] = (origin, targets) => {
           pool.emit("connect", origin, [pool, ...targets]);
         };
@@ -6090,6 +6325,7 @@ var require_timers = __commonJS({
         refreshTimeout();
       }
     }
+    __name(onTimeout, "onTimeout");
     function refreshTimeout() {
       if (fastNowTimeout && fastNowTimeout.refresh) {
         fastNowTimeout.refresh();
@@ -6101,7 +6337,11 @@ var require_timers = __commonJS({
         }
       }
     }
+    __name(refreshTimeout, "refreshTimeout");
     var Timeout = class {
+      static {
+        __name(this, "Timeout");
+      }
       constructor(callback, delay, opaque) {
         this.callback = callback;
         this.delay = delay;
@@ -6169,6 +6409,9 @@ var require_request2 = __commonJS({
       channels.error = { hasSubscribers: false };
     }
     var Request = class _Request {
+      static {
+        __name(this, "Request");
+      }
       constructor(origin, {
         path,
         method,
@@ -6400,6 +6643,7 @@ var require_request2 = __commonJS({
       return skipAppend ? val : `${key}: ${val}\r
 `;
     }
+    __name(processHeaderValue, "processHeaderValue");
     function processHeader(request, key, val, skipAppend = false) {
       if (val && (typeof val === "object" && !Array.isArray(val))) {
         throw new InvalidArgumentError(`invalid ${key} header`);
@@ -6459,6 +6703,7 @@ var require_request2 = __commonJS({
         }
       }
     }
+    __name(processHeader, "processHeader");
     module2.exports = Request;
   }
 });
@@ -6475,6 +6720,9 @@ var require_connect = __commonJS({
     var SessionCache;
     if (global.FinalizationRegistry && !process.env.NODE_V8_COVERAGE) {
       SessionCache = class WeakSessionCache {
+        static {
+          __name(this, "WeakSessionCache");
+        }
         constructor(maxCachedSessions) {
           this._maxCachedSessions = maxCachedSessions;
           this._sessionCache = /* @__PURE__ */ new Map();
@@ -6502,6 +6750,9 @@ var require_connect = __commonJS({
       };
     } else {
       SessionCache = class SimpleSessionCache {
+        static {
+          __name(this, "SimpleSessionCache");
+        }
         constructor(maxCachedSessions) {
           this._maxCachedSessions = maxCachedSessions;
           this._sessionCache = /* @__PURE__ */ new Map();
@@ -6529,7 +6780,7 @@ var require_connect = __commonJS({
       const sessionCache = new SessionCache(maxCachedSessions == null ? 100 : maxCachedSessions);
       timeout = timeout == null ? 1e4 : timeout;
       allowH2 = allowH2 != null ? allowH2 : false;
-      return function connect({ hostname, host, protocol, port, servername, localAddress, httpSocket }, callback) {
+      return /* @__PURE__ */ __name(function connect({ hostname, host, protocol, port, servername, localAddress, httpSocket }, callback) {
         let socket;
         if (protocol === "https:") {
           if (!tls) {
@@ -6588,8 +6839,9 @@ var require_connect = __commonJS({
           }
         });
         return socket;
-      };
+      }, "connect");
     }
+    __name(buildConnector, "buildConnector");
     function setupTimeout(onConnectTimeout2, timeout) {
       if (!timeout) {
         return () => {
@@ -6612,9 +6864,11 @@ var require_connect = __commonJS({
         clearImmediate(s2);
       };
     }
+    __name(setupTimeout, "setupTimeout");
     function onConnectTimeout(socket) {
       util.destroy(socket, new ConnectTimeoutError());
     }
+    __name(onConnectTimeout, "onConnectTimeout");
     module2.exports = buildConnector;
   }
 });
@@ -6635,6 +6889,7 @@ var require_utils = __commonJS({
       });
       return res;
     }
+    __name(enumToMap, "enumToMap");
     exports2.enumToMap = enumToMap;
   }
 });
@@ -6972,6 +7227,9 @@ var require_RedirectHandler = __commonJS({
     var redirectableStatusCodes = [300, 301, 302, 303, 307, 308];
     var kBody = Symbol("body");
     var BodyAsyncIterable = class {
+      static {
+        __name(this, "BodyAsyncIterable");
+      }
       constructor(body) {
         this[kBody] = body;
         this[kBodyUsed] = false;
@@ -6983,6 +7241,9 @@ var require_RedirectHandler = __commonJS({
       }
     };
     var RedirectHandler = class {
+      static {
+        __name(this, "RedirectHandler");
+      }
       constructor(dispatch, maxRedirections, opts, handler) {
         if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) {
           throw new InvalidArgumentError("maxRedirections must be a positive number");
@@ -7074,9 +7335,11 @@ var require_RedirectHandler = __commonJS({
         }
       }
     }
+    __name(parseLocation, "parseLocation");
     function shouldRemoveHeader(header, removeContent, unknownOrigin) {
       return header.length === 4 && header.toString().toLowerCase() === "host" || removeContent && header.toString().toLowerCase().indexOf("content-") === 0 || unknownOrigin && header.length === 13 && header.toString().toLowerCase() === "authorization" || unknownOrigin && header.length === 6 && header.toString().toLowerCase() === "cookie";
     }
+    __name(shouldRemoveHeader, "shouldRemoveHeader");
     function cleanRequestHeaders(headers, removeContent, unknownOrigin) {
       const ret = [];
       if (Array.isArray(headers)) {
@@ -7096,6 +7359,7 @@ var require_RedirectHandler = __commonJS({
       }
       return ret;
     }
+    __name(cleanRequestHeaders, "cleanRequestHeaders");
     module2.exports = RedirectHandler;
   }
 });
@@ -7107,7 +7371,7 @@ var require_redirectInterceptor = __commonJS({
     var RedirectHandler = require_RedirectHandler();
     function createRedirectInterceptor({ maxRedirections: defaultMaxRedirections }) {
       return (dispatch) => {
-        return function Intercept(opts, handler) {
+        return /* @__PURE__ */ __name(function Intercept(opts, handler) {
           const { maxRedirections = defaultMaxRedirections } = opts;
           if (!maxRedirections) {
             return dispatch(opts, handler);
@@ -7115,9 +7379,10 @@ var require_redirectInterceptor = __commonJS({
           const redirectHandler = new RedirectHandler(dispatch, maxRedirections, opts, handler);
           opts = { ...opts, maxRedirections: 0 };
           return dispatch(opts, redirectHandler);
-        };
+        }, "Intercept");
       };
     }
+    __name(createRedirectInterceptor, "createRedirectInterceptor");
     module2.exports = createRedirectInterceptor;
   }
 });
@@ -7249,6 +7514,9 @@ var require_client = __commonJS({
       channels.connected = { hasSubscribers: false };
     }
     var Client = class extends DispatcherBase {
+      static {
+        __name(this, "Client");
+      }
       /**
        *
        * @param {string|URL} url
@@ -7456,13 +7724,13 @@ var require_client = __commonJS({
             const request = requests[i];
             errorRequest(this, request, err);
           }
-          const callback = () => {
+          const callback = /* @__PURE__ */ __name(() => {
             if (this[kClosedResolve]) {
               this[kClosedResolve]();
               this[kClosedResolve] = null;
             }
             resolve();
-          };
+          }, "callback");
           if (this[kHTTP2Session] != null) {
             util.destroy(this[kHTTP2Session], err);
             this[kHTTP2Session] = null;
@@ -7482,6 +7750,7 @@ var require_client = __commonJS({
       this[kSocket][kError] = err;
       onError(this[kClient], err);
     }
+    __name(onHttp2SessionError, "onHttp2SessionError");
     function onHttp2FrameError(type, code, id) {
       const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`);
       if (id === 0) {
@@ -7489,10 +7758,12 @@ var require_client = __commonJS({
         onError(this[kClient], err);
       }
     }
+    __name(onHttp2FrameError, "onHttp2FrameError");
     function onHttp2SessionEnd() {
       util.destroy(this, new SocketError("other side closed"));
       util.destroy(this[kSocket], new SocketError("other side closed"));
     }
+    __name(onHttp2SessionEnd, "onHttp2SessionEnd");
     function onHTTP2GoAway(code) {
       const client = this[kClient];
       const err = new InformationalError(`HTTP/2: "GOAWAY" frame received with code ${code}`);
@@ -7520,6 +7791,7 @@ var require_client = __commonJS({
       );
       resume(client);
     }
+    __name(onHTTP2GoAway, "onHTTP2GoAway");
     var constants = require_constants2();
     var createRedirectInterceptor = require_redirectInterceptor();
     var EMPTY_BUF = Buffer.alloc(0);
@@ -7573,6 +7845,7 @@ var require_client = __commonJS({
         }
       });
     }
+    __name(lazyllhttp, "lazyllhttp");
     var llhttpInstance = null;
     var llhttpPromise = lazyllhttp();
     llhttpPromise.catch();
@@ -7584,6 +7857,9 @@ var require_client = __commonJS({
     var TIMEOUT_BODY = 2;
     var TIMEOUT_IDLE = 3;
     var Parser = class {
+      static {
+        __name(this, "Parser");
+      }
       constructor(client, socket, { exports: exports3 }) {
         assert(Number.isFinite(client[kMaxHeadersSize]) && client[kMaxHeadersSize] > 0);
         this.llhttp = exports3;
@@ -7960,10 +8236,14 @@ var require_client = __commonJS({
         util.destroy(socket, new InformationalError("socket idle timeout"));
       }
     }
+    __name(onParserTimeout, "onParserTimeout");
     function onSocketReadable() {
       const { [kParser]: parser } = this;
-      parser.readMore();
+      if (parser) {
+        parser.readMore();
+      }
     }
+    __name(onSocketReadable, "onSocketReadable");
     function onSocketError(err) {
       const { [kClient]: client, [kParser]: parser } = this;
       assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID");
@@ -7976,6 +8256,7 @@ var require_client = __commonJS({
       this[kError] = err;
       onError(this[kClient], err);
     }
+    __name(onSocketError, "onSocketError");
     function onError(client, err) {
       if (client[kRunning] === 0 && err.code !== "UND_ERR_INFO" && err.code !== "UND_ERR_SOCKET") {
         assert(client[kPendingIdx] === client[kRunningIdx]);
@@ -7987,6 +8268,7 @@ var require_client = __commonJS({
         assert(client[kSize] === 0);
       }
     }
+    __name(onError, "onError");
     function onSocketEnd() {
       const { [kParser]: parser, [kClient]: client } = this;
       if (client[kHTTPConnVersion] !== "h2") {
@@ -7997,6 +8279,7 @@ var require_client = __commonJS({
       }
       util.destroy(this, new SocketError("other side closed", util.getSocketInfo(this)));
     }
+    __name(onSocketEnd, "onSocketEnd");
     function onSocketClose() {
       const { [kClient]: client, [kParser]: parser } = this;
       if (client[kHTTPConnVersion] === "h1" && parser) {
@@ -8025,6 +8308,7 @@ var require_client = __commonJS({
       client.emit("disconnect", client[kUrl], [client], err);
       resume(client);
     }
+    __name(onSocketClose, "onSocketClose");
     async function connect(client) {
       assert(!client[kConnecting]);
       assert(!client[kSocket]);
@@ -8161,10 +8445,12 @@ var require_client = __commonJS({
       }
       resume(client);
     }
+    __name(connect, "connect");
     function emitDrain(client) {
       client[kNeedDrain] = 0;
       client.emit("drain", client[kUrl], [client]);
     }
+    __name(emitDrain, "emitDrain");
     function resume(client, sync) {
       if (client[kResuming] === 2) {
         return;
@@ -8178,6 +8464,7 @@ var require_client = __commonJS({
         client[kRunningIdx] = 0;
       }
     }
+    __name(resume, "resume");
     function _resume(client, sync) {
       while (true) {
         if (client.destroyed) {
@@ -8280,6 +8567,7 @@ var require_client = __commonJS({
         }
       }
     }
+    __name(_resume, "_resume");
     function write(client, request) {
       if (client[kHTTPConnVersion] === "h2") {
         writeH2(client, client[kHTTP2Session], request);
@@ -8396,6 +8684,7 @@ upgrade: ${upgrade}\r
       }
       return true;
     }
+    __name(write, "write");
     function writeH2(client, session, request) {
       const { body, method, path, host, upgrade, expectContinue, signal, headers: reqHeaders } = request;
       let headers;
@@ -8574,13 +8863,16 @@ upgrade: ${upgrade}\r
           assert(false);
         }
       }
+      __name(writeBodyH2, "writeBodyH2");
     }
+    __name(writeH2, "writeH2");
     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") {
         let onPipeData = function(chunk) {
           request.onBodySent(chunk);
         };
+        __name(onPipeData, "onPipeData");
         const pipe = pipeline(
           body,
           h2stream,
@@ -8602,7 +8894,7 @@ upgrade: ${upgrade}\r
       }
       let finished = false;
       const writer = new AsyncWriter({ socket, request, contentLength, client, expectsPayload, header });
-      const onData = function(chunk) {
+      const onData = /* @__PURE__ */ __name(function(chunk) {
         if (finished) {
           return;
         }
@@ -8613,19 +8905,19 @@ upgrade: ${upgrade}\r
         } catch (err) {
           util.destroy(this, err);
         }
-      };
-      const onDrain = function() {
+      }, "onData");
+      const onDrain = /* @__PURE__ */ __name(function() {
         if (finished) {
           return;
         }
         if (body.resume) {
           body.resume();
         }
-      };
-      const onAbort = function() {
+      }, "onDrain");
+      const onAbort = /* @__PURE__ */ __name(function() {
         onFinished(new RequestAbortedError());
-      };
-      const onFinished = function(err) {
+      }, "onAbort");
+      const onFinished = /* @__PURE__ */ __name(function(err) {
         if (finished) {
           return;
         }
@@ -8646,13 +8938,14 @@ upgrade: ${upgrade}\r
         } else {
           util.destroy(body);
         }
-      };
+      }, "onFinished");
       body.on("data", onData).on("end", onFinished).on("error", onFinished).on("close", onAbort);
       if (body.resume) {
         body.resume();
       }
       socket.on("drain", onDrain).on("error", onFinished);
     }
+    __name(writeStream, "writeStream");
     async function writeBlob({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) {
       assert(contentLength === body.size, "blob body must have content length");
       const isH2 = client[kHTTPConnVersion] === "h2";
@@ -8683,6 +8976,7 @@ upgrade: ${upgrade}\r
         util.destroy(isH2 ? h2stream : socket, err);
       }
     }
+    __name(writeBlob, "writeBlob");
     async function writeIterable({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) {
       assert(contentLength !== 0 || client[kRunning] === 0, "iterator body cannot be pipelined");
       let callback = null;
@@ -8693,14 +8987,15 @@ upgrade: ${upgrade}\r
           cb();
         }
       }
-      const waitForDrain = () => new Promise((resolve, reject) => {
+      __name(onDrain, "onDrain");
+      const waitForDrain = /* @__PURE__ */ __name(() => new Promise((resolve, reject) => {
         assert(callback === null);
         if (socket[kError]) {
           reject(socket[kError]);
         } else {
           callback = resolve;
         }
-      });
+      }), "waitForDrain");
       if (client[kHTTPConnVersion] === "h2") {
         h2stream.on("close", onDrain).on("drain", onDrain);
         try {
@@ -8741,7 +9036,11 @@ upgrade: ${upgrade}\r
         socket.off("close", onDrain).off("drain", onDrain);
       }
     }
+    __name(writeIterable, "writeIterable");
     var AsyncWriter = class {
+      static {
+        __name(this, "AsyncWriter");
+      }
       constructor({ socket, request, contentLength, client, expectsPayload, header }) {
         this.socket = socket;
         this.request = request;
@@ -8855,6 +9154,7 @@ ${len.toString(16)}\r
         client.emit("error", err2);
       }
     }
+    __name(errorRequest, "errorRequest");
     module2.exports = Client;
   }
 });
@@ -8883,7 +9183,11 @@ var require_pool = __commonJS({
     function defaultFactory(origin, opts) {
       return new Client(origin, opts);
     }
+    __name(defaultFactory, "defaultFactory");
     var Pool = class extends PoolBase {
+      static {
+        __name(this, "Pool");
+      }
       constructor(origin, {
         connections,
         factory = defaultFactory,
@@ -8964,7 +9268,11 @@ var require_agent = __commonJS({
     function defaultFactory(origin, opts) {
       return opts && opts.connections === 1 ? new Client(origin, opts) : new Pool(origin, opts);
     }
+    __name(defaultFactory, "defaultFactory");
     var Agent = class extends DispatcherBase {
+      static {
+        __name(this, "Agent");
+      }
       constructor({ factory = defaultFactory, maxRedirections = 0, connect, ...options } = {}) {
         super();
         if (typeof factory !== "function") {
@@ -9080,9 +9388,11 @@ var require_global2 = __commonJS({
         configurable: false
       });
     }
+    __name(setGlobalDispatcher, "setGlobalDispatcher");
     function getGlobalDispatcher() {
       return globalThis[globalDispatcher];
     }
+    __name(getGlobalDispatcher, "getGlobalDispatcher");
     module2.exports = {
       setGlobalDispatcher,
       getGlobalDispatcher
@@ -9093,7 +9403,7 @@ var require_global2 = __commonJS({
 // lib/fetch/index.js
 var require_fetch = __commonJS({
   "lib/fetch/index.js"(exports2, module2) {
-    var esbuildDetection = 1;
+    "use strict";
     var {
       Response,
       makeNetworkError,
@@ -9157,6 +9467,9 @@ var require_fetch = __commonJS({
     var resolveObjectURL;
     var ReadableStream = globalThis.ReadableStream;
     var Fetch = class extends EE {
+      static {
+        __name(this, "Fetch");
+      }
       constructor(dispatcher) {
         super();
         this.dispatcher = dispatcher;
@@ -9219,8 +9532,8 @@ var require_fetch = __commonJS({
           abortFetch(p, request, responseObject, requestObject.signal.reason);
         }
       );
-      const handleFetchDone = (response) => finalizeAndReportTiming(response, "fetch");
-      const processResponse = (response) => {
+      const handleFetchDone = /* @__PURE__ */ __name((response) => finalizeAndReportTiming(response, "fetch"), "handleFetchDone");
+      const processResponse = /* @__PURE__ */ __name((response) => {
         if (locallyAborted) {
           return;
         }
@@ -9241,7 +9554,7 @@ var require_fetch = __commonJS({
         responseObject[kHeaders][kGuard] = "immutable";
         responseObject[kHeaders][kRealm] = relevantRealm;
         p.resolve(responseObject);
-      };
+      }, "processResponse");
       controller = fetching({
         request,
         processResponseEndOfBody: handleFetchDone,
@@ -9251,6 +9564,7 @@ var require_fetch = __commonJS({
       });
       return p.promise;
     }
+    __name(fetch2, "fetch");
     function finalizeAndReportTiming(response, initiatorType = "other") {
       if (response.type === "error" && response.aborted) {
         return;
@@ -9283,11 +9597,13 @@ var require_fetch = __commonJS({
         cacheState
       );
     }
+    __name(finalizeAndReportTiming, "finalizeAndReportTiming");
     function markResourceTiming(timingInfo, originalURL, initiatorType, globalThis2, cacheState) {
       if (nodeMajor > 18 || nodeMajor === 18 && nodeMinor >= 2) {
         performance.markResourceTiming(timingInfo, originalURL.href, initiatorType, globalThis2, cacheState);
       }
     }
+    __name(markResourceTiming, "markResourceTiming");
     function abortFetch(p, request, responseObject, error) {
       if (!error) {
         error = new DOMException("The operation was aborted.", "AbortError");
@@ -9314,6 +9630,7 @@ var require_fetch = __commonJS({
         });
       }
     }
+    __name(abortFetch, "abortFetch");
     function fetching({
       request,
       processRequestBodyChunkLength,
@@ -9379,6 +9696,7 @@ var require_fetch = __commonJS({
       });
       return fetchParams.controller;
     }
+    __name(fetching, "fetching");
     async function mainFetch(fetchParams, recursive = false) {
       const request = fetchParams.request;
       let response = null;
@@ -9458,24 +9776,25 @@ var require_fetch = __commonJS({
         fetchParams.controller.dump = true;
       }
       if (request.integrity) {
-        const processBodyError = (reason) => fetchFinale(fetchParams, makeNetworkError(reason));
+        const processBodyError = /* @__PURE__ */ __name((reason) => fetchFinale(fetchParams, makeNetworkError(reason)), "processBodyError");
         if (request.responseTainting === "opaque" || response.body == null) {
           processBodyError(response.error);
           return;
         }
-        const processBody = (bytes) => {
+        const processBody = /* @__PURE__ */ __name((bytes) => {
           if (!bytesMatch(bytes, request.integrity)) {
             processBodyError("integrity mismatch");
             return;
           }
           response.body = safelyExtractBody(bytes)[0];
           fetchFinale(fetchParams, response);
-        };
+        }, "processBody");
         await fullyReadBody(response.body, processBody, processBodyError);
       } else {
         fetchFinale(fetchParams, response);
       }
     }
+    __name(mainFetch, "mainFetch");
     async function schemeFetch(fetchParams) {
       if (isCancelled(fetchParams) && fetchParams.request.redirectCount === 0) {
         return makeAppropriateNetworkError(fetchParams);
@@ -9539,12 +9858,14 @@ var require_fetch = __commonJS({
         }
       }
     }
+    __name(schemeFetch, "schemeFetch");
     function finalizeResponse(fetchParams, response) {
       fetchParams.request.done = true;
       if (fetchParams.processResponseDone != null) {
         queueMicrotask(() => fetchParams.processResponseDone(response));
       }
     }
+    __name(finalizeResponse, "finalizeResponse");
     async function fetchFinale(fetchParams, response) {
       if (response.type === "error") {
         response.urlList = [fetchParams.request.urlList[0]];
@@ -9552,21 +9873,21 @@ var require_fetch = __commonJS({
           startTime: fetchParams.timingInfo.startTime
         });
       }
-      const processResponseEndOfBody = () => {
+      const processResponseEndOfBody = /* @__PURE__ */ __name(() => {
         fetchParams.request.done = true;
         if (fetchParams.processResponseEndOfBody != null) {
           queueMicrotask(() => fetchParams.processResponseEndOfBody(response));
         }
-      };
+      }, "processResponseEndOfBody");
       if (fetchParams.processResponse != null) {
         queueMicrotask(() => fetchParams.processResponse(response));
       }
       if (response.body == null) {
         processResponseEndOfBody();
       } else {
-        const identityTransformAlgorithm = (chunk, controller) => {
+        const identityTransformAlgorithm = /* @__PURE__ */ __name((chunk, controller) => {
           controller.enqueue(chunk);
-        };
+        }, "identityTransformAlgorithm");
         const transformStream = new TransformStream({
           start() {
           },
@@ -9584,8 +9905,8 @@ var require_fetch = __commonJS({
         response.body = { stream: response.body.stream.pipeThrough(transformStream) };
       }
       if (fetchParams.processResponseConsumeBody != null) {
-        const processBody = (nullOrBytes) => fetchParams.processResponseConsumeBody(response, nullOrBytes);
-        const processBodyError = (failure) => fetchParams.processResponseConsumeBody(response, failure);
+        const processBody = /* @__PURE__ */ __name((nullOrBytes) => fetchParams.processResponseConsumeBody(response, nullOrBytes), "processBody");
+        const processBodyError = /* @__PURE__ */ __name((failure) => fetchParams.processResponseConsumeBody(response, failure), "processBodyError");
         if (response.body == null) {
           queueMicrotask(() => processBody(null));
         } else {
@@ -9593,6 +9914,7 @@ var require_fetch = __commonJS({
         }
       }
     }
+    __name(fetchFinale, "fetchFinale");
     async function httpFetch(fetchParams) {
       const request = fetchParams.request;
       let response = null;
@@ -9637,6 +9959,7 @@ var require_fetch = __commonJS({
       response.timingInfo = timingInfo;
       return response;
     }
+    __name(httpFetch, "httpFetch");
     async function httpRedirectFetch(fetchParams, response) {
       const request = fetchParams.request;
       const actualResponse = response.internalResponse ? response.internalResponse : response;
@@ -9695,6 +10018,7 @@ var require_fetch = __commonJS({
       setRequestReferrerPolicyOnRedirect(request, actualResponse);
       return mainFetch(fetchParams, true);
     }
+    __name(httpRedirectFetch, "httpRedirectFetch");
     async function httpNetworkOrCacheFetch(fetchParams, isAuthenticationFetch = false, isNewConnectionFetch = false) {
       const request = fetchParams.request;
       let httpFetchParams = null;
@@ -9730,7 +10054,7 @@ var require_fetch = __commonJS({
       appendRequestOriginHeader(httpRequest);
       appendFetchMetadata(httpRequest);
       if (!httpRequest.headersList.contains("user-agent")) {
-        httpRequest.headersList.append("user-agent", typeof esbuildDetection === "undefined" ? "undici" : "node");
+        httpRequest.headersList.append("user-agent", false ? "undici" : "node");
       }
       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";
@@ -9815,6 +10139,7 @@ var require_fetch = __commonJS({
       }
       return response;
     }
+    __name(httpNetworkOrCacheFetch, "httpNetworkOrCacheFetch");
     async function httpNetworkFetch(fetchParams, includeCredentials = false, forceNewConnection = false) {
       assert(!fetchParams.controller.connection || fetchParams.controller.connection.destroyed);
       fetchParams.controller.connection = {
@@ -9842,22 +10167,22 @@ var require_fetch = __commonJS({
       if (request.body == null && fetchParams.processRequestEndOfBody) {
         queueMicrotask(() => fetchParams.processRequestEndOfBody());
       } else if (request.body != null) {
-        const processBodyChunk = async function* (bytes) {
+        const processBodyChunk = /* @__PURE__ */ __name(async function* (bytes) {
           if (isCancelled(fetchParams)) {
             return;
           }
           yield bytes;
           fetchParams.processRequestBodyChunkLength?.(bytes.byteLength);
-        };
-        const processEndOfBody = () => {
+        }, "processBodyChunk");
+        const processEndOfBody = /* @__PURE__ */ __name(() => {
           if (isCancelled(fetchParams)) {
             return;
           }
           if (fetchParams.processRequestEndOfBody) {
             fetchParams.processRequestEndOfBody();
           }
-        };
-        const processBodyError = (e) => {
+        }, "processEndOfBody");
+        const processBodyError = /* @__PURE__ */ __name((e) => {
           if (isCancelled(fetchParams)) {
             return;
           }
@@ -9866,7 +10191,7 @@ var require_fetch = __commonJS({
           } else {
             fetchParams.controller.terminate(e);
           }
-        };
+        }, "processBodyError");
         requestBody = async function* () {
           try {
             for await (const bytes of request.body.stream) {
@@ -9894,12 +10219,12 @@ var require_fetch = __commonJS({
         }
         return makeNetworkError(err);
       }
-      const pullAlgorithm = () => {
+      const pullAlgorithm = /* @__PURE__ */ __name(() => {
         fetchParams.controller.resume();
-      };
-      const cancelAlgorithm = (reason) => {
+      }, "pullAlgorithm");
+      const cancelAlgorithm = /* @__PURE__ */ __name((reason) => {
         fetchParams.controller.abort(reason);
-      };
+      }, "cancelAlgorithm");
       if (!ReadableStream) {
         ReadableStream = require("stream/web").ReadableStream;
       }
@@ -9979,6 +10304,7 @@ var require_fetch = __commonJS({
         }
         fetchParams.controller.connection.destroy();
       }
+      __name(onAborted, "onAborted");
       return response;
       async function dispatch({ body }) {
         const url = requestCurrentURL(request);
@@ -10113,7 +10439,9 @@ var require_fetch = __commonJS({
           }
         ));
       }
+      __name(dispatch, "dispatch");
     }
+    __name(httpNetworkFetch, "httpNetworkFetch");
     module2.exports = {
       fetch: fetch2,
       Fetch,
@@ -10192,6 +10520,9 @@ var require_events = __commonJS({
     var { kEnumerableProperty } = require_util();
     var { MessagePort } = require("worker_threads");
     var MessageEvent = class _MessageEvent extends Event {
+      static {
+        __name(this, "MessageEvent");
+      }
       #eventInit;
       constructor(type, eventInitDict = {}) {
         webidl.argumentLengthCheck(arguments, 1, { header: "MessageEvent constructor" });
@@ -10238,6 +10569,9 @@ var require_events = __commonJS({
       }
     };
     var CloseEvent = class _CloseEvent extends Event {
+      static {
+        __name(this, "CloseEvent");
+      }
       #eventInit;
       constructor(type, eventInitDict = {}) {
         webidl.argumentLengthCheck(arguments, 1, { header: "CloseEvent constructor" });
@@ -10260,6 +10594,9 @@ var require_events = __commonJS({
       }
     };
     var ErrorEvent = class _ErrorEvent extends Event {
+      static {
+        __name(this, "ErrorEvent");
+      }
       #eventInit;
       constructor(type, eventInitDict) {
         webidl.argumentLengthCheck(arguments, 1, { header: "ErrorEvent constructor" });
@@ -10437,16 +10774,20 @@ var require_util3 = __commonJS({
     function isEstablished(ws) {
       return ws[kReadyState] === states.OPEN;
     }
+    __name(isEstablished, "isEstablished");
     function isClosing(ws) {
       return ws[kReadyState] === states.CLOSING;
     }
+    __name(isClosing, "isClosing");
     function isClosed(ws) {
       return ws[kReadyState] === states.CLOSED;
     }
+    __name(isClosed, "isClosed");
     function fireEvent(e, target, eventConstructor = Event, eventInitDict) {
       const event = new eventConstructor(e, eventInitDict);
       target.dispatchEvent(event);
     }
+    __name(fireEvent, "fireEvent");
     function websocketMessageReceived(ws, type, data) {
       if (ws[kReadyState] !== states.OPEN) {
         return;
@@ -10471,6 +10812,7 @@ var require_util3 = __commonJS({
         data: dataForEvent
       });
     }
+    __name(websocketMessageReceived, "websocketMessageReceived");
     function isValidSubprotocol(protocol) {
       if (protocol.length === 0) {
         return false;
@@ -10484,6 +10826,7 @@ var require_util3 = __commonJS({
       }
       return true;
     }
+    __name(isValidSubprotocol, "isValidSubprotocol");
     function isValidStatusCode(code) {
       if (code >= 1e3 && code < 1015) {
         return code !== 1004 && // reserved
@@ -10492,6 +10835,7 @@ var require_util3 = __commonJS({
       }
       return code >= 3e3 && code <= 4999;
     }
+    __name(isValidStatusCode, "isValidStatusCode");
     function failWebsocketConnection(ws, reason) {
       const { [kController]: controller, [kResponse]: response } = ws;
       controller.abort();
@@ -10504,6 +10848,7 @@ var require_util3 = __commonJS({
         });
       }
     }
+    __name(failWebsocketConnection, "failWebsocketConnection");
     module2.exports = {
       isEstablished,
       isClosing,
@@ -10620,11 +10965,13 @@ var require_connection = __commonJS({
       });
       return controller;
     }
+    __name(establishWebSocketConnection, "establishWebSocketConnection");
     function onSocketData(chunk) {
       if (!this.ws[kByteParser].write(chunk)) {
         this.pause();
       }
     }
+    __name(onSocketData, "onSocketData");
     function onSocketClose() {
       const { ws } = this;
       const wasClean = ws[kSentClose] && ws[kReceivedClose];
@@ -10651,6 +10998,7 @@ var require_connection = __commonJS({
         });
       }
     }
+    __name(onSocketClose, "onSocketClose");
     function onSocketError(error) {
       const { ws } = this;
       ws[kReadyState] = states.CLOSING;
@@ -10659,6 +11007,7 @@ var require_connection = __commonJS({
       }
       this.destroy();
     }
+    __name(onSocketError, "onSocketError");
     module2.exports = {
       establishWebSocketConnection
     };
@@ -10676,6 +11025,9 @@ var require_frame = __commonJS({
     } catch {
     }
     var WebsocketFrameSend = class {
+      static {
+        __name(this, "WebsocketFrameSend");
+      }
       /**
        * @param {Buffer|undefined} data
        */
@@ -10736,6 +11088,9 @@ var require_receiver = __commonJS({
     channels.ping = diagnosticsChannel.channel("undici:websocket:ping");
     channels.pong = diagnosticsChannel.channel("undici:websocket:pong");
     var ByteParser = class extends Writable {
+      static {
+        __name(this, "ByteParser");
+      }
       #buffers = [];
       #byteOffset = 0;
       #state = parserStates.INFO;
@@ -10985,6 +11340,9 @@ var require_websocket = __commonJS({
     var { types } = require("util");
     var experimentalWarned = false;
     var WebSocket = class _WebSocket extends EventTarget {
+      static {
+        __name(this, "WebSocket");
+      }
       #events = {
         open: null,
         error: null,
@@ -11260,9 +11618,9 @@ var require_websocket = __commonJS({
       #onConnectionEstablished(response) {
         this[kResponse] = response;
         const parser = new ByteParser(this);
-        parser.on("drain", function onParserDrain() {
+        parser.on("drain", /* @__PURE__ */ __name(function onParserDrain() {
           this.ws[kResponse].socket.resume();
-        });
+        }, "onParserDrain"));
         response.socket.ws = this;
         this[kByteParser] = parser;
         this[kReadyState] = states.OPEN;
@@ -11365,14 +11723,14 @@ var require_websocket = __commonJS({
 
 // index-fetch.js
 var fetchImpl = require_fetch().fetch;
-module.exports.fetch = async function fetch(resource, init = void 0) {
+module.exports.fetch = /* @__PURE__ */ __name(async function fetch(resource, init = void 0) {
   try {
     return await fetchImpl(resource, init);
   } catch (err) {
     Error.captureStackTrace(err, this);
     throw err;
   }
-};
+}, "fetch");
 module.exports.FormData = require_formdata().FormData;
 module.exports.Headers = require_headers().Headers;
 module.exports.Response = require_response().Response;
diff --git a/deps/uvwasi/include/uvwasi.h b/deps/uvwasi/include/uvwasi.h
index d475d3e67512bf..a458cfe17daaa3 100644
--- a/deps/uvwasi/include/uvwasi.h
+++ b/deps/uvwasi/include/uvwasi.h
@@ -5,12 +5,13 @@
 extern "C" {
 #endif
 
+#include "uv.h"
 #include "wasi_serdes.h"
 #include "wasi_types.h"
 
 #define UVWASI_VERSION_MAJOR 0
 #define UVWASI_VERSION_MINOR 0
-#define UVWASI_VERSION_PATCH 18
+#define UVWASI_VERSION_PATCH 19
 #define UVWASI_VERSION_HEX ((UVWASI_VERSION_MAJOR << 16) | \
                             (UVWASI_VERSION_MINOR <<  8) | \
                             (UVWASI_VERSION_PATCH))
@@ -47,6 +48,7 @@ typedef struct uvwasi_s {
   char* env_buf;
   uvwasi_size_t env_buf_size;
   const uvwasi_mem_t* allocator;
+  uv_loop_t* loop;
 } uvwasi_t;
 
 typedef struct uvwasi_preopen_s {
@@ -54,10 +56,17 @@ typedef struct uvwasi_preopen_s {
   const char* real_path;
 } uvwasi_preopen_t;
 
+typedef struct uvwasi_preopen_socket_s {
+  const char* address;
+  int port;
+} uvwasi_preopen_socket_t;
+
 typedef struct uvwasi_options_s {
   uvwasi_size_t fd_table_size;
   uvwasi_size_t preopenc;
   uvwasi_preopen_t* preopens;
+  uvwasi_size_t preopen_socketc;
+  uvwasi_preopen_socket_t* preopen_sockets;
   uvwasi_size_t argc;
   const char** argv;
   const char** envp;
diff --git a/deps/uvwasi/src/fd_table.c b/deps/uvwasi/src/fd_table.c
index 7782f1ee43b420..881d192ff3a340 100644
--- a/deps/uvwasi/src/fd_table.c
+++ b/deps/uvwasi/src/fd_table.c
@@ -37,6 +37,7 @@ static uvwasi_errno_t uvwasi__insert_stdio(uvwasi_t* uvwasi,
   err = uvwasi_fd_table_insert(uvwasi,
                                table,
                                fd,
+                               NULL,
                                name,
                                name,
                                type,
@@ -58,6 +59,7 @@ static uvwasi_errno_t uvwasi__insert_stdio(uvwasi_t* uvwasi,
 uvwasi_errno_t uvwasi_fd_table_insert(uvwasi_t* uvwasi,
                                       struct uvwasi_fd_table_t* table,
                                       uv_file fd,
+                                      uv_tcp_t* sock,
                                       const char* mapped_path,
                                       const char* real_path,
                                       uvwasi_filetype_t type,
@@ -78,29 +80,40 @@ uvwasi_errno_t uvwasi_fd_table_insert(uvwasi_t* uvwasi,
   char* rp_copy;
   char* np_copy;
 
-  mp_len = strlen(mapped_path);
-  rp_len = strlen(real_path);
+  if (type != UVWASI_FILETYPE_SOCKET_STREAM) {
+    mp_len = strlen(mapped_path);
+    rp_len = strlen(real_path);
+  } else {
+    mp_len = 0;
+    rp_len = 0;
+    rp_copy = NULL;
+    mp_copy = NULL;
+    np_copy = NULL;
+  }
+
   /* Reserve room for the mapped path, real path, and normalized mapped path. */
   entry = (struct uvwasi_fd_wrap_t*)
     uvwasi__malloc(uvwasi, sizeof(*entry) + mp_len + mp_len + rp_len + 3);
   if (entry == NULL)
     return UVWASI_ENOMEM;
 
-  mp_copy = (char*)(entry + 1);
-  rp_copy = mp_copy + mp_len + 1;
-  np_copy = rp_copy + rp_len + 1;
-  memcpy(mp_copy, mapped_path, mp_len);
-  mp_copy[mp_len] = '\0';
-  memcpy(rp_copy, real_path, rp_len);
-  rp_copy[rp_len] = '\0';
-
-  /* Calculate the normalized version of the mapped path, as it will be used for
-     any path calculations on this fd. Use the length of the mapped path as an
-     upper bound for the normalized path length. */
-  err = uvwasi__normalize_path(mp_copy, mp_len, np_copy, mp_len);
-  if (err) {
-    uvwasi__free(uvwasi, entry);
-    goto exit;
+  if (type != UVWASI_FILETYPE_SOCKET_STREAM) {
+    mp_copy = (char*)(entry + 1);
+    rp_copy = mp_copy + mp_len + 1;
+    np_copy = rp_copy + rp_len + 1;
+    memcpy(mp_copy, mapped_path, mp_len);
+    mp_copy[mp_len] = '\0';
+    memcpy(rp_copy, real_path, rp_len);
+    rp_copy[rp_len] = '\0';
+
+    /* Calculate the normalized version of the mapped path, as it will be used for
+       any path calculations on this fd. Use the length of the mapped path as an
+       upper bound for the normalized path length. */
+    err = uvwasi__normalize_path(mp_copy, mp_len, np_copy, mp_len);
+    if (err) {
+      uvwasi__free(uvwasi, entry);
+      goto exit;
+    }
   }
 
   uv_rwlock_wrlock(&table->rwlock);
@@ -150,6 +163,7 @@ uvwasi_errno_t uvwasi_fd_table_insert(uvwasi_t* uvwasi,
 
   entry->id = index;
   entry->fd = fd;
+  entry->sock = sock;
   entry->path = mp_copy;
   entry->real_path = rp_copy;
   entry->normalized_path = np_copy;
@@ -280,6 +294,7 @@ uvwasi_errno_t uvwasi_fd_table_insert_preopen(uvwasi_t* uvwasi,
   return uvwasi_fd_table_insert(uvwasi,
                                 table,
                                 fd,
+                                NULL,
                                 path,
                                 real_path,
                                 UVWASI_FILETYPE_DIRECTORY,
@@ -290,6 +305,26 @@ uvwasi_errno_t uvwasi_fd_table_insert_preopen(uvwasi_t* uvwasi,
 }
 
 
+uvwasi_errno_t uvwasi_fd_table_insert_preopen_socket(uvwasi_t* uvwasi,
+                                              struct uvwasi_fd_table_t* table,
+                                              uv_tcp_t* sock) {
+  if (table == NULL || sock == NULL)
+    return UVWASI_EINVAL;
+
+  return uvwasi_fd_table_insert(uvwasi,
+                                table,
+                                -1,
+                                sock,
+                                NULL,
+                                NULL,
+                                UVWASI_FILETYPE_SOCKET_STREAM,
+                                UVWASI__RIGHTS_SOCKET_BASE,
+                                UVWASI__RIGHTS_SOCKET_INHERITING,
+                                1,
+                                NULL);
+}
+
+
 uvwasi_errno_t uvwasi_fd_table_get(struct uvwasi_fd_table_t* table,
                                    const uvwasi_fd_t id,
                                    struct uvwasi_fd_wrap_t** wrap,
diff --git a/deps/uvwasi/src/fd_table.h b/deps/uvwasi/src/fd_table.h
index 0755c2d17fdec2..9a7a825bc85d4c 100644
--- a/deps/uvwasi/src/fd_table.h
+++ b/deps/uvwasi/src/fd_table.h
@@ -11,6 +11,7 @@ struct uvwasi_options_s;
 struct uvwasi_fd_wrap_t {
   uvwasi_fd_t id;
   uv_file fd;
+  uv_tcp_t* sock;
   char* path;
   char* real_path;
   char* normalized_path;
@@ -35,6 +36,7 @@ void uvwasi_fd_table_free(struct uvwasi_s* uvwasi,
 uvwasi_errno_t uvwasi_fd_table_insert(struct uvwasi_s* uvwasi,
                                       struct uvwasi_fd_table_t* table,
                                       uv_file fd,
+                                      uv_tcp_t* sock,
                                       const char* mapped_path,
                                       const char* real_path,
                                       uvwasi_filetype_t type,
@@ -47,6 +49,9 @@ uvwasi_errno_t uvwasi_fd_table_insert_preopen(struct uvwasi_s* uvwasi,
                                               const uv_file fd,
                                               const char* path,
                                               const char* real_path);
+uvwasi_errno_t uvwasi_fd_table_insert_preopen_socket(struct uvwasi_s* uvwasi,
+                                              struct uvwasi_fd_table_t* table,
+                                              uv_tcp_t* sock);
 uvwasi_errno_t uvwasi_fd_table_get(struct uvwasi_fd_table_t* table,
                                    const uvwasi_fd_t id,
                                    struct uvwasi_fd_wrap_t** wrap,
diff --git a/deps/uvwasi/src/sync_helpers.c b/deps/uvwasi/src/sync_helpers.c
new file mode 100644
index 00000000000000..c63a62b83d75ed
--- /dev/null
+++ b/deps/uvwasi/src/sync_helpers.c
@@ -0,0 +1,95 @@
+#include "uv.h"
+#include "sync_helpers.h"
+#include "uv_mapping.h"
+#include "uvwasi_alloc.h"
+
+typedef struct free_handle_data_s {
+  uvwasi_t* uvwasi;
+  int done;
+} free_handle_data_t;
+
+static void free_handle_cb(uv_handle_t* handle) {
+  free_handle_data_t* free_handle_data = uv_handle_get_data((uv_handle_t*) handle);
+  uvwasi__free(free_handle_data->uvwasi, handle);
+  free_handle_data->done = 1;
+}
+
+int free_handle_sync(struct uvwasi_s* uvwasi, uv_handle_t* handle) {
+  free_handle_data_t free_handle_data = { uvwasi, 0 };
+  uv_handle_set_data(handle, (void*) &free_handle_data);
+  uv_close(handle, free_handle_cb);
+  uv_loop_t* handle_loop = uv_handle_get_loop(handle);
+  while(!free_handle_data.done) {
+    if (uv_run(handle_loop, UV_RUN_ONCE) == 0) {
+      break;
+    }
+  }
+  return UVWASI_ESUCCESS;
+}
+
+static void do_stream_shutdown(uv_shutdown_t* req, int status) {
+  shutdown_data_t* shutdown_data;
+  shutdown_data = uv_handle_get_data((uv_handle_t*) req->handle);
+  shutdown_data->status = status;
+  shutdown_data->done = 1;
+ }
+
+int shutdown_stream_sync(struct uvwasi_s* uvwasi,
+                          uv_stream_t* stream,
+		          shutdown_data_t* shutdown_data) {
+  uv_shutdown_t req; 
+  uv_loop_t* stream_loop;
+
+  shutdown_data->done = 0;
+  shutdown_data->status = 0;
+  stream_loop = uv_handle_get_loop((uv_handle_t*) stream);
+
+  uv_handle_set_data((uv_handle_t*) stream, (void*) shutdown_data);
+  uv_shutdown(&req, stream, do_stream_shutdown);
+  while (!shutdown_data->done) {
+    if (uv_run(stream_loop, UV_RUN_ONCE) == 0) {
+      return UVWASI_ECANCELED;
+    }
+  }
+  return UVWASI_ESUCCESS;
+}
+
+static void recv_alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
+  recv_data_t* recv_data;
+  recv_data = uv_handle_get_data(handle);
+  buf->base = recv_data->base;
+  buf->len = recv_data->len;
+}
+
+void do_stream_recv(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
+  recv_data_t* recv_data;
+  recv_data = uv_handle_get_data((uv_handle_t*) stream);
+  uv_read_stop(stream);
+  recv_data->nread = nread;
+  recv_data->done = 1;
+}
+
+int read_stream_sync(struct uvwasi_s* uvwasi,
+                     uv_stream_t* stream,
+	             recv_data_t* recv_data) {
+  uv_loop_t* recv_loop;
+  int r;
+
+  recv_data->nread = 0;
+  recv_data->done = 0;
+  recv_loop = uv_handle_get_loop((uv_handle_t*) stream);
+
+  uv_handle_set_data((uv_handle_t*) stream, (void*) recv_data);
+  r = uv_read_start(stream, recv_alloc_cb, do_stream_recv);
+  if (r != 0) {
+    return uvwasi__translate_uv_error(r);
+  }
+
+  while (!recv_data->done) {
+    if (uv_run(recv_loop, UV_RUN_ONCE) == 0) {
+      return UVWASI_ECANCELED;
+    }
+ }
+
+  return UVWASI_ESUCCESS;
+}
diff --git a/deps/uvwasi/src/sync_helpers.h b/deps/uvwasi/src/sync_helpers.h
new file mode 100644
index 00000000000000..6ffe2cac133d6c
--- /dev/null
+++ b/deps/uvwasi/src/sync_helpers.h
@@ -0,0 +1,27 @@
+#ifndef __UVWASI_SYNC_HELPERS_H__
+#define __UVWASI_SYNC_HELPERS_H__
+
+struct uvwasi_s;
+
+typedef struct shutdown_data_s {
+  int status;
+  int done;
+} shutdown_data_t;
+
+typedef struct recv_data_s {
+  char* base;
+  size_t len;
+  ssize_t nread;
+  int done;
+} recv_data_t;
+
+int free_handle_sync(struct uvwasi_s* uvwasi, uv_handle_t* handle);
+
+int shutdown_stream_sync(struct uvwasi_s* uvwasi,
+                         uv_stream_t* stream,
+                         shutdown_data_t* shutdown_data);
+
+int read_stream_sync(struct uvwasi_s* uvwasi,
+                     uv_stream_t* stream,
+	             recv_data_t* recv_data);
+#endif /* __UVWASI_SYNC_HELPERS_H__ */
diff --git a/deps/uvwasi/src/uvwasi.c b/deps/uvwasi/src/uvwasi.c
index 9e7fc7681664b8..e904b9f9293864 100644
--- a/deps/uvwasi/src/uvwasi.c
+++ b/deps/uvwasi/src/uvwasi.c
@@ -25,6 +25,7 @@
 #include "clocks.h"
 #include "path_resolver.h"
 #include "poll_oneoff.h"
+#include "sync_helpers.h"
 #include "wasi_rights.h"
 #include "wasi_serdes.h"
 #include "debug.h"
@@ -231,6 +232,13 @@ static uvwasi_errno_t uvwasi__setup_ciovs(const uvwasi_t* uvwasi,
   return UVWASI_ESUCCESS;
 }
 
+typedef struct new_connection_data_s {
+  int done;
+} new_connection_data_t;
+
+void on_new_connection(uv_stream_t *server, int status) {
+  // just do nothing
+}
 
 uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, const uvwasi_options_t* options) {
   uv_fs_t realpath_req;
@@ -243,11 +251,16 @@ uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, const uvwasi_options_t* options) {
   uvwasi_size_t env_buf_size;
   uvwasi_size_t i;
   int r;
+  struct sockaddr_in addr;
 
   if (uvwasi == NULL || options == NULL || options->fd_table_size == 0)
     return UVWASI_EINVAL;
 
+  // loop is only needed if there were pre-open sockets
+  uvwasi->loop = NULL;
+
   uvwasi->allocator = options->allocator;
+
   if (uvwasi->allocator == NULL)
     uvwasi->allocator = &default_allocator;
 
@@ -328,6 +341,14 @@ uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, const uvwasi_options_t* options) {
     }
   }
 
+  for (i = 0; i < options->preopen_socketc; ++i) {
+    if (options->preopen_sockets[i].address == NULL ||
+        options->preopen_sockets[i].port > 65535) {
+      err = UVWASI_EINVAL;
+      goto exit;
+    }
+  }
+
   err = uvwasi_fd_table_init(uvwasi, options);
   if (err != UVWASI_ESUCCESS)
     goto exit;
@@ -363,6 +384,36 @@ uvwasi_errno_t uvwasi_init(uvwasi_t* uvwasi, const uvwasi_options_t* options) {
       goto exit;
   }
 
+  if (options->preopen_socketc > 0) {
+    uvwasi->loop = uvwasi__malloc(uvwasi, sizeof(uv_loop_t));
+    r = uv_loop_init(uvwasi->loop);
+    if (r != 0) {
+      err = uvwasi__translate_uv_error(r);
+      goto exit;
+    }
+  }
+
+  for (i = 0; i < options->preopen_socketc; ++i) {
+    uv_tcp_t* socket = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
+    uv_tcp_init(uvwasi->loop, socket);
+
+    uv_ip4_addr(options->preopen_sockets[i].address, options->preopen_sockets[i].port, &addr);
+
+    uv_tcp_bind(socket, (const struct sockaddr*)&addr, 0);
+    r = uv_listen((uv_stream_t*) socket, 128, on_new_connection);
+    if (r != 0) {
+      err = uvwasi__translate_uv_error(r);
+      goto exit;
+    }
+
+    err = uvwasi_fd_table_insert_preopen_socket(uvwasi,
+                                         uvwasi->fds,
+                                         socket);
+
+    if (err != UVWASI_ESUCCESS)
+      goto exit;
+  }
+
   return UVWASI_ESUCCESS;
 
 exit:
@@ -380,6 +431,12 @@ void uvwasi_destroy(uvwasi_t* uvwasi) {
   uvwasi__free(uvwasi, uvwasi->argv);
   uvwasi__free(uvwasi, uvwasi->env_buf);
   uvwasi__free(uvwasi, uvwasi->env);
+  if (uvwasi->loop != NULL) {
+    uv_stop(uvwasi->loop);
+    uv_loop_close(uvwasi->loop);
+    uvwasi__free(uvwasi, uvwasi->loop);
+    uvwasi->loop = NULL;
+  }
   uvwasi->fds = NULL;
   uvwasi->argv_buf = NULL;
   uvwasi->argv = NULL;
@@ -401,6 +458,8 @@ void uvwasi_options_init(uvwasi_options_t* options) {
   options->envp = NULL;
   options->preopenc = 0;
   options->preopens = NULL;
+  options->preopen_socketc = 0;
+  options->preopen_sockets = NULL;
   options->allocator = NULL;
 }
 
@@ -694,10 +753,9 @@ uvwasi_errno_t uvwasi_fd_allocate(uvwasi_t* uvwasi,
   return err;
 }
 
-
 uvwasi_errno_t uvwasi_fd_close(uvwasi_t* uvwasi, uvwasi_fd_t fd) {
   struct uvwasi_fd_wrap_t* wrap;
-  uvwasi_errno_t err;
+  uvwasi_errno_t err = 0;
   uv_fs_t req;
   int r;
 
@@ -712,9 +770,18 @@ uvwasi_errno_t uvwasi_fd_close(uvwasi_t* uvwasi, uvwasi_fd_t fd) {
   if (err != UVWASI_ESUCCESS)
     goto exit;
 
-  r = uv_fs_close(NULL, &req, wrap->fd, NULL);
-  uv_mutex_unlock(&wrap->mutex);
-  uv_fs_req_cleanup(&req);
+  if (wrap->sock == NULL) {
+    r = uv_fs_close(NULL, &req, wrap->fd, NULL);
+    uv_mutex_unlock(&wrap->mutex);
+    uv_fs_req_cleanup(&req);
+  } else {
+    r = 0;
+    err = free_handle_sync(uvwasi, (uv_handle_t*) wrap->sock);
+    uv_mutex_unlock(&wrap->mutex);
+    if (err != UVWASI_ESUCCESS) {
+      goto exit;
+    }   
+  }
 
   if (r != 0) {
     err = uvwasi__translate_uv_error(r);
@@ -1997,6 +2064,7 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi,
   err = uvwasi_fd_table_insert(uvwasi,
                                uvwasi->fds,
                                r,
+                               NULL,
                                resolved_path,
                                resolved_path,
                                filetype,
@@ -2520,7 +2588,6 @@ uvwasi_errno_t uvwasi_sched_yield(uvwasi_t* uvwasi) {
   return UVWASI_ESUCCESS;
 }
 
-
 uvwasi_errno_t uvwasi_sock_recv(uvwasi_t* uvwasi,
                                 uvwasi_fd_t sock,
                                 const uvwasi_iovec_t* ri_data,
@@ -2528,10 +2595,50 @@ uvwasi_errno_t uvwasi_sock_recv(uvwasi_t* uvwasi,
                                 uvwasi_riflags_t ri_flags,
                                 uvwasi_size_t* ro_datalen,
                                 uvwasi_roflags_t* ro_flags) {
-  /* TODO(cjihrig): Waiting to implement, pending
-                    https://github.com/WebAssembly/WASI/issues/4 */
-  UVWASI_DEBUG("uvwasi_sock_recv(uvwasi=%p, unimplemented)\n", uvwasi);
-  return UVWASI_ENOTSUP;
+  struct uvwasi_fd_wrap_t* wrap;
+  uvwasi_errno_t err = 0;
+  recv_data_t recv_data;
+
+  UVWASI_DEBUG("uvwasi_sock_recv(uvwasi=%p, sock=%d, ri_data=%p, "
+	       "ri_data_len=%d, ri_flags=%d, ro_datalen=%p, ro_flags=%p)\n",
+               uvwasi,
+               sock,
+               ri_data,
+               ri_data_len,
+               ri_flags,
+               ro_datalen,
+               ro_flags);
+
+  if (uvwasi == NULL || ri_data == NULL || ro_datalen == NULL || ro_flags == NULL)
+    return UVWASI_EINVAL;
+
+  if (ri_flags != 0)
+    return UVWASI_ENOTSUP;
+
+  err = uvwasi_fd_table_get(uvwasi->fds,
+                            sock,
+                            &wrap,
+                            UVWASI__RIGHTS_SOCKET_BASE,
+                            0);
+  if (err != UVWASI_ESUCCESS)
+    return err;
+
+  recv_data.base = ri_data->buf;
+  recv_data.len = ri_data->buf_len;
+  err = read_stream_sync(uvwasi, (uv_stream_t*) wrap->sock, &recv_data);
+  uv_mutex_unlock(&wrap->mutex);
+  if (err != 0) {
+    return err;
+  }
+
+  if (recv_data.nread == 0) {
+    return UVWASI_EAGAIN;
+  } else if (recv_data.nread < 0) {
+    return uvwasi__translate_uv_error(recv_data.nread);
+  }
+
+  *ro_datalen = recv_data.nread;
+  return UVWASI_ESUCCESS;
 }
 
 
@@ -2541,30 +2648,195 @@ uvwasi_errno_t uvwasi_sock_send(uvwasi_t* uvwasi,
                                 uvwasi_size_t si_data_len,
                                 uvwasi_siflags_t si_flags,
                                 uvwasi_size_t* so_datalen) {
-  /* TODO(cjihrig): Waiting to implement, pending
-                    https://github.com/WebAssembly/WASI/issues/4 */
-  UVWASI_DEBUG("uvwasi_sock_send(uvwasi=%p, unimplemented)\n", uvwasi);
-  return UVWASI_ENOTSUP;
-}
 
+  struct uvwasi_fd_wrap_t* wrap;
+  uvwasi_errno_t err = 0;
+  uv_buf_t* bufs;
+  int r = 0;
+
+  UVWASI_DEBUG("uvwasi_sock_send(uvwasi=%p, sock=%d, si_data=%p, "
+	       "si_data_len=%d, si_flags=%d, so_datalen=%p)\n",
+               uvwasi,
+               sock,
+               si_data,
+               si_data_len,
+               si_flags,
+               so_datalen);
+
+  if (uvwasi == NULL || si_data == NULL || so_datalen == NULL ||
+      si_flags != 0)
+    return UVWASI_EINVAL;
+
+  err = uvwasi_fd_table_get(uvwasi->fds,
+                            sock,
+                            &wrap,
+                            UVWASI__RIGHTS_SOCKET_BASE,
+                            0);
+  if (err != UVWASI_ESUCCESS)
+    return err;
+
+  err = uvwasi__setup_ciovs(uvwasi, &bufs, si_data, si_data_len);
+  if (err != UVWASI_ESUCCESS) {
+    uv_mutex_unlock(&wrap->mutex);
+    return err;
+  }
+
+  r = uv_try_write((uv_stream_t*) wrap->sock, bufs, si_data_len);
+  uvwasi__free(uvwasi, bufs);
+  uv_mutex_unlock(&wrap->mutex);
+  if (r < 0)
+    return uvwasi__translate_uv_error(r);
+
+  *so_datalen = (uvwasi_size_t) r;
+  return UVWASI_ESUCCESS;
+}
 
 uvwasi_errno_t uvwasi_sock_shutdown(uvwasi_t* uvwasi,
                                     uvwasi_fd_t sock,
                                     uvwasi_sdflags_t how) {
-  /* TODO(cjihrig): Waiting to implement, pending
-                    https://github.com/WebAssembly/WASI/issues/4 */
-  UVWASI_DEBUG("uvwasi_sock_shutdown(uvwasi=%p, unimplemented)\n", uvwasi);
-  return UVWASI_ENOTSUP;
+  struct uvwasi_fd_wrap_t* wrap;
+  uvwasi_errno_t err = 0;
+  shutdown_data_t shutdown_data;
+
+  if (how & ~UVWASI_SHUT_WR)
+    return UVWASI_ENOTSUP;
+
+  UVWASI_DEBUG("uvwasi_sock_shutdown(uvwasi=%p, sock=%d, how=%d)\n",
+               uvwasi,
+               sock,
+               how);
+
+  if (uvwasi == NULL)
+    return UVWASI_EINVAL;
+
+  err = uvwasi_fd_table_get(uvwasi->fds,
+                            sock,
+                            &wrap,
+                            UVWASI__RIGHTS_SOCKET_BASE,
+                            0);
+  if (err != UVWASI_ESUCCESS)
+    return err;
+
+  if (how & UVWASI_SHUT_WR) {
+    err = shutdown_stream_sync(uvwasi, (uv_stream_t*) wrap->sock, &shutdown_data);
+    if (err != UVWASI_ESUCCESS) {
+      uv_mutex_unlock(&wrap->mutex);
+      return err;
+    }
+  }
+
+  uv_mutex_unlock(&wrap->mutex);
+
+  if (shutdown_data.status != 0) 
+    return uvwasi__translate_uv_error(shutdown_data.status);
+
+  return UVWASI_ESUCCESS;
 }
 
 uvwasi_errno_t uvwasi_sock_accept(uvwasi_t* uvwasi,
                                   uvwasi_fd_t sock,
                                   uvwasi_fdflags_t flags,
-                                  uvwasi_fd_t* fd) {
-  /* TODO(mhdawson): Needs implementation */
-  UVWASI_DEBUG("uvwasi_sock_accept(uvwasi=%p, unimplemented)\n", uvwasi);
-  return UVWASI_ENOTSUP;
-};
+                                  uvwasi_fd_t* connect_sock) {
+  struct uvwasi_fd_wrap_t* wrap;
+  struct uvwasi_fd_wrap_t* connected_wrap;
+  uvwasi_errno_t err = 0;
+  uv_loop_t* sock_loop = NULL;
+  int r = 0;
+
+  UVWASI_DEBUG("uvwasi_sock_accept(uvwasi=%p, sock=%d, flags=%d, "
+               "connect_sock=%p)\n",
+               uvwasi,
+               sock,
+               flags,
+               connect_sock);
+
+  if (uvwasi == NULL || connect_sock == NULL)
+    return UVWASI_EINVAL;
+
+  if (flags & ~UVWASI_FDFLAG_NONBLOCK)
+    return UVWASI_ENOTSUP;
+
+  err = uvwasi_fd_table_get(uvwasi->fds,
+                            sock,
+                            &wrap,
+                            UVWASI__RIGHTS_SOCKET_BASE,
+                            0);
+  if (err != UVWASI_ESUCCESS)
+    return err;
+
+  sock_loop = uv_handle_get_loop((uv_handle_t*) wrap->sock);
+  uv_tcp_t* uv_connect_sock = (uv_tcp_t*) uvwasi__malloc(uvwasi, sizeof(uv_tcp_t));
+  uv_tcp_init(sock_loop, uv_connect_sock);
+
+  r = uv_accept((uv_stream_t*) wrap->sock, (uv_stream_t*) uv_connect_sock);
+  if (r != 0) {
+    if (r == UV_EAGAIN) {
+      // if not blocking then just return as we have to wait for a connection
+      if (flags & UVWASI_FDFLAG_NONBLOCK) {
+        err = free_handle_sync(uvwasi, (uv_handle_t*) uv_connect_sock);
+        uv_mutex_unlock(&wrap->mutex);
+        if (err != UVWASI_ESUCCESS) {
+          return err;
+	}
+        return UVWASI_EAGAIN;
+      }
+    } else {
+      err = uvwasi__translate_uv_error(r);
+      goto close_sock_and_error_exit;
+    }
+
+    // request was blocking and we have no connection yet. run
+    // the loop until a connection comes in
+    while (1) {
+      err = 0;
+      if (uv_run(sock_loop, UV_RUN_ONCE) == 0) {
+        err = UVWASI_ECONNABORTED;
+        goto close_sock_and_error_exit;
+      }
+
+      int r = uv_accept((uv_stream_t*) wrap->sock, (uv_stream_t*) uv_connect_sock);
+      if (r == UV_EAGAIN) {
+	// still no connection or error so run the loop again
+        continue;
+      }
+
+      if (r != 0) {
+	// An error occurred accepting the connection. Break out of the loop and
+	// report an error.
+        err = uvwasi__translate_uv_error(r);
+        goto close_sock_and_error_exit;
+      }
+
+      // if we get here a new connection was successfully accepted
+      break;
+    }
+  }
+
+  err = uvwasi_fd_table_insert(uvwasi,
+                               uvwasi->fds,
+                               -1,
+                               uv_connect_sock,
+                               NULL,
+                               NULL,
+                               UVWASI_FILETYPE_SOCKET_STREAM,
+                               UVWASI__RIGHTS_SOCKET_BASE,
+                               UVWASI__RIGHTS_SOCKET_INHERITING,
+                               1,
+                               &connected_wrap);
+
+  if (err != UVWASI_ESUCCESS)
+    goto close_sock_and_error_exit;
+
+  *connect_sock = connected_wrap->id;
+  uv_mutex_unlock(&wrap->mutex);
+  uv_mutex_unlock(&connected_wrap->mutex);
+  return UVWASI_ESUCCESS;
+
+close_sock_and_error_exit:
+  uvwasi__free(uvwasi, uv_connect_sock);
+  uv_mutex_unlock(&wrap->mutex);
+  return err;
+}
 
 
 const char* uvwasi_embedder_err_code_to_string(uvwasi_errno_t code) {
diff --git a/deps/uvwasi/src/wasi_rights.h b/deps/uvwasi/src/wasi_rights.h
index 09009b39889cc0..54ac7d7072b7fe 100644
--- a/deps/uvwasi/src/wasi_rights.h
+++ b/deps/uvwasi/src/wasi_rights.h
@@ -84,8 +84,9 @@
                                     UVWASI_RIGHT_FD_WRITE |                   \
                                     UVWASI_RIGHT_FD_FILESTAT_GET |            \
                                     UVWASI_RIGHT_POLL_FD_READWRITE |          \
-                                    UVWASI_RIGHT_SOCK_SHUTDOWN)
-#define UVWASI__RIGHTS_SOCKET_INHERITING UVWASI__RIGHTS_ALL;
+                                    UVWASI_RIGHT_SOCK_SHUTDOWN |              \
+                                    UVWASI_RIGHT_SOCK_ACCEPT)
+#define UVWASI__RIGHTS_SOCKET_INHERITING UVWASI__RIGHTS_ALL
 
 #define UVWASI__RIGHTS_TTY_BASE (UVWASI_RIGHT_FD_READ |                       \
                                  UVWASI_RIGHT_FD_FDSTAT_SET_FLAGS |           \
diff --git a/deps/uvwasi/uvwasi.gyp b/deps/uvwasi/uvwasi.gyp
index 5822f8d59bd9e9..525456a9a8b2cc 100644
--- a/deps/uvwasi/uvwasi.gyp
+++ b/deps/uvwasi/uvwasi.gyp
@@ -13,6 +13,7 @@
         'src/fd_table.c',
         'src/path_resolver.c',
         'src/poll_oneoff.c',
+        'src/sync_helpers.c',
         'src/uv_mapping.c',
         'src/uvwasi.c',
         'src/wasi_rights.c',
@@ -36,4 +37,4 @@
       ],
     }
   ]
-}
+}
\ No newline at end of file
diff --git a/deps/v8/AUTHORS b/deps/v8/AUTHORS
index d827b95979057e..92d440ef19635b 100644
--- a/deps/v8/AUTHORS
+++ b/deps/v8/AUTHORS
@@ -159,6 +159,7 @@ Kyounga Ra 
 Loo Rong Jie 
 Lu Yahan 
 Luis Reis 
+Luke Albao 
 Luke Zarko 
 Ma Aiguo 
 Maciej Małecki 
diff --git a/deps/v8/BUILD.gn b/deps/v8/BUILD.gn
index 988c907d964a25..f6860561cad2bd 100644
--- a/deps/v8/BUILD.gn
+++ b/deps/v8/BUILD.gn
@@ -82,6 +82,17 @@ declare_args() {
   # Sets -dENABLE_HUGEPAGE
   v8_enable_hugepage = false
 
+  # Sets -dV8_ENABLE_PRIVATE_MAPPING_FORK_OPTIMIZATION.
+  #
+  # This flag speeds up the performance of fork/execve on Linux systems for
+  # embedders which use it (like Node.js). It works by marking the pages that
+  # V8 allocates as MADV_DONTFORK. Without MADV_DONTFORK, the Linux kernel
+  # spends a long time manipulating page mappings on fork and exec which the
+  # child process doesn't generally need to access.
+  #
+  # See v8:7381 for more details.
+  v8_enable_private_mapping_fork_optimization = false
+
   # Sets -dENABLE_HANDLE_ZAPPING.
   v8_enable_handle_zapping = !is_on_release_branch || is_debug
 
@@ -862,6 +873,9 @@ config("features") {
   if (v8_enable_hugepage) {
     defines += [ "ENABLE_HUGEPAGE" ]
   }
+  if (v8_enable_private_mapping_fork_optimization) {
+    defines += [ "V8_ENABLE_PRIVATE_MAPPING_FORK_OPTIMIZATION" ]
+  }
   if (v8_enable_object_print) {
     defines += [ "OBJECT_PRINT" ]
   }
diff --git a/deps/v8/src/base/platform/platform-posix.cc b/deps/v8/src/base/platform/platform-posix.cc
index 664ed301c87baa..517cbfccab6843 100644
--- a/deps/v8/src/base/platform/platform-posix.cc
+++ b/deps/v8/src/base/platform/platform-posix.cc
@@ -174,6 +174,12 @@ void* Allocate(void* hint, size_t size, OS::MemoryPermission access,
   int flags = GetFlagsForMemoryPermission(access, page_type);
   void* result = mmap(hint, size, prot, flags, kMmapFd, kMmapFdOffset);
   if (result == MAP_FAILED) return nullptr;
+
+#if V8_ENABLE_PRIVATE_MAPPING_FORK_OPTIMIZATION
+  // This is advisory, so we ignore errors.
+  madvise(result, size, MADV_DONTFORK);
+#endif
+
 #if ENABLE_HUGEPAGE
   if (result != nullptr && size >= kHugePageSize) {
     const uintptr_t huge_start =
diff --git a/deps/v8/src/diagnostics/perf-jit.cc b/deps/v8/src/diagnostics/perf-jit.cc
index d222c11336f417..c2399046a92144 100644
--- a/deps/v8/src/diagnostics/perf-jit.cc
+++ b/deps/v8/src/diagnostics/perf-jit.cc
@@ -42,6 +42,7 @@
 #include "src/codegen/assembler.h"
 #include "src/codegen/source-position-table.h"
 #include "src/diagnostics/eh-frame.h"
+#include "src/objects/code-kind.h"
 #include "src/objects/objects-inl.h"
 #include "src/objects/shared-function-info.h"
 #include "src/snapshot/embedded/embedded-data.h"
@@ -214,11 +215,7 @@ void PerfJitLogger::LogRecordedBuffer(
     Handle abstract_code,
     MaybeHandle maybe_shared, const char* name,
     int length) {
-  if (FLAG_perf_basic_prof_only_functions &&
-      (abstract_code->kind() != CodeKind::INTERPRETED_FUNCTION &&
-       abstract_code->kind() != CodeKind::TURBOFAN &&
-       abstract_code->kind() != CodeKind::MAGLEV &&
-       abstract_code->kind() != CodeKind::BASELINE)) {
+  if (FLAG_perf_basic_prof_only_functions && !CodeKindIsJSFunction(abstract_code->kind())) {
     return;
   }
 
diff --git a/deps/v8/src/logging/log.cc b/deps/v8/src/logging/log.cc
index e2de9db07cd3ea..8a640ac273220d 100644
--- a/deps/v8/src/logging/log.cc
+++ b/deps/v8/src/logging/log.cc
@@ -364,7 +364,7 @@ void PerfBasicLogger::LogRecordedBuffer(Handle code,
                                         MaybeHandle,
                                         const char* name, int length) {
   if (FLAG_perf_basic_prof_only_functions &&
-      CodeKindIsBuiltinOrJSFunction(code->kind())) {
+      !CodeKindIsBuiltinOrJSFunction(code->kind())) {
     return;
   }
 
diff --git a/deps/v8/src/snapshot/deserializer.cc b/deps/v8/src/snapshot/deserializer.cc
index e1383ca2b7fe0d..96e8427efa69da 100644
--- a/deps/v8/src/snapshot/deserializer.cc
+++ b/deps/v8/src/snapshot/deserializer.cc
@@ -427,6 +427,8 @@ void Deserializer::PostProcessNewJSReceiver(
         reinterpret_cast(backing_store) + data_view.byte_offset());
   } else if (InstanceTypeChecker::IsJSTypedArray(instance_type)) {
     auto typed_array = JSTypedArray::cast(raw_obj);
+    // Note: ByteArray objects must not be deferred s.t. they are
+    // available here for is_on_heap(). See also: CanBeDeferred.
     // Fixup typed array pointers.
     if (typed_array.is_on_heap()) {
       typed_array.AddExternalPointerCompensationForDeserialization(
@@ -517,7 +519,10 @@ void Deserializer::PostProcessNewObject(Handle map,
         // to |ObjectDeserializer::CommitPostProcessedObjects()|.
         new_allocation_sites_.push_back(Handle::cast(obj));
       } else {
-        DCHECK(CanBeDeferred(*obj));
+        // We dont defer ByteArray because JSTypedArray needs the base_pointer
+        // ByteArray immediately if it's on heap.
+        DCHECK(CanBeDeferred(*obj) ||
+               InstanceTypeChecker::IsByteArray(instance_type));
       }
     }
   }
diff --git a/deps/v8/src/snapshot/serializer-deserializer.cc b/deps/v8/src/snapshot/serializer-deserializer.cc
index d32de12ec05932..5d758cd8253498 100644
--- a/deps/v8/src/snapshot/serializer-deserializer.cc
+++ b/deps/v8/src/snapshot/serializer-deserializer.cc
@@ -51,10 +51,13 @@ bool SerializerDeserializer::CanBeDeferred(HeapObject o) {
   // 3. JS objects with embedder fields cannot be deferred because the
   // serialize/deserialize callbacks need the back reference immediately to
   // identify the object.
+  // 4. ByteArray cannot be deferred as JSTypedArray needs the base_pointer
+  // ByteArray immediately if it's on heap.
   // TODO(leszeks): Could we defer string serialization if forward references
   // were resolved after object post processing?
   return !o.IsMap() && !o.IsInternalizedString() &&
-         !(o.IsJSObject() && JSObject::cast(o).GetEmbedderFieldCount() > 0);
+         !(o.IsJSObject() && JSObject::cast(o).GetEmbedderFieldCount() > 0) &&
+         !o.IsByteArray();
 }
 
 void SerializerDeserializer::RestoreExternalReferenceRedirector(
diff --git a/deps/v8/src/wasm/baseline/riscv64/liftoff-assembler-riscv64.h b/deps/v8/src/wasm/baseline/riscv64/liftoff-assembler-riscv64.h
index 642a7d2a3350c9..8d7ef96f3ad45b 100644
--- a/deps/v8/src/wasm/baseline/riscv64/liftoff-assembler-riscv64.h
+++ b/deps/v8/src/wasm/baseline/riscv64/liftoff-assembler-riscv64.h
@@ -393,7 +393,7 @@ void LiftoffAssembler::AbortCompilation() { AbortedCodeGeneration(); }
 
 // static
 constexpr int LiftoffAssembler::StaticStackFrameSize() {
-  return liftoff::kFeedbackVectorOffset;
+  return liftoff::kTierupBudgetOffset;
 }
 
 int LiftoffAssembler::SlotSizeForType(ValueKind kind) {
diff --git a/deps/v8/test/cctest/test-serialize.cc b/deps/v8/test/cctest/test-serialize.cc
index 4252d4bd652034..e7f1dd4760c861 100644
--- a/deps/v8/test/cctest/test-serialize.cc
+++ b/deps/v8/test/cctest/test-serialize.cc
@@ -4990,6 +4990,46 @@ UNINITIALIZED_TEST(SnapshotCreatorAnonClassWithKeep) {
   delete[] blob.data;
 }
 
+UNINITIALIZED_TEST(SnapshotCreatorDontDeferByteArrayForTypedArray) {
+  DisableAlwaysOpt();
+  v8::StartupData blob;
+  {
+    v8::SnapshotCreator creator;
+    v8::Isolate* isolate = creator.GetIsolate();
+    {
+      v8::HandleScope handle_scope(isolate);
+
+      v8::Local context = v8::Context::New(isolate);
+      v8::Context::Scope context_scope(context);
+      CompileRun(
+          "const z = new Uint8Array(1);\n"
+          "class A { \n"
+          "  static x() { \n"
+          "  } \n"
+          "} \n"
+          "class B extends A {} \n"
+          "B.foo = ''; \n"
+          "class C extends B {} \n"
+          "class D extends C {} \n"
+          "class E extends B {} \n"
+          "function F() {} \n"
+          "Object.setPrototypeOf(F, D); \n");
+      creator.SetDefaultContext(context);
+    }
+
+    blob =
+        creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
+    CHECK(blob.raw_size > 0 && blob.data != nullptr);
+  }
+  {
+    SnapshotCreator creator(nullptr, &blob);
+    v8::Isolate* isolate = creator.GetIsolate();
+    v8::HandleScope scope(isolate);
+    USE(v8::Context::New(isolate));
+  }
+  delete[] blob.data;
+}
+
 class V8_NODISCARD DisableLazySourcePositionScope {
  public:
   DisableLazySourcePositionScope()
diff --git a/deps/zlib/BUILD.gn b/deps/zlib/BUILD.gn
index 9b3971041dffa0..8ed0807a994b1e 100644
--- a/deps/zlib/BUILD.gn
+++ b/deps/zlib/BUILD.gn
@@ -124,45 +124,40 @@ source_set("zlib_adler32_simd") {
 
 if (use_arm_neon_optimizations) {
   config("zlib_arm_crc32_config") {
-    # Disabled for iPhone, as described in DDI0487C_a_armv8_arm:
-    #  "All implementations of the ARMv8.1 architecture are required to
-    #   implement the CRC32* instructions. These are optional in ARMv8.0."
-    if (!is_ios) {
-      defines = [ "CRC32_ARMV8_CRC32" ]
-      if (is_android) {
-        defines += [ "ARMV8_OS_ANDROID" ]
-      } else if (is_linux || is_chromeos) {
-        defines += [ "ARMV8_OS_LINUX" ]
-      } else if (is_mac) {
-        defines += [ "ARMV8_OS_MACOS" ]
-      } else if (is_fuchsia) {
-        defines += [ "ARMV8_OS_FUCHSIA" ]
-      } else if (is_win) {
-        defines += [ "ARMV8_OS_WINDOWS" ]
-      } else {
-        assert(false, "Unsupported ARM OS")
-      }
+    defines = [ "CRC32_ARMV8_CRC32" ]
+    if (is_android) {
+      defines += [ "ARMV8_OS_ANDROID" ]
+    } else if (is_linux || is_chromeos) {
+      defines += [ "ARMV8_OS_LINUX" ]
+    } else if (is_mac) {
+      defines += [ "ARMV8_OS_MACOS" ]
+    } else if (is_ios) {
+      defines += [ "ARMV8_OS_IOS" ]
+    } else if (is_fuchsia) {
+      defines += [ "ARMV8_OS_FUCHSIA" ]
+    } else if (is_win) {
+      defines += [ "ARMV8_OS_WINDOWS" ]
+    } else {
+      assert(false, "Unsupported ARM OS")
     }
   }
 
   source_set("zlib_arm_crc32") {
     visibility = [ ":*" ]
 
-    if (!is_ios) {
-      include_dirs = [ "." ]
-
-      if (!is_win && !is_clang) {
-        assert(!use_thin_lto,
-               "ThinLTO fails mixing different module-level targets")
-        cflags_c = [ "-march=armv8-a+aes+crc" ]
-      }
+    include_dirs = [ "." ]
 
-      sources = [
-        "crc32_simd.c",
-        "crc32_simd.h",
-      ]
+    if (!is_win && !is_clang) {
+      assert(!use_thin_lto,
+             "ThinLTO fails mixing different module-level targets")
+      cflags_c = [ "-march=armv8-a+aes+crc" ]
     }
 
+    sources = [
+      "crc32_simd.c",
+      "crc32_simd.h",
+    ]
+
     configs += [ ":zlib_internal_config" ]
 
     public_configs = [ ":zlib_arm_crc32_config" ]
@@ -332,14 +327,6 @@ component("zlib") {
     defines += [ "CPU_NO_SIMD" ]
   }
 
-  if (is_ios) {
-    # iOS@ARM is a special case where we always have NEON but don't check
-    # for crypto extensions.
-    # TODO(cavalcantii): verify what is the current state of CPU features
-    # shipped on latest iOS devices.
-    defines += [ "ARM_OS_IOS" ]
-  }
-
   if (use_x86_x64_optimizations || use_arm_neon_optimizations) {
     deps += [
       ":zlib_adler32_simd",
@@ -398,6 +385,11 @@ config("minizip_warnings") {
 }
 
 static_library("minizip") {
+  include_dirs = [
+    ".",
+    "//third_party/zlib",
+  ]
+
   sources = [
     "contrib/minizip/ioapi.c",
     "contrib/minizip/ioapi.h",
@@ -520,6 +512,7 @@ if (build_with_chromium) {
     }
 
     deps = [
+      ":minizip",
       ":zlib",
       "google:compression_utils",
       "google:zip",
diff --git a/deps/zlib/CMakeLists.txt b/deps/zlib/CMakeLists.txt
index 378a3792f4ba8f..234eab8db41def 100644
--- a/deps/zlib/CMakeLists.txt
+++ b/deps/zlib/CMakeLists.txt
@@ -23,6 +23,12 @@ check_include_file(stddef.h    HAVE_STDDEF_H)
 
 option(ENABLE_SIMD_OPTIMIZATIONS "Enable all SIMD optimizations" OFF)
 option(ENABLE_SIMD_AVX512 "Enable SIMD AXV512 optimizations" OFF)
+option(USE_ZLIB_RABIN_KARP_HASH "Enable bitstream compatibility with canonical zlib" OFF)
+option(BUILD_UNITTESTS "Enable standalone unit tests build" OFF)
+
+if (USE_ZLIB_RABIN_KARP_HASH)
+   add_definitions(-DUSE_ZLIB_RABIN_KARP_ROLLING_HASH)
+endif()
 
 # TODO(cavalcantii): add support for other OSes (e.g. Android, fuchsia, osx)
 # and architectures (e.g. Arm).
@@ -238,3 +244,64 @@ enable_language(CXX)
 set(CMAKE_CXX_STANDARD 14) # workaround for older compilers (e.g. g++ 5.4).
 add_executable(zlib_bench contrib/bench/zlib_bench.cc)
 target_link_libraries(zlib_bench zlib)
+
+#============================================================================
+# Unit Tests
+#============================================================================
+if (BUILD_UNITTESTS)
+    include (ExternalProject)
+    set_directory_properties(PROPERTIES EP_PREFIX ${CMAKE_BINARY_DIR}/third_party)
+    ExternalProject_add(
+        googletest
+        GIT_REPOSITORY https://github.com/google/googletest.git
+        GIT_TAG d1467f5813f4d363cfd11aba99c4e9fe47a85e99
+        UPDATE_COMMAND ""
+        INSTALL_COMMAND ""
+        LOG_DOWNLOAD ON
+        LOG_CONFIGURE ON
+        LOG_BUILD ON
+    )
+
+    # gtest includedir
+    ExternalProject_Get_Property(googletest source_dir)
+    set(GTEST_INCLUDE_DIRS
+        ${source_dir}/googletest/include
+        ${source_dir}/googletest/include/gtest
+    )
+
+    # gtest library
+    ExternalProject_Get_Property(googletest binary_dir)
+    set(GTEST_LIBRARY_PATH ${binary_dir}/lib/${CMAKE_FIND_LIBRARY_PREFIXES}gtest.a)
+    set(GTEST_LIBRARY gtest)
+    add_library(${GTEST_LIBRARY} UNKNOWN IMPORTED)
+    set_property(TARGET ${GTEST_LIBRARY} PROPERTY IMPORTED_LOCATION ${GTEST_LIBRARY_PATH})
+    add_dependencies(${GTEST_LIBRARY} googletest)
+
+    set(UTEST_SRC
+        ${CMAKE_CURRENT_SOURCE_DIR}/contrib/tests/infcover.cc
+        ${CMAKE_CURRENT_SOURCE_DIR}/contrib/tests/infcover.h
+        ${CMAKE_CURRENT_SOURCE_DIR}/contrib/tests/utils_unittest.cc
+        ${CMAKE_CURRENT_SOURCE_DIR}/contrib/tests/standalone_test_runner.cc
+        ${CMAKE_CURRENT_SOURCE_DIR}/google/compression_utils_portable.cc
+    )
+
+    add_compile_definitions(CMAKE_STANDALONE_UNITTESTS)
+
+    add_executable(zlib_unittests ${UTEST_SRC})
+    target_include_directories(zlib_unittests PUBLIC ${GTEST_INCLUDE_DIRS})
+    target_include_directories(zlib_unittests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/google)
+
+    target_link_libraries(zlib_unittests ${GTEST_LIBRARY})
+    target_link_libraries(zlib_unittests zlib)
+    # Needed by gtest
+    target_link_libraries(zlib_unittests pthread)
+endif()
+
+#============================================================================
+# Minigzip tool
+#============================================================================
+add_executable(minizip_bin contrib/minizip/minizip.c contrib/minizip/ioapi.c
+contrib/minizip/ioapi.h contrib/minizip/unzip.c
+contrib/minizip/unzip.h contrib/minizip/zip.c contrib/minizip/zip.h
+)
+target_link_libraries(minizip_bin zlib)
diff --git a/deps/zlib/README.chromium b/deps/zlib/README.chromium
index 190430f5325ce6..1dfb99666423ea 100644
--- a/deps/zlib/README.chromium
+++ b/deps/zlib/README.chromium
@@ -4,7 +4,8 @@ URL: http://zlib.net/
 Version: 1.2.13
 CPEPrefix: cpe:/a:zlib:zlib:1.2.13
 Security Critical: yes
-License: Custom license
+Shipped: yes
+License: Zlib
 License File: LICENSE
 License Android Compatible: yes
 
diff --git a/deps/zlib/adler32.c b/deps/zlib/adler32.c
index 81c584f68e2331..99a294496f7eb5 100644
--- a/deps/zlib/adler32.c
+++ b/deps/zlib/adler32.c
@@ -90,9 +90,9 @@ uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, z_size_t len) {
         return adler | (sum2 << 16);
     }
 
-#if defined(ADLER32_SIMD_SSSE3)
+#if defined(ADLER32_SIMD_SSSE3) || defined(ADLER32_SIMD_NEON)
     /*
-     * Use SSSE3 to compute the adler32. Since this routine can be
+     * Use SIMD to compute the adler32. Since this function can be
      * freely used, check CPU features here. zlib convention is to
      * call adler32(0, NULL, 0), before making calls to adler32().
      * So this is a good early (and infrequent) place to cache CPU
diff --git a/deps/zlib/contrib/bench/zlib_bench.cc b/deps/zlib/contrib/bench/zlib_bench.cc
index 8580319edf25bc..b65f9291bff500 100644
--- a/deps/zlib/contrib/bench/zlib_bench.cc
+++ b/deps/zlib/contrib/bench/zlib_bench.cc
@@ -236,7 +236,11 @@ void check_file(const Data& file, zlib_wrapper type, int mode) {
     error_exit("check file: error writing output", 3);
 }
 
-void zlib_file(const char* name, zlib_wrapper type, int width, int check) {
+void zlib_file(const char* name,
+               zlib_wrapper type,
+               int width,
+               int check,
+               bool output_csv_format) {
   /*
    * Read the file data.
    */
@@ -257,7 +261,9 @@ void zlib_file(const char* name, zlib_wrapper type, int width, int check) {
    * Report compression strategy and file name.
    */
   const char* strategy = zlib_level_strategy_name(zlib_compression_level);
-  printf("%s%-40s :\n", strategy, name);
+  if (!output_csv_format) {
+    printf("%s%-40s :\n", strategy, name);
+  }
 
   /*
    * Chop the data into blocks.
@@ -329,19 +335,28 @@ void zlib_file(const char* name, zlib_wrapper type, int width, int check) {
   std::sort(ctime, ctime + runs);
   std::sort(utime, utime + runs);
 
-  double deflate_rate_med = length * repeats / mega_byte / ctime[runs / 2];
-  double inflate_rate_med = length * repeats / mega_byte / utime[runs / 2];
-  double deflate_rate_max = length * repeats / mega_byte / ctime[0];
-  double inflate_rate_max = length * repeats / mega_byte / utime[0];
-
-  // type, block size, compression ratio, etc
-  printf("%s: [b %dM] bytes %*d -> %*u %4.2f%%",
-    zlib_wrapper_name(type), block_size / (1 << 20), width, length, width,
-    unsigned(output_length), output_length * 100.0 / length);
-
-  // compress / uncompress median (max) rates
-  printf(" comp %5.1f (%5.1f) MB/s uncomp %5.1f (%5.1f) MB/s\n",
-    deflate_rate_med, deflate_rate_max, inflate_rate_med, inflate_rate_max);
+  double deflate_rate_med, inflate_rate_med, deflate_rate_max, inflate_rate_max;
+  deflate_rate_med = length * repeats / mega_byte / ctime[runs / 2];
+  inflate_rate_med = length * repeats / mega_byte / utime[runs / 2];
+  deflate_rate_max = length * repeats / mega_byte / ctime[0];
+  inflate_rate_max = length * repeats / mega_byte / utime[0];
+  double compress_ratio = output_length * 100.0 / length;
+
+  if (!output_csv_format) {
+    // type, block size, compression ratio, etc
+    printf("%s: [b %dM] bytes %*d -> %*u %4.2f%%", zlib_wrapper_name(type),
+           block_size / (1 << 20), width, length, width,
+           unsigned(output_length), compress_ratio);
+
+    // compress / uncompress median (max) rates
+    printf(" comp %5.1f (%5.1f) MB/s uncomp %5.1f (%5.1f) MB/s\n",
+           deflate_rate_med, deflate_rate_max, inflate_rate_med,
+           inflate_rate_max);
+  } else {
+    printf("%s\t%.5lf\t%.5lf\t%.5lf\t%.5lf\t%.5lf\n", name, deflate_rate_med,
+           inflate_rate_med, deflate_rate_max, inflate_rate_max,
+           compress_ratio);
+  }
 }
 
 static int argn = 1;
@@ -363,8 +378,10 @@ void get_field_width(int argc, char* argv[], int& value) {
 }
 
 void usage_exit(const char* program) {
-  static auto* options = "gzip|zlib|raw"
-    " [--compression 0:9] [--huffman|--rle] [--field width] [--check]";
+  static auto* options =
+      "gzip|zlib|raw"
+      " [--compression 0:9] [--huffman|--rle] [--field width] [--check]"
+      " [--csv]";
   printf("usage: %s %s files ...\n", program, options);
   printf("zlib version: %s\n", ZLIB_VERSION);
   exit(1);
@@ -383,7 +400,7 @@ int main(int argc, char* argv[]) {
 
   int size_field_width = 0;
   int file_check = 0;
-
+  bool output_csv = false;
   while (argn < argc && argv[argn][0] == '-') {
     if (get_option(argc, argv, "--compression")) {
       if (!get_compression(argc, argv, zlib_compression_level))
@@ -398,6 +415,11 @@ int main(int argc, char* argv[]) {
       file_check = 2;
     } else if (get_option(argc, argv, "--field")) {
       get_field_width(argc, argv, size_field_width);
+    } else if (get_option(argc, argv, "--csv")) {
+      output_csv = true;
+      printf(
+          "filename\tcompression\tdecompression\tcomp_max\t"
+          "decomp_max\tcompress_ratio\n");
     } else {
       usage_exit(argv[0]);
     }
@@ -408,8 +430,9 @@ int main(int argc, char* argv[]) {
 
   if (size_field_width < 6)
     size_field_width = 6;
-  while (argn < argc)
-    zlib_file(argv[argn++], type, size_field_width, file_check);
+  while (argn < argc) {
+    zlib_file(argv[argn++], type, size_field_width, file_check, output_csv);
+  }
 
   return 0;
 }
diff --git a/deps/zlib/contrib/minizip/README.chromium b/deps/zlib/contrib/minizip/README.chromium
index 1ad489a6780db2..9c780f94682075 100644
--- a/deps/zlib/contrib/minizip/README.chromium
+++ b/deps/zlib/contrib/minizip/README.chromium
@@ -3,7 +3,9 @@ Short Name: minizip
 URL: https://github.com/madler/zlib/tree/master/contrib/minizip
 Version: 1.2.12
 License: Zlib
+License File: //third_party/zlib/LICENSE
 Security Critical: yes
+Shipped: yes
 
 Description:
 Minizip provides API on top of zlib that can enumerate and extract ZIP archive
@@ -13,3 +15,6 @@ Local Modifications:
 - Add parsing of the 'Info-ZIP Unicode Path Extra Field' as described in
   https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT section 4.6.9.
   (see crrev.com/1002476)
+
+- Check for overly long filename, comment, or extra field in
+  zipOpenNewFileInZip4_64 (crbug.com/1470539).
diff --git a/deps/zlib/contrib/minizip/ioapi.h b/deps/zlib/contrib/minizip/ioapi.h
index c1b7a54847f552..8dcbdb06e35ad5 100644
--- a/deps/zlib/contrib/minizip/ioapi.h
+++ b/deps/zlib/contrib/minizip/ioapi.h
@@ -43,7 +43,7 @@
 
 #include 
 #include 
-#include "third_party/zlib/zlib.h"
+#include "zlib.h"
 
 #if defined(USE_FILE32API)
 #define fopen64 fopen
diff --git a/deps/zlib/contrib/minizip/mztools.c b/deps/zlib/contrib/minizip/mztools.c
index 8bf9cca326338a..96891c2e0b71ef 100644
--- a/deps/zlib/contrib/minizip/mztools.c
+++ b/deps/zlib/contrib/minizip/mztools.c
@@ -8,7 +8,7 @@
 #include 
 #include 
 #include 
-#include "third_party/zlib/zlib.h"
+#include "zlib.h"
 #include "unzip.h"
 
 #define READ_8(adr)  ((unsigned char)*(adr))
diff --git a/deps/zlib/contrib/minizip/mztools.h b/deps/zlib/contrib/minizip/mztools.h
index f295ffeda6afcf..a49a426ec2fcb2 100644
--- a/deps/zlib/contrib/minizip/mztools.h
+++ b/deps/zlib/contrib/minizip/mztools.h
@@ -12,7 +12,7 @@ extern "C" {
 #endif
 
 #ifndef _ZLIB_H
-#include "third_party/zlib/zlib.h"
+#include "zlib.h"
 #endif
 
 #include "unzip.h"
diff --git a/deps/zlib/contrib/minizip/unzip.c b/deps/zlib/contrib/minizip/unzip.c
index 0a1d8b4fe2cf78..4973a4eea97b99 100644
--- a/deps/zlib/contrib/minizip/unzip.c
+++ b/deps/zlib/contrib/minizip/unzip.c
@@ -68,7 +68,7 @@
 #include 
 #include 
 
-#include "third_party/zlib/zlib.h"
+#include "zlib.h"
 #include "unzip.h"
 
 #ifdef STDC
diff --git a/deps/zlib/contrib/minizip/unzip.h b/deps/zlib/contrib/minizip/unzip.h
index 3c0143529b9144..2104e39150749b 100644
--- a/deps/zlib/contrib/minizip/unzip.h
+++ b/deps/zlib/contrib/minizip/unzip.h
@@ -48,7 +48,7 @@ extern "C" {
 #endif
 
 #ifndef _ZLIB_H
-#include "third_party/zlib/zlib.h"
+#include "zlib.h"
 #endif
 
 #ifndef  _ZLIBIOAPI_H
diff --git a/deps/zlib/contrib/minizip/zip.c b/deps/zlib/contrib/minizip/zip.c
index 65c0c7251843c0..f21d4954286af4 100644
--- a/deps/zlib/contrib/minizip/zip.c
+++ b/deps/zlib/contrib/minizip/zip.c
@@ -26,7 +26,7 @@
 #include 
 #include 
 #include 
-#include "third_party/zlib/zlib.h"
+#include "zlib.h"
 #include "zip.h"
 
 #ifdef STDC
@@ -1083,6 +1083,17 @@ extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename,
       return ZIP_PARAMERROR;
 #endif
 
+    // The filename and comment length must fit in 16 bits.
+    if ((filename!=NULL) && (strlen(filename)>0xffff))
+        return ZIP_PARAMERROR;
+    if ((comment!=NULL) && (strlen(comment)>0xffff))
+        return ZIP_PARAMERROR;
+    // The extra field length must fit in 16 bits. If the member also requires
+    // a Zip64 extra block, that will also need to fit within that 16-bit
+    // length, but that will be checked for later.
+    if ((size_extrafield_local>0xffff) || (size_extrafield_global>0xffff))
+        return ZIP_PARAMERROR;
+
     zi = (zip64_internal*)file;
 
     if (zi->in_opened_file_inzip == 1)
diff --git a/deps/zlib/contrib/minizip/zip.h b/deps/zlib/contrib/minizip/zip.h
index 8c06c0aa7bb08b..8aaebb623430fc 100644
--- a/deps/zlib/contrib/minizip/zip.h
+++ b/deps/zlib/contrib/minizip/zip.h
@@ -47,7 +47,7 @@ extern "C" {
 //#define HAVE_BZIP2
 
 #ifndef _ZLIB_H
-#include "third_party/zlib/zlib.h"
+#include "zlib.h"
 #endif
 
 #ifndef _ZLIBIOAPI_H
diff --git a/deps/zlib/contrib/optimizations/inflate.c b/deps/zlib/contrib/optimizations/inflate.c
index 6ed87160f5350d..2a8e0ef76db6ba 100644
--- a/deps/zlib/contrib/optimizations/inflate.c
+++ b/deps/zlib/contrib/optimizations/inflate.c
@@ -1488,8 +1488,9 @@ int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) {
     if (copy == Z_NULL) return Z_MEM_ERROR;
     window = Z_NULL;
     if (state->window != Z_NULL) {
-        window = (unsigned char FAR *)
-                 ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
+        window = (unsigned char FAR *)ZALLOC(
+            source, (1U << state->wbits) + CHUNKCOPY_CHUNK_SIZE,
+            sizeof(unsigned char));
         if (window == Z_NULL) {
             ZFREE(source, copy);
             return Z_MEM_ERROR;
diff --git a/deps/zlib/contrib/optimizations/insert_string.h b/deps/zlib/contrib/optimizations/insert_string.h
index c6a296aef7390e..260b8268029a8c 100644
--- a/deps/zlib/contrib/optimizations/insert_string.h
+++ b/deps/zlib/contrib/optimizations/insert_string.h
@@ -16,64 +16,7 @@
 #endif
 #endif
 
-#include "cpu_features.h"
-
-// clang-format off
-#if defined(CRC32_SIMD_SSE42_PCLMUL)
-  #include   /* Required to make MSVC bot build pass. */
-
-  #if defined(__clang__) || defined(__GNUC__)
-    #define TARGET_CPU_WITH_CRC __attribute__((target("sse4.2")))
-  #else
-    #define TARGET_CPU_WITH_CRC
-  #endif
-
-  /* CRC32C uint32_t */
-  #define _cpu_crc32c_hash_u32 _mm_crc32_u32
-
-#elif defined(CRC32_ARMV8_CRC32)
-  #if defined(__clang__)
-    #define __crc32cw __builtin_arm_crc32cw
-  #elif defined(__GNUC__)
-    #define __crc32cw __builtin_aarch64_crc32cw
-  #endif
-
-  #if defined(__aarch64__) && defined(__clang__)
-    #define TARGET_CPU_WITH_CRC __attribute__((target("crc")))
-  #elif defined(__aarch64__) && defined(__GNUC__)
-    #define TARGET_CPU_WITH_CRC __attribute__((target("+crc")))
-  #elif defined(__clang__) // !defined(__aarch64__)
-    #define TARGET_CPU_WITH_CRC __attribute__((target("armv8-a,crc")))
-  #endif  // defined(__aarch64__)
-
-  /* CRC32C uint32_t */
-  #define _cpu_crc32c_hash_u32 __crc32cw
-
-#endif
-// clang-format on
-
-#if defined(TARGET_CPU_WITH_CRC)
-
-TARGET_CPU_WITH_CRC
-local INLINE Pos insert_string_simd(deflate_state* const s, const Pos str) {
-  Pos ret;
-  unsigned val, h = 0;
-
-  zmemcpy(&val, &s->window[str], sizeof(val));
-
-  if (s->level >= 6)
-    val &= 0xFFFFFF;
-
-  /* Compute hash from the CRC32C of |val|. */
-  h = _cpu_crc32c_hash_u32(h, val);
-
-  ret = s->head[h & s->hash_mask];
-  s->head[h & s->hash_mask] = str;
-  s->prev[str & s->w_mask] = ret;
-  return ret;
-}
-
-#endif // TARGET_CPU_WITH_CRC
+#include 
 
 /**
  * Some applications need to match zlib DEFLATE output exactly [3]. Use the
@@ -107,10 +50,23 @@ local INLINE Pos insert_string_simd(deflate_state* const s, const Pos str) {
  *    characters and the first MIN_MATCH bytes of str are valid (except for
  *    the last MIN_MATCH-1 bytes of the input file).
  */
-local INLINE Pos insert_string_c(deflate_state* const s, const Pos str) {
+local INLINE Pos insert_string(deflate_state* const s, const Pos str) {
   Pos ret;
-
+/* insert_string dictionary insertion: ANZAC++ hasher
+ * significantly improves data compression speed.
+ *
+ * Note: the generated compressed output is a valid DEFLATE stream, but will
+ * differ from canonical zlib output.
+ */
+#if defined(USE_ZLIB_RABIN_KARP_ROLLING_HASH)
   UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH - 1)]);
+#else
+  uint32_t value;
+  // Validated for little endian archs (i.e. x86, Arm). YMMV for big endian.
+  zmemcpy(&value, &s->window[str], sizeof(value));
+  s->ins_h = ((value * 66521 + 66521) >> 16) & s->hash_mask;
+#endif
+
 #ifdef FASTEST
   ret = s->head[s->ins_h];
 #else
@@ -121,25 +77,4 @@ local INLINE Pos insert_string_c(deflate_state* const s, const Pos str) {
   return ret;
 }
 
-local INLINE Pos insert_string(deflate_state* const s, const Pos str) {
-/* insert_string_simd string dictionary insertion: SIMD crc32c symbol hasher
- * significantly improves data compression speed.
- *
- * Note: the generated compressed output is a valid DEFLATE stream, but will
- * differ from canonical zlib output.
- */
-#if defined(USE_ZLIB_RABIN_KARP_ROLLING_HASH)
-/* So this build-time option can be used to disable the crc32c hash, and use
- * the Rabin-Karp hash instead.
- */ /* FALLTHROUGH Rabin-Karp */
-#elif defined(TARGET_CPU_WITH_CRC) && defined(CRC32_SIMD_SSE42_PCLMUL)
-  if (x86_cpu_enable_simd)
-    return insert_string_simd(s, str);
-#elif defined(TARGET_CPU_WITH_CRC) && defined(CRC32_ARMV8_CRC32)
-  if (arm_cpu_enable_crc32)
-    return insert_string_simd(s, str);
-#endif
-  return insert_string_c(s, str); /* Rabin-Karp */
-}
-
 #endif /* INSERT_STRING_H */
diff --git a/deps/zlib/contrib/tests/DEPS b/deps/zlib/contrib/tests/DEPS
index 42751740686776..67973613c74138 100644
--- a/deps/zlib/contrib/tests/DEPS
+++ b/deps/zlib/contrib/tests/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
     "+testing/gtest",
+    "+third_party/zlib/contrib/minizip",
     "+base",
 ]
diff --git a/deps/zlib/contrib/tests/standalone_test_runner.cc b/deps/zlib/contrib/tests/standalone_test_runner.cc
new file mode 100644
index 00000000000000..1ec9c30bacba02
--- /dev/null
+++ b/deps/zlib/contrib/tests/standalone_test_runner.cc
@@ -0,0 +1,9 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the Chromium source repository LICENSE file.
+#include 
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/deps/zlib/contrib/tests/utils_unittest.cc b/deps/zlib/contrib/tests/utils_unittest.cc
index 5745939f24f9d1..d06dbc9812ad92 100644
--- a/deps/zlib/contrib/tests/utils_unittest.cc
+++ b/deps/zlib/contrib/tests/utils_unittest.cc
@@ -9,6 +9,15 @@
 
 #include "compression_utils_portable.h"
 #include "gtest.h"
+
+#if !defined(CMAKE_STANDALONE_UNITTESTS)
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+
+#include "third_party/zlib/contrib/minizip/unzip.h"
+#include "third_party/zlib/contrib/minizip/zip.h"
+#endif
+
 #include "zlib.h"
 
 void TestPayloads(size_t input_size, zlib_internal::WrapperType type) {
@@ -1015,3 +1024,127 @@ TEST(ZlibTest, DeflateZFixedCorruption) {
       memcmp(zFixedCorruptionData, decompressed.data(), decompressed.size()),
       0);
 }
+
+// TODO(gustavoa): make these tests run standalone.
+#ifndef CMAKE_STANDALONE_UNITTESTS
+
+TEST(ZlibTest, ZipFilenameCommentSize) {
+  // Check that minizip rejects zip member filenames or comments longer than
+  // the zip format can represent.
+
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  base::FilePath zip_file = temp_dir.GetPath().AppendASCII("crbug1470539.zip");
+
+  zipFile zf = zipOpen(zip_file.AsUTF8Unsafe().c_str(), APPEND_STATUS_CREATE);
+  ASSERT_NE(zf, nullptr);
+
+  // Adding a member with 2^16 byte filename is okay.
+  std::string long_filename(UINT16_MAX, 'a');
+  EXPECT_EQ(zipOpenNewFileInZip(zf, long_filename.c_str(), nullptr, nullptr, 0,
+                                nullptr, 0, nullptr, Z_DEFLATED,
+                                Z_DEFAULT_COMPRESSION),
+            ZIP_OK);
+  EXPECT_EQ(zipWriteInFileInZip(zf, "1", 1), ZIP_OK);
+  EXPECT_EQ(zipCloseFileInZip(zf), ZIP_OK);
+
+  // Adding a member with 2^16+1 byte filename is NOT okay.
+  std::string too_long_filename = long_filename + 'a';
+  EXPECT_EQ(zipOpenNewFileInZip(zf, too_long_filename.c_str(), nullptr, nullptr,
+                                0, nullptr, 0, nullptr, Z_DEFLATED,
+                                Z_DEFAULT_COMPRESSION),
+            ZIP_PARAMERROR);
+
+  // Adding a member with 2^16 byte comment is okay.
+  std::string long_comment(UINT16_MAX, 'x');
+  EXPECT_EQ(zipOpenNewFileInZip(zf, "x", nullptr, nullptr, 0, nullptr, 0,
+                                long_comment.c_str(), Z_DEFLATED,
+                                Z_DEFAULT_COMPRESSION),
+            ZIP_OK);
+  EXPECT_EQ(zipCloseFileInZip(zf), ZIP_OK);
+
+  // Adding a member with 2^16+1 byte comment is NOT okay.
+  std::string too_long_comment = long_comment + 'x';
+  EXPECT_EQ(zipOpenNewFileInZip(zf, "x", nullptr, nullptr, 0, nullptr, 0,
+                                too_long_comment.c_str(), Z_DEFLATED,
+                                Z_DEFAULT_COMPRESSION),
+            ZIP_PARAMERROR);
+
+  EXPECT_EQ(zipClose(zf, nullptr), ZIP_OK);
+
+  // Check that the long filename and comment members were successfully added.
+  unzFile uzf = unzOpen(zip_file.AsUTF8Unsafe().c_str());
+  ASSERT_NE(uzf, nullptr);
+  char buf[UINT16_MAX + 2];
+
+  ASSERT_EQ(unzGoToFirstFile(uzf), UNZ_OK);
+  ASSERT_EQ(unzGetCurrentFileInfo(uzf, nullptr, buf, sizeof(buf), nullptr, 0,
+                                  nullptr, 0),
+            UNZ_OK);
+  EXPECT_EQ(std::string(buf), long_filename);
+
+  ASSERT_EQ(unzGoToNextFile(uzf), UNZ_OK);
+  ASSERT_EQ(unzGetCurrentFileInfo(uzf, nullptr, nullptr, 0, nullptr, 0, buf,
+                                  sizeof(buf)),
+            UNZ_OK);
+  EXPECT_EQ(std::string(buf), long_comment);
+
+  EXPECT_EQ(unzGoToNextFile(uzf), UNZ_END_OF_LIST_OF_FILE);
+  EXPECT_EQ(unzClose(uzf), UNZ_OK);
+}
+
+TEST(ZlibTest, ZipExtraFieldSize) {
+  // Check that minizip rejects zip members with too large extra fields.
+
+  std::string extra_field;
+  extra_field.append("\x12\x34");  // Header ID.
+  extra_field.append("\xfb\xff");  // Data size (not including the header).
+  extra_field.append(UINT16_MAX - 4, 'a');
+
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  base::FilePath zip_file = temp_dir.GetPath().AppendASCII("extrafield.zip");
+
+  zipFile zf = zipOpen(zip_file.AsUTF8Unsafe().c_str(), APPEND_STATUS_CREATE);
+  ASSERT_NE(zf, nullptr);
+
+  // Adding a member with 2^16 byte extra field should work.
+  EXPECT_EQ(zipOpenNewFileInZip(zf, "a", nullptr, extra_field.data(),
+                                extra_field.size(), extra_field.data(),
+                                extra_field.size(), nullptr, Z_DEFLATED,
+                                Z_DEFAULT_COMPRESSION),
+            ZIP_OK);
+  EXPECT_EQ(zipWriteInFileInZip(zf, "1", 1), ZIP_OK);
+  EXPECT_EQ(zipCloseFileInZip(zf), ZIP_OK);
+
+  // More then 2^16 bytes doesn't work. Neither for size_extrafield_local, nor
+  // size_extrafield_global.
+  std::string extra_field_long = extra_field + 'x';
+  EXPECT_EQ(
+      zipOpenNewFileInZip(zf, "b", nullptr, nullptr, 0, extra_field_long.data(),
+                          extra_field_long.size(), nullptr, Z_DEFLATED,
+                          Z_DEFAULT_COMPRESSION),
+      ZIP_PARAMERROR);
+  EXPECT_EQ(zipOpenNewFileInZip(zf, "b", nullptr, extra_field_long.data(),
+                                extra_field_long.size(), nullptr, 0, nullptr,
+                                Z_DEFLATED, Z_DEFAULT_COMPRESSION),
+            ZIP_PARAMERROR);
+
+  EXPECT_EQ(zipClose(zf, nullptr), ZIP_OK);
+
+  // Check that the data can be read back.
+  unzFile uzf = unzOpen(zip_file.AsUTF8Unsafe().c_str());
+  ASSERT_NE(uzf, nullptr);
+  char buf[UINT16_MAX + 1] = {0};
+
+  ASSERT_EQ(unzGoToFirstFile(uzf), UNZ_OK);
+  ASSERT_EQ(unzGetCurrentFileInfo(uzf, nullptr, nullptr, 0, buf,
+                                  sizeof(buf) - 1, nullptr, 0),
+            UNZ_OK);
+  EXPECT_EQ(std::string(buf), extra_field);
+
+  EXPECT_EQ(unzGoToNextFile(uzf), UNZ_END_OF_LIST_OF_FILE);
+  EXPECT_EQ(unzClose(uzf), UNZ_OK);
+}
+
+#endif
diff --git a/deps/zlib/cpu_features.c b/deps/zlib/cpu_features.c
index ac6ee88e460e2e..64e0428cd2fc2d 100644
--- a/deps/zlib/cpu_features.c
+++ b/deps/zlib/cpu_features.c
@@ -35,7 +35,7 @@ int ZLIB_INTERNAL x86_cpu_enable_avx512 = 0;
 
 #ifndef CPU_NO_SIMD
 
-#if defined(ARMV8_OS_ANDROID) || defined(ARMV8_OS_LINUX) || defined(ARMV8_OS_FUCHSIA)
+#if defined(ARMV8_OS_ANDROID) || defined(ARMV8_OS_LINUX) || defined(ARMV8_OS_FUCHSIA) || defined(ARMV8_OS_IOS)
 #include 
 #endif
 
@@ -50,17 +50,19 @@ int ZLIB_INTERNAL x86_cpu_enable_avx512 = 0;
 #include 
 #elif defined(ARMV8_OS_WINDOWS) || defined(X86_WINDOWS)
 #include 
+#elif defined(ARMV8_OS_IOS)
+#include 
 #elif !defined(_MSC_VER)
 #include 
 #else
 #error cpu_features.c CPU feature detection in not defined for your platform
 #endif
 
-#if !defined(CPU_NO_SIMD) && !defined(ARMV8_OS_MACOS) && !defined(ARM_OS_IOS)
+#if !defined(CPU_NO_SIMD) && !defined(ARMV8_OS_MACOS)
 static void _cpu_check_features(void);
 #endif
 
-#if defined(ARMV8_OS_ANDROID) || defined(ARMV8_OS_LINUX) || defined(ARMV8_OS_MACOS) || defined(ARMV8_OS_FUCHSIA) || defined(X86_NOT_WINDOWS)
+#if defined(ARMV8_OS_ANDROID) || defined(ARMV8_OS_LINUX) || defined(ARMV8_OS_MACOS) || defined(ARMV8_OS_FUCHSIA) || defined(X86_NOT_WINDOWS) || defined(ARMV8_OS_IOS)
 #if !defined(ARMV8_OS_MACOS)
 // _cpu_check_features() doesn't need to do anything on mac/arm since all
 // features are known at build time, so don't call it.
@@ -89,11 +91,7 @@ void ZLIB_INTERNAL cpu_check_features(void)
 #endif
 
 #if (defined(__ARM_NEON__) || defined(__ARM_NEON))
-/*
- * iOS@ARM is a special case where we always have NEON but don't check
- * for crypto extensions.
- */
-#if !defined(ARMV8_OS_MACOS) && !defined(ARM_OS_IOS)
+#if !defined(ARMV8_OS_MACOS)
 /*
  * See http://bit.ly/2CcoEsr for run-time detection of ARM features and also
  * crbug.com/931275 for android_getCpuFeatures() use in the Android sandbox.
@@ -127,6 +125,18 @@ static void _cpu_check_features(void)
 #elif defined(ARMV8_OS_WINDOWS)
     arm_cpu_enable_crc32 = IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE);
     arm_cpu_enable_pmull = IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE);
+#elif defined(ARMV8_OS_IOS)
+    // Determine what features are supported dynamically. This code is applicable to macOS
+    // as well if we wish to do that dynamically on that platform in the future.
+    // See https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics
+    int val = 0;
+    size_t len = sizeof(val);
+    arm_cpu_enable_crc32 = sysctlbyname("hw.optional.armv8_crc32", &val, &len, 0, 0) == 0
+               && val != 0;
+    val = 0;
+    len = sizeof(val);
+    arm_cpu_enable_pmull = sysctlbyname("hw.optional.arm.FEAT_PMULL", &val, &len, 0, 0) == 0
+               && val != 0;
 #endif
 }
 #endif
diff --git a/deps/zlib/deflate.c b/deps/zlib/deflate.c
index 1fa55e5d010618..173ce596be582e 100644
--- a/deps/zlib/deflate.c
+++ b/deps/zlib/deflate.c
@@ -457,15 +457,9 @@ int ZEXPORT deflateInit2_(z_streamp strm, int level, int method,
     s->w_size = 1 << s->w_bits;
     s->w_mask = s->w_size - 1;
 
+    s->chromium_zlib_hash = 1;
+#if defined(USE_ZLIB_RABIN_KARP_ROLLING_HASH)
     s->chromium_zlib_hash = 0;
-#if !defined(USE_ZLIB_RABIN_KARP_ROLLING_HASH)
-  #if defined(TARGET_CPU_WITH_CRC) && defined(CRC32_SIMD_SSE42_PCLMUL)
-    if (x86_cpu_enable_simd)
-      s->chromium_zlib_hash = 1;
-  #elif defined(TARGET_CPU_WITH_CRC) && defined(CRC32_ARMV8_CRC32)
-    if (arm_cpu_enable_crc32)
-      s->chromium_zlib_hash = 1;
-  #endif
 #endif
 
     s->hash_bits = memLevel + 7;
diff --git a/deps/zlib/google/DEPS b/deps/zlib/google/DEPS
index 03f2cb950b9517..7ec5343ee23953 100644
--- a/deps/zlib/google/DEPS
+++ b/deps/zlib/google/DEPS
@@ -2,5 +2,6 @@ include_rules = [
   '+base',
   '+build',
   '+testing',
-  "+third_party/zlib/zlib.h",
+  '+third_party/icu/source/i18n/unicode',
+  '+third_party/zlib/zlib.h',
 ]
diff --git a/deps/zlib/google/zip_internal.cc b/deps/zlib/google/zip_internal.cc
index c986e763cccda3..b9976d63ee301b 100644
--- a/deps/zlib/google/zip_internal.cc
+++ b/deps/zlib/google/zip_internal.cc
@@ -8,12 +8,12 @@
 #include 
 
 #include 
-#include 
 
+#include "base/containers/fixed_flat_set.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
-#include "base/no_destructor.h"
 #include "base/notreached.h"
+#include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 
@@ -260,12 +260,13 @@ zip_fileinfo TimeToZipFileInfo(const base::Time& file_time) {
     // It assumes that dates below 1980 are in the double digit format.
     // Hence the fail safe option is to leave the date unset. Some programs
     // might show the unset date as 1980-0-0 which is invalid.
-    zip_info.tmz_date.tm_year = file_time_parts.year;
-    zip_info.tmz_date.tm_mon = file_time_parts.month - 1;
-    zip_info.tmz_date.tm_mday = file_time_parts.day_of_month;
-    zip_info.tmz_date.tm_hour = file_time_parts.hour;
-    zip_info.tmz_date.tm_min = file_time_parts.minute;
-    zip_info.tmz_date.tm_sec = file_time_parts.second;
+    zip_info.tmz_date = {
+        .tm_sec = static_cast(file_time_parts.second),
+        .tm_min = static_cast(file_time_parts.minute),
+        .tm_hour = static_cast(file_time_parts.hour),
+        .tm_mday = static_cast(file_time_parts.day_of_month),
+        .tm_mon = static_cast(file_time_parts.month - 1),
+        .tm_year = static_cast(file_time_parts.year)};
   }
 
   return zip_info;
@@ -407,59 +408,59 @@ Compression GetCompressionMethod(const base::FilePath& path) {
 
   // Well known filename extensions of files that a likely to be already
   // compressed. The extensions are in lower case without the leading dot.
-  static const base::NoDestructor> exts(
-      std::initializer_list{
-          FILE_PATH_LITERAL("3g2"),   //
-          FILE_PATH_LITERAL("3gp"),   //
-          FILE_PATH_LITERAL("7z"),    //
-          FILE_PATH_LITERAL("7zip"),  //
-          FILE_PATH_LITERAL("aac"),   //
-          FILE_PATH_LITERAL("avi"),   //
-          FILE_PATH_LITERAL("bz"),    //
-          FILE_PATH_LITERAL("bz2"),   //
-          FILE_PATH_LITERAL("crx"),   //
-          FILE_PATH_LITERAL("gif"),   //
-          FILE_PATH_LITERAL("gz"),    //
-          FILE_PATH_LITERAL("jar"),   //
-          FILE_PATH_LITERAL("jpeg"),  //
-          FILE_PATH_LITERAL("jpg"),   //
-          FILE_PATH_LITERAL("lz"),    //
-          FILE_PATH_LITERAL("m2v"),   //
-          FILE_PATH_LITERAL("m4p"),   //
-          FILE_PATH_LITERAL("m4v"),   //
-          FILE_PATH_LITERAL("mng"),   //
-          FILE_PATH_LITERAL("mov"),   //
-          FILE_PATH_LITERAL("mp2"),   //
-          FILE_PATH_LITERAL("mp3"),   //
-          FILE_PATH_LITERAL("mp4"),   //
-          FILE_PATH_LITERAL("mpe"),   //
-          FILE_PATH_LITERAL("mpeg"),  //
-          FILE_PATH_LITERAL("mpg"),   //
-          FILE_PATH_LITERAL("mpv"),   //
-          FILE_PATH_LITERAL("ogg"),   //
-          FILE_PATH_LITERAL("ogv"),   //
-          FILE_PATH_LITERAL("png"),   //
-          FILE_PATH_LITERAL("qt"),    //
-          FILE_PATH_LITERAL("rar"),   //
-          FILE_PATH_LITERAL("taz"),   //
-          FILE_PATH_LITERAL("tb2"),   //
-          FILE_PATH_LITERAL("tbz"),   //
-          FILE_PATH_LITERAL("tbz2"),  //
-          FILE_PATH_LITERAL("tgz"),   //
-          FILE_PATH_LITERAL("tlz"),   //
-          FILE_PATH_LITERAL("tz"),    //
-          FILE_PATH_LITERAL("tz2"),   //
-          FILE_PATH_LITERAL("vob"),   //
-          FILE_PATH_LITERAL("webm"),  //
-          FILE_PATH_LITERAL("wma"),   //
-          FILE_PATH_LITERAL("wmv"),   //
-          FILE_PATH_LITERAL("xz"),    //
-          FILE_PATH_LITERAL("z"),     //
-          FILE_PATH_LITERAL("zip"),   //
-      });
-
-  if (exts->count(ext_without_dot))
+  static constexpr auto kExts = base::MakeFixedFlatSet({
+      FILE_PATH_LITERAL("3g2"),   //
+      FILE_PATH_LITERAL("3gp"),   //
+      FILE_PATH_LITERAL("7z"),    //
+      FILE_PATH_LITERAL("7zip"),  //
+      FILE_PATH_LITERAL("aac"),   //
+      FILE_PATH_LITERAL("avi"),   //
+      FILE_PATH_LITERAL("bz"),    //
+      FILE_PATH_LITERAL("bz2"),   //
+      FILE_PATH_LITERAL("crx"),   //
+      FILE_PATH_LITERAL("gif"),   //
+      FILE_PATH_LITERAL("gz"),    //
+      FILE_PATH_LITERAL("jar"),   //
+      FILE_PATH_LITERAL("jpeg"),  //
+      FILE_PATH_LITERAL("jpg"),   //
+      FILE_PATH_LITERAL("lz"),    //
+      FILE_PATH_LITERAL("m2v"),   //
+      FILE_PATH_LITERAL("m4p"),   //
+      FILE_PATH_LITERAL("m4v"),   //
+      FILE_PATH_LITERAL("mng"),   //
+      FILE_PATH_LITERAL("mov"),   //
+      FILE_PATH_LITERAL("mp2"),   //
+      FILE_PATH_LITERAL("mp3"),   //
+      FILE_PATH_LITERAL("mp4"),   //
+      FILE_PATH_LITERAL("mpe"),   //
+      FILE_PATH_LITERAL("mpeg"),  //
+      FILE_PATH_LITERAL("mpg"),   //
+      FILE_PATH_LITERAL("mpv"),   //
+      FILE_PATH_LITERAL("ogg"),   //
+      FILE_PATH_LITERAL("ogv"),   //
+      FILE_PATH_LITERAL("png"),   //
+      FILE_PATH_LITERAL("qt"),    //
+      FILE_PATH_LITERAL("rar"),   //
+      FILE_PATH_LITERAL("taz"),   //
+      FILE_PATH_LITERAL("tb2"),   //
+      FILE_PATH_LITERAL("tbz"),   //
+      FILE_PATH_LITERAL("tbz2"),  //
+      FILE_PATH_LITERAL("tgz"),   //
+      FILE_PATH_LITERAL("tlz"),   //
+      FILE_PATH_LITERAL("tz"),    //
+      FILE_PATH_LITERAL("tz2"),   //
+      FILE_PATH_LITERAL("vob"),   //
+      FILE_PATH_LITERAL("webm"),  //
+      FILE_PATH_LITERAL("wma"),   //
+      FILE_PATH_LITERAL("wmv"),   //
+      FILE_PATH_LITERAL("xz"),    //
+      FILE_PATH_LITERAL("z"),     //
+      FILE_PATH_LITERAL("zip"),   //
+  });
+
+  if (kExts.count(ext_without_dot)) {
     return kStored;
+  }
 
   return kDeflated;
 }
diff --git a/deps/zlib/google/zip_reader.cc b/deps/zlib/google/zip_reader.cc
index 9b1030a029c8a4..34a815e5f52e9f 100644
--- a/deps/zlib/google/zip_reader.cc
+++ b/deps/zlib/google/zip_reader.cc
@@ -246,14 +246,14 @@ bool ZipReader::OpenEntry() {
 
   // Construct the last modified time. The timezone info is not present in ZIP
   // archives, so we construct the time as UTC.
-  base::Time::Exploded exploded_time = {};
-  exploded_time.year = info.tmu_date.tm_year;
-  exploded_time.month = info.tmu_date.tm_mon + 1;  // 0-based vs 1-based
-  exploded_time.day_of_month = info.tmu_date.tm_mday;
-  exploded_time.hour = info.tmu_date.tm_hour;
-  exploded_time.minute = info.tmu_date.tm_min;
-  exploded_time.second = info.tmu_date.tm_sec;
-  exploded_time.millisecond = 0;
+  const base::Time::Exploded exploded_time = {
+      .year = static_cast(info.tmu_date.tm_year),
+      .month =
+          static_cast(info.tmu_date.tm_mon + 1),  // 0-based vs 1-based
+      .day_of_month = static_cast(info.tmu_date.tm_mday),
+      .hour = static_cast(info.tmu_date.tm_hour),
+      .minute = static_cast(info.tmu_date.tm_min),
+      .second = static_cast(info.tmu_date.tm_sec)};
 
   if (!base::Time::FromUTCExploded(exploded_time, &entry_.last_modified))
     entry_.last_modified = base::Time::UnixEpoch();
diff --git a/deps/zlib/google/zip_reader_unittest.cc b/deps/zlib/google/zip_reader_unittest.cc
index b9175045d07268..6086c97c49b622 100644
--- a/deps/zlib/google/zip_reader_unittest.cc
+++ b/deps/zlib/google/zip_reader_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/functional/bind.h"
 #include "base/hash/md5.h"
+#include "base/i18n/time_formatting.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/strings/string_piece.h"
@@ -31,6 +32,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
+#include "third_party/icu/source/i18n/unicode/timezone.h"
 #include "third_party/zlib/google/zip_internal.h"
 
 using ::testing::_;
@@ -288,18 +290,10 @@ TEST_F(ZipReaderTest, RegularFile) {
 
   EXPECT_EQ(target_path, entry->path);
   EXPECT_EQ(13527, entry->original_size);
-
-  // The expected time stamp: 2009-05-29 06:22:20
-  base::Time::Exploded exploded = {};  // Zero-clear.
-  entry->last_modified.UTCExplode(&exploded);
-  EXPECT_EQ(2009, exploded.year);
-  EXPECT_EQ(5, exploded.month);
-  EXPECT_EQ(29, exploded.day_of_month);
-  EXPECT_EQ(6, exploded.hour);
-  EXPECT_EQ(22, exploded.minute);
-  EXPECT_EQ(20, exploded.second);
-  EXPECT_EQ(0, exploded.millisecond);
-
+  EXPECT_EQ("2009-05-29 06:22:20.000",
+            base::UnlocalizedTimeFormatWithPattern(entry->last_modified,
+                                                   "y-MM-dd HH:mm:ss.SSS",
+                                                   icu::TimeZone::getGMT()));
   EXPECT_FALSE(entry->is_unsafe);
   EXPECT_FALSE(entry->is_directory);
 }
@@ -396,18 +390,10 @@ TEST_F(ZipReaderTest, Directory) {
   EXPECT_EQ(target_path, entry->path);
   // The directory size should be zero.
   EXPECT_EQ(0, entry->original_size);
-
-  // The expected time stamp: 2009-05-31 15:49:52
-  base::Time::Exploded exploded = {};  // Zero-clear.
-  entry->last_modified.UTCExplode(&exploded);
-  EXPECT_EQ(2009, exploded.year);
-  EXPECT_EQ(5, exploded.month);
-  EXPECT_EQ(31, exploded.day_of_month);
-  EXPECT_EQ(15, exploded.hour);
-  EXPECT_EQ(49, exploded.minute);
-  EXPECT_EQ(52, exploded.second);
-  EXPECT_EQ(0, exploded.millisecond);
-
+  EXPECT_EQ("2009-05-31 15:49:52.000",
+            base::UnlocalizedTimeFormatWithPattern(entry->last_modified,
+                                                   "y-MM-dd HH:mm:ss.SSS",
+                                                   icu::TimeZone::getGMT()));
   EXPECT_FALSE(entry->is_unsafe);
   EXPECT_TRUE(entry->is_directory);
 }
diff --git a/deps/zlib/patches/0000-build.patch b/deps/zlib/patches/0000-build.patch
index b7c59964822096..6119f09c05b73c 100644
--- a/deps/zlib/patches/0000-build.patch
+++ b/deps/zlib/patches/0000-build.patch
@@ -1,16 +1,3 @@
-diff --git a/contrib/minizip/ioapi.h b/contrib/minizip/ioapi.h
-index 8dcbdb06e35a..c1b7a54847f5 100644
---- a/contrib/minizip/ioapi.h
-+++ b/contrib/minizip/ioapi.h
-@@ -43,7 +43,7 @@
- 
- #include 
- #include 
--#include "zlib.h"
-+#include "third_party/zlib/zlib.h"
- 
- #if defined(USE_FILE32API)
- #define fopen64 fopen
 diff --git a/contrib/minizip/iowin32.c b/contrib/minizip/iowin32.c
 index 274f39eb1dd2..246ceb91a139 100644
 --- a/contrib/minizip/iowin32.c
@@ -35,45 +22,10 @@ index 274f39eb1dd2..246ceb91a139 100644
  
  voidpf  ZCALLBACK win32_open_file_func  OF((voidpf opaque, const char* filename, int mode));
  uLong   ZCALLBACK win32_read_file_func  OF((voidpf opaque, voidpf stream, void* buf, uLong size));
-diff --git a/contrib/minizip/mztools.c b/contrib/minizip/mztools.c
-index 96891c2e0b71..8bf9cca32633 100644
---- a/contrib/minizip/mztools.c
-+++ b/contrib/minizip/mztools.c
-@@ -8,7 +8,7 @@
- #include 
- #include 
- #include 
--#include "zlib.h"
-+#include "third_party/zlib/zlib.h"
- #include "unzip.h"
- 
- #define READ_8(adr)  ((unsigned char)*(adr))
-diff --git a/contrib/minizip/mztools.h b/contrib/minizip/mztools.h
-index a49a426ec2fc..f295ffeda6af 100644
---- a/contrib/minizip/mztools.h
-+++ b/contrib/minizip/mztools.h
-@@ -12,7 +12,7 @@ extern "C" {
- #endif
- 
- #ifndef _ZLIB_H
--#include "zlib.h"
-+#include "third_party/zlib/zlib.h"
- #endif
- 
- #include "unzip.h"
 diff --git a/contrib/minizip/unzip.c b/contrib/minizip/unzip.c
 index bcfb9416ec35..199b4723fcfc 100644
 --- a/contrib/minizip/unzip.c
 +++ b/contrib/minizip/unzip.c
-@@ -72,7 +72,7 @@
-         #define NOUNCRYPT
- #endif
- 
--#include "zlib.h"
-+#include "third_party/zlib/zlib.h"
- #include "unzip.h"
- 
- #ifdef STDC
 @@ -1705,11 +1705,6 @@ extern int ZEXPORT unzReadCurrentFile  (unzFile file, voidp buf, unsigned len)
  
      pfile_in_zip_read_info->stream.avail_out = (uInt)len;
@@ -86,45 +38,6 @@ index bcfb9416ec35..199b4723fcfc 100644
      if ((len>pfile_in_zip_read_info->rest_read_compressed+
             pfile_in_zip_read_info->stream.avail_in) &&
           (pfile_in_zip_read_info->raw))
-diff --git a/contrib/minizip/unzip.h b/contrib/minizip/unzip.h
-index 2104e3915074..3c0143529b91 100644
---- a/contrib/minizip/unzip.h
-+++ b/contrib/minizip/unzip.h
-@@ -48,7 +48,7 @@ extern "C" {
- #endif
- 
- #ifndef _ZLIB_H
--#include "zlib.h"
-+#include "third_party/zlib/zlib.h"
- #endif
- 
- #ifndef  _ZLIBIOAPI_H
-diff --git a/contrib/minizip/zip.c b/contrib/minizip/zip.c
-index 44e88a9cb989..65c0c7251843 100644
---- a/contrib/minizip/zip.c
-+++ b/contrib/minizip/zip.c
-@@ -26,7 +26,7 @@
- #include 
- #include 
- #include 
--#include "zlib.h"
-+#include "third_party/zlib/zlib.h"
- #include "zip.h"
- 
- #ifdef STDC
-diff --git a/contrib/minizip/zip.h b/contrib/minizip/zip.h
-index 8aaebb623430..8c06c0aa7bb0 100644
---- a/contrib/minizip/zip.h
-+++ b/contrib/minizip/zip.h
-@@ -47,7 +47,7 @@ extern "C" {
- //#define HAVE_BZIP2
- 
- #ifndef _ZLIB_H
--#include "zlib.h"
-+#include "third_party/zlib/zlib.h"
- #endif
- 
- #ifndef _ZLIBIOAPI_H
 diff --git a/gzread.c b/gzread.c
 index 956b91ea7d9e..832d3ef98c59 100644
 --- a/gzread.c
diff --git a/deps/zlib/patches/0013-cpu-feature-detection-for-arm.patch b/deps/zlib/patches/0013-cpu-feature-detection-for-arm.patch
new file mode 100644
index 00000000000000..0547851fe5d99d
--- /dev/null
+++ b/deps/zlib/patches/0013-cpu-feature-detection-for-arm.patch
@@ -0,0 +1,30 @@
+From c43ba7a55f091c0dcbfd8d89f7a5121269ce1b81 Mon Sep 17 00:00:00 2001
+From: Ho Cheung 
+Date: Thu, 27 Jul 2023 09:47:52 +0800
+Subject: [PATCH] [zlib] Perform CPU feature detection for ARM inside adler32()
+
+Perform CPU feature detection for ARM within adler32() to have the same
+behavior as x86.
+
+---
+ third_party/zlib/adler32.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/third_party/zlib/adler32.c b/third_party/zlib/adler32.c
+index 81c584f68e233..99a294496f7eb 100644
+--- a/third_party/zlib/adler32.c
++++ b/third_party/zlib/adler32.c
+@@ -90,9 +90,9 @@ uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, z_size_t len) {
+         return adler | (sum2 << 16);
+     }
+
+-#if defined(ADLER32_SIMD_SSSE3)
++#if defined(ADLER32_SIMD_SSSE3) || defined(ADLER32_SIMD_NEON)
+     /*
+-     * Use SSSE3 to compute the adler32. Since this routine can be
++     * Use SIMD to compute the adler32. Since this function can be
+      * freely used, check CPU features here. zlib convention is to
+      * call adler32(0, NULL, 0), before making calls to adler32().
+      * So this is a good early (and infrequent) place to cache CPU
+--
+2.41.0.windows.3
diff --git a/doc/api/async_hooks.md b/doc/api/async_hooks.md
index 1b408ba97b717c..a5571c30be575d 100644
--- a/doc/api/async_hooks.md
+++ b/doc/api/async_hooks.md
@@ -768,6 +768,7 @@ import { executionAsyncId } from 'node:async_hooks';
 import fs from 'node:fs';
 
 console.log(executionAsyncId());  // 1 - bootstrap
+const path = '.';
 fs.open(path, 'r', (err, fd) => {
   console.log(executionAsyncId());  // 6 - open()
 });
@@ -778,6 +779,7 @@ const async_hooks = require('node:async_hooks');
 const fs = require('node:fs');
 
 console.log(async_hooks.executionAsyncId());  // 1 - bootstrap
+const path = '.';
 fs.open(path, 'r', (err, fd) => {
   console.log(async_hooks.executionAsyncId());  // 6 - open()
 });
diff --git a/doc/api/cli.md b/doc/api/cli.md
index 31ed14ce2730e4..e17d4c25f8bedb 100644
--- a/doc/api/cli.md
+++ b/doc/api/cli.md
@@ -25,14 +25,16 @@ For more info about `node inspect`, see the [debugger][] documentation.
 
 The program entry point is a specifier-like string. If the string is not an
 absolute path, it's resolved as a relative path from the current working
-directory. That path is then resolved by [CommonJS][] module loader. If no
-corresponding file is found, an error is thrown.
+directory. That path is then resolved by [CommonJS][] module loader, or by the
+[ES module loader][Modules loaders] if [`--experimental-default-type=module`][]
+is passed. If no corresponding file is found, an error is thrown.
 
-If a file is found, its path will be passed to the [ECMAScript module loader][]
-under any of the following conditions:
+If a file is found, its path will be passed to the
+[ES module loader][Modules loaders] under any of the following conditions:
 
 * The program was started with a command-line flag that forces the entry
-  point to be loaded with ECMAScript module loader.
+  point to be loaded with ECMAScript module loader, such as `--import` or
+  [`--experimental-default-type=module`][].
 * The file has an `.mjs` extension.
 * The file does not have a `.cjs` extension, and the nearest parent
   `package.json` file contains a top-level [`"type"`][] field with a value of
@@ -43,10 +45,11 @@ Otherwise, the file is loaded using the CommonJS module loader. See
 
 ### ECMAScript modules loader entry point caveat
 
-When loading [ECMAScript module loader][] loads the program entry point, the `node`
-command will only accept as input only files with `.js`, `.mjs`, or `.cjs`
-extensions; and with `.wasm` extensions when
-[`--experimental-wasm-modules`][] is enabled.
+When loading, the [ES module loader][Modules loaders] loads the program
+entry point, the `node` command will accept as input only files with `.js`,
+`.mjs`, or `.cjs` extensions; with `.wasm` extensions when
+[`--experimental-wasm-modules`][] is enabled; and with no extension when
+[`--experimental-default-type=module`][] is passed.
 
 ## Options
 
@@ -366,15 +369,54 @@ added: v17.6.0
 
 Expose the [Web Crypto API][] on the global scope.
 
+### `--experimental-default-type=type`
+
+
+
+> Stability: 1.0 - Early development
+
+Define which module system, `module` or `commonjs`, to use for the following:
+
+* String input provided via `--eval` or STDIN, if `--input-type` is unspecified.
+
+* Files ending in `.js` or with no extension, if there is no `package.json` file
+  present in the same folder or any parent folder.
+
+* Files ending in `.js` or with no extension, if the nearest parent
+  `package.json` field lacks a `"type"` field; unless the `package.json` folder
+  or any parent folder is inside a `node_modules` folder.
+
+In other words, `--experimental-default-type=module` flips all the places where
+Node.js currently defaults to CommonJS to instead default to ECMAScript modules,
+with the exception of folders and subfolders below `node_modules`, for backward
+compatibility.
+
+Under `--experimental-default-type=module` and `--experimental-wasm-modules`,
+files with no extension will be treated as WebAssembly if they begin with the
+WebAssembly magic number (`\0asm`); otherwise they will be treated as ES module
+JavaScript.
+
 ### `--experimental-import-meta-resolve`
 
 
 
-Enable experimental `import.meta.resolve()` support.
+Enable experimental `import.meta.resolve()` parent URL support, which allows
+passing a second `parentURL` argument for contextual resolution.
+
+Previously gated the entire `import.meta.resolve` feature.
 
 ### `--experimental-loader=module`
 
@@ -387,7 +429,11 @@ changes:
                  `--experimental-loader`.
 -->
 
-Specify the `module` of a custom experimental [ECMAScript module loader][].
+> This flag is discouraged and may be removed in a future version of Node.js.
+> Please use
+> [`--import` with `register()`][module customization hooks: enabling] instead.
+
+Specify the `module` containing exported [module customization hooks][].
 `module` may be any string accepted as an [`import` specifier][].
 
 ### `--experimental-network-imports`
@@ -1252,6 +1298,15 @@ Starts the Node.js command line test runner. This flag cannot be combined with
 See the documentation on [running tests from the command line][]
 for more details.
 
+### `--test-concurrency`
+
+
+
+The maximum number of test files that the test runner CLI will execute
+concurrently. The default value is `os.availableParallelism() - 1`.
+
 ### `--test-name-pattern`
 
 
+
+Test suite shard to execute in a format of `/`, where
+
+`index` is a positive integer, index of divided parts
+`total` is a positive integer, total of divided part
+This command will divide all tests files into `total` equal parts,
+and will run only those that happen to be in an `index` part.
+
+For example, to split your tests suite into three parts, use this:
+
+```bash
+node --test --test-shard=1/3
+node --test --test-shard=2/3
+node --test --test-shard=3/3
+```
+
 ### `--throw-deprecation`
 
 
+
+> Stability: 1 - Experimental
+
+* `nameOrChannels` {string|TracingChannel} Channel name or
+  object containing all the [TracingChannel Channels][]
+* Returns: {TracingChannel} Collection of channels to trace with
+
+Creates a [`TracingChannel`][] wrapper for the given
+[TracingChannel Channels][]. If a name is given, the corresponding tracing
+channels will be created in the form of `tracing:${name}:${eventType}` where
+`eventType` corresponds to the types of [TracingChannel Channels][].
+
+```mjs
+import diagnostics_channel from 'node:diagnostics_channel';
+
+const channelsByName = diagnostics_channel.tracingChannel('my-channel');
+
+// or...
+
+const channelsByCollection = diagnostics_channel.tracingChannel({
+  start: diagnostics_channel.channel('tracing:my-channel:start'),
+  end: diagnostics_channel.channel('tracing:my-channel:end'),
+  asyncStart: diagnostics_channel.channel('tracing:my-channel:asyncStart'),
+  asyncEnd: diagnostics_channel.channel('tracing:my-channel:asyncEnd'),
+  error: diagnostics_channel.channel('tracing:my-channel:error'),
+});
+```
+
+```cjs
+const diagnostics_channel = require('node:diagnostics_channel');
+
+const channelsByName = diagnostics_channel.tracingChannel('my-channel');
+
+// or...
+
+const channelsByCollection = diagnostics_channel.tracingChannel({
+  start: diagnostics_channel.channel('tracing:my-channel:start'),
+  end: diagnostics_channel.channel('tracing:my-channel:end'),
+  asyncStart: diagnostics_channel.channel('tracing:my-channel:asyncStart'),
+  asyncEnd: diagnostics_channel.channel('tracing:my-channel:asyncEnd'),
+  error: diagnostics_channel.channel('tracing:my-channel:error'),
+});
+```
+
 ### Class: `Channel`
 
 
+
+> Stability: 1 - Experimental
+
+* `store` {AsyncLocalStorage} The store to which to bind the context data
+* `transform` {Function} Transform context data before setting the store context
+
+When [`channel.runStores(context, ...)`][] is called, the given context data
+will be applied to any store bound to the channel. If the store has already been
+bound the previous `transform` function will be replaced with the new one.
+The `transform` function may be omitted to set the given context data as the
+context directly.
+
+```mjs
+import diagnostics_channel from 'node:diagnostics_channel';
+import { AsyncLocalStorage } from 'node:async_hooks';
+
+const store = new AsyncLocalStorage();
+
+const channel = diagnostics_channel.channel('my-channel');
+
+channel.bindStore(store, (data) => {
+  return { data };
+});
+```
+
+```cjs
+const diagnostics_channel = require('node:diagnostics_channel');
+const { AsyncLocalStorage } = require('node:async_hooks');
+
+const store = new AsyncLocalStorage();
+
+const channel = diagnostics_channel.channel('my-channel');
+
+channel.bindStore(store, (data) => {
+  return { data };
+});
+```
+
+#### `channel.unbindStore(store)`
+
+
+
+> Stability: 1 - Experimental
+
+* `store` {AsyncLocalStorage} The store to unbind from the channel.
+* Returns: {boolean} `true` if the store was found, `false` otherwise.
+
+Remove a message handler previously registered to this channel with
+[`channel.bindStore(store)`][].
+
+```mjs
+import diagnostics_channel from 'node:diagnostics_channel';
+import { AsyncLocalStorage } from 'node:async_hooks';
+
+const store = new AsyncLocalStorage();
+
+const channel = diagnostics_channel.channel('my-channel');
+
+channel.bindStore(store);
+channel.unbindStore(store);
+```
+
+```cjs
+const diagnostics_channel = require('node:diagnostics_channel');
+const { AsyncLocalStorage } = require('node:async_hooks');
+
+const store = new AsyncLocalStorage();
+
+const channel = diagnostics_channel.channel('my-channel');
+
+channel.bindStore(store);
+channel.unbindStore(store);
+```
+
+#### `channel.runStores(context, fn[, thisArg[, ...args]])`
+
+
+
+> Stability: 1 - Experimental
+
+* `context` {any} Message to send to subscribers and bind to stores
+* `fn` {Function} Handler to run within the entered storage context
+* `thisArg` {any} The receiver to be used for the function call.
+* `...args` {any} Optional arguments to pass to the function.
+
+Applies the given data to any AsyncLocalStorage instances bound to the channel
+for the duration of the given function, then publishes to the channel within
+the scope of that data is applied to the stores.
+
+If a transform function was given to [`channel.bindStore(store)`][] it will be
+applied to transform the message data before it becomes the context value for
+the store. The prior storage context is accessible from within the transform
+function in cases where context linking is required.
+
+The context applied to the store should be accesible in any async code which
+continues from execution which began during the given function, however
+there are some situations in which [context loss][] may occur.
+
+```mjs
+import diagnostics_channel from 'node:diagnostics_channel';
+import { AsyncLocalStorage } from 'node:async_hooks';
+
+const store = new AsyncLocalStorage();
+
+const channel = diagnostics_channel.channel('my-channel');
+
+channel.bindStore(store, (message) => {
+  const parent = store.getStore();
+  return new Span(message, parent);
+});
+channel.runStores({ some: 'message' }, () => {
+  store.getStore(); // Span({ some: 'message' })
+});
+```
+
+```cjs
+const diagnostics_channel = require('node:diagnostics_channel');
+const { AsyncLocalStorage } = require('node:async_hooks');
+
+const store = new AsyncLocalStorage();
+
+const channel = diagnostics_channel.channel('my-channel');
+
+channel.bindStore(store, (message) => {
+  const parent = store.getStore();
+  return new Span(message, parent);
+});
+channel.runStores({ some: 'message' }, () => {
+  store.getStore(); // Span({ some: 'message' })
+});
+```
+
+### Class: `TracingChannel`
+
+
+
+> Stability: 1 - Experimental
+
+The class `TracingChannel` is a collection of [TracingChannel Channels][] which
+together express a single traceable action. It is used to formalize and
+simplify the process of producing events for tracing application flow.
+[`diagnostics_channel.tracingChannel()`][] is used to construct a
+`TracingChannel`. As with `Channel` it is recommended to create and reuse a
+single `TracingChannel` at the top-level of the file rather than creating them
+dynamically.
+
+#### `tracingChannel.subscribe(subscribers)`
+
+
+
+> Stability: 1 - Experimental
+
+* `subscribers` {Object} Set of [TracingChannel Channels][] subscribers
+  * `start` {Function} The [`start` event][] subscriber
+  * `end` {Function} The [`end` event][] subscriber
+  * `asyncStart` {Function} The [`asyncStart` event][] subscriber
+  * `asyncEnd` {Function} The [`asyncEnd` event][] subscriber
+  * `error` {Function} The [`error` event][] subscriber
+
+Helper to subscribe a collection of functions to the corresponding channels.
+This is the same as calling [`channel.subscribe(onMessage)`][] on each channel
+individually.
+
+```mjs
+import diagnostics_channel from 'node:diagnostics_channel';
+
+const channels = diagnostics_channel.tracingChannel('my-channel');
+
+channels.subscribe({
+  start(message) {
+    // Handle start message
+  },
+  end(message) {
+    // Handle end message
+  },
+  asyncStart(message) {
+    // Handle asyncStart message
+  },
+  asyncEnd(message) {
+    // Handle asyncEnd message
+  },
+  error(message) {
+    // Handle error message
+  },
+});
+```
+
+```cjs
+const diagnostics_channel = require('node:diagnostics_channel');
+
+const channels = diagnostics_channel.tracingChannel('my-channel');
+
+channels.subscribe({
+  start(message) {
+    // Handle start message
+  },
+  end(message) {
+    // Handle end message
+  },
+  asyncStart(message) {
+    // Handle asyncStart message
+  },
+  asyncEnd(message) {
+    // Handle asyncEnd message
+  },
+  error(message) {
+    // Handle error message
+  },
+});
+```
+
+#### `tracingChannel.unsubscribe(subscribers)`
+
+
+
+> Stability: 1 - Experimental
+
+* `subscribers` {Object} Set of [TracingChannel Channels][] subscribers
+  * `start` {Function} The [`start` event][] subscriber
+  * `end` {Function} The [`end` event][] subscriber
+  * `asyncStart` {Function} The [`asyncStart` event][] subscriber
+  * `asyncEnd` {Function} The [`asyncEnd` event][] subscriber
+  * `error` {Function} The [`error` event][] subscriber
+* Returns: {boolean} `true` if all handlers were successfully unsubscribed,
+  and `false` otherwise.
+
+Helper to unsubscribe a collection of functions from the corresponding channels.
+This is the same as calling [`channel.unsubscribe(onMessage)`][] on each channel
+individually.
+
+```mjs
+import diagnostics_channel from 'node:diagnostics_channel';
+
+const channels = diagnostics_channel.tracingChannel('my-channel');
+
+channels.unsubscribe({
+  start(message) {
+    // Handle start message
+  },
+  end(message) {
+    // Handle end message
+  },
+  asyncStart(message) {
+    // Handle asyncStart message
+  },
+  asyncEnd(message) {
+    // Handle asyncEnd message
+  },
+  error(message) {
+    // Handle error message
+  },
+});
+```
+
+```cjs
+const diagnostics_channel = require('node:diagnostics_channel');
+
+const channels = diagnostics_channel.tracingChannel('my-channel');
+
+channels.unsubscribe({
+  start(message) {
+    // Handle start message
+  },
+  end(message) {
+    // Handle end message
+  },
+  asyncStart(message) {
+    // Handle asyncStart message
+  },
+  asyncEnd(message) {
+    // Handle asyncEnd message
+  },
+  error(message) {
+    // Handle error message
+  },
+});
+```
+
+#### `tracingChannel.traceSync(fn[, context[, thisArg[, ...args]]])`
+
+
+
+> Stability: 1 - Experimental
+
+* `fn` {Function} Function to wrap a trace around
+* `context` {Object} Shared object to correlate events through
+* `thisArg` {any} The receiver to be used for the function call
+* `...args` {any} Optional arguments to pass to the function
+* Returns: {any} The return value of the given function
+
+Trace a synchronous function call. This will always produce a [`start` event][]
+and [`end` event][] around the execution and may produce an [`error` event][]
+if the given function throws an error. This will run the given function using
+[`channel.runStores(context, ...)`][] on the `start` channel which ensures all
+events should have any bound stores set to match this trace context.
+
+```mjs
+import diagnostics_channel from 'node:diagnostics_channel';
+
+const channels = diagnostics_channel.tracingChannel('my-channel');
+
+channels.traceSync(() => {
+  // Do something
+}, {
+  some: 'thing',
+});
+```
+
+```cjs
+const diagnostics_channel = require('node:diagnostics_channel');
+
+const channels = diagnostics_channel.tracingChannel('my-channel');
+
+channels.traceSync(() => {
+  // Do something
+}, {
+  some: 'thing',
+});
+```
+
+#### `tracingChannel.tracePromise(fn[, context[, thisArg[, ...args]]])`
+
+
+
+> Stability: 1 - Experimental
+
+* `fn` {Function} Promise-returning function to wrap a trace around
+* `context` {Object} Shared object to correlate trace events through
+* `thisArg` {any} The receiver to be used for the function call
+* `...args` {any} Optional arguments to pass to the function
+* Returns: {Promise} Chained from promise returned by the given function
+
+Trace a promise-returning function call. This will always produce a
+[`start` event][] and [`end` event][] around the synchronous portion of the
+function execution, and will produce an [`asyncStart` event][] and
+[`asyncEnd` event][] when a promise continuation is reached. It may also
+produce an [`error` event][] if the given function throws an error or the
+returned promise rejects. This will run the given function using
+[`channel.runStores(context, ...)`][] on the `start` channel which ensures all
+events should have any bound stores set to match this trace context.
+
+```mjs
+import diagnostics_channel from 'node:diagnostics_channel';
+
+const channels = diagnostics_channel.tracingChannel('my-channel');
+
+channels.tracePromise(async () => {
+  // Do something
+}, {
+  some: 'thing',
+});
+```
+
+```cjs
+const diagnostics_channel = require('node:diagnostics_channel');
+
+const channels = diagnostics_channel.tracingChannel('my-channel');
+
+channels.tracePromise(async () => {
+  // Do something
+}, {
+  some: 'thing',
+});
+```
+
+#### `tracingChannel.traceCallback(fn[, position[, context[, thisArg[, ...args]]]])`
+
+
+
+> Stability: 1 - Experimental
+
+* `fn` {Function} callback using function to wrap a trace around
+* `position` {number} Zero-indexed argument position of expected callback
+* `context` {Object} Shared object to correlate trace events through
+* `thisArg` {any} The receiver to be used for the function call
+* `...args` {any} Optional arguments to pass to the function
+* Returns: {any} The return value of the given function
+
+Trace a callback-receiving function call. This will always produce a
+[`start` event][] and [`end` event][] around the synchronous portion of the
+function execution, and will produce a [`asyncStart` event][] and
+[`asyncEnd` event][] around the callback execution. It may also produce an
+[`error` event][] if the given function throws an error or the returned
+promise rejects. This will run the given function using
+[`channel.runStores(context, ...)`][] on the `start` channel which ensures all
+events should have any bound stores set to match this trace context.
+
+The `position` will be -1 by default to indicate the final argument should
+be used as the callback.
+
+```mjs
+import diagnostics_channel from 'node:diagnostics_channel';
+
+const channels = diagnostics_channel.tracingChannel('my-channel');
+
+channels.traceCallback((arg1, callback) => {
+  // Do something
+  callback(null, 'result');
+}, 1, {
+  some: 'thing',
+}, thisArg, arg1, callback);
+```
+
+```cjs
+const diagnostics_channel = require('node:diagnostics_channel');
+
+const channels = diagnostics_channel.tracingChannel('my-channel');
+
+channels.traceCallback((arg1, callback) => {
+  // Do something
+  callback(null, 'result');
+}, {
+  some: 'thing',
+}, thisArg, arg1, callback);
+```
+
+The callback will also be run with [`channel.runStores(context, ...)`][] which
+enables context loss recovery in some cases.
+
+```mjs
+import diagnostics_channel from 'node:diagnostics_channel';
+import { AsyncLocalStorage } from 'node:async_hooks';
+
+const channels = diagnostics_channel.tracingChannel('my-channel');
+const myStore = new AsyncLocalStorage();
+
+// The start channel sets the initial store data to something
+// and stores that store data value on the trace context object
+channels.start.bindStore(myStore, (data) => {
+  const span = new Span(data);
+  data.span = span;
+  return span;
+});
+
+// Then asyncStart can restore from that data it stored previously
+channels.asyncStart.bindStore(myStore, (data) => {
+  return data.span;
+});
+```
+
+```cjs
+const diagnostics_channel = require('node:diagnostics_channel');
+const { AsyncLocalStorage } = require('node:async_hooks');
+
+const channels = diagnostics_channel.tracingChannel('my-channel');
+const myStore = new AsyncLocalStorage();
+
+// The start channel sets the initial store data to something
+// and stores that store data value on the trace context object
+channels.start.bindStore(myStore, (data) => {
+  const span = new Span(data);
+  data.span = span;
+  return span;
+});
+
+// Then asyncStart can restore from that data it stored previously
+channels.asyncStart.bindStore(myStore, (data) => {
+  return data.span;
+});
+```
+
+### TracingChannel Channels
+
+A TracingChannel is a collection of several diagnostics\_channels representing
+specific points in the execution lifecycle of a single traceable action. The
+behaviour is split into five diagnostics\_channels consisting of `start`,
+`end`, `asyncStart`, `asyncEnd`, and `error`. A single traceable action will
+share the same event object between all events, this can be helpful for
+managing correlation through a weakmap.
+
+These event objects will be extended with `result` or `error` values when
+the task "completes". In the case of a synchronous task the `result` will be
+the return value and the `error` will be anything thrown from the function.
+With callback-based async functions the `result` will be the second argument
+of the callback while the `error` will either be a thrown error visible in the
+`end` event or the first callback argument in either of the `asyncStart` or
+`asyncEnd` events.
+
+Tracing channels should follow a naming pattern of:
+
+* `tracing:module.class.method:start` or `tracing:module.function:start`
+* `tracing:module.class.method:end` or `tracing:module.function:end`
+* `tracing:module.class.method:asyncStart` or `tracing:module.function:asyncStart`
+* `tracing:module.class.method:asyncEnd` or `tracing:module.function:asyncEnd`
+* `tracing:module.class.method:error` or `tracing:module.function:error`
+
+#### `start(event)`
+
+* Name: `tracing:${name}:start`
+
+The `start` event represents the point at which a function is called. At this
+point the event data may contain function arguments or anything else available
+at the very start of the execution of the function.
+
+#### `end(event)`
+
+* Name: `tracing:${name}:end`
+
+The `end` event represents the point at which a function call returns a value.
+In the case of an async function this is when the promise returned not when the
+function itself makes a return statement internally. At this point, if the
+traced function was synchronous the `result` field will be set to the return
+value of the function. Alternatively, the `error` field may be present to
+represent any thrown errors.
+
+It is recommended to listen specifically to the `error` event to track errors
+as it may be possible for a traceable action to produce multiple errors. For
+example, an async task which fails may be started internally before the sync
+part of the task then throws an error.
+
+#### `asyncStart(event)`
+
+* Name: `tracing:${name}:asyncStart`
+
+The `asyncStart` event represents the callback or continuation of a traceable
+function being reached. At this point things like callback arguments may be
+available, or anything else expressing the "result" of the action.
+
+For callbacks-based functions, the first argument of the callback will be
+assigned to the `error` field, if not `undefined` or `null`, and the second
+argument will be assigned to the `result` field.
+
+For promises, the argument to the `resolve` path will be assigned to `result`
+or the argument to the `reject` path will be assign to `error`.
+
+It is recommended to listen specifically to the `error` event to track errors
+as it may be possible for a traceable action to produce multiple errors. For
+example, an async task which fails may be started internally before the sync
+part of the task then throws an error.
+
+#### `asyncEnd(event)`
+
+* Name: `tracing:${name}:asyncEnd`
+
+The `asyncEnd` event represents the callback of an asynchronous function
+returning. It's not likely event data will change after the `asyncStart` event,
+however it may be useful to see the point where the callback completes.
+
+#### `error(event)`
+
+* Name: `tracing:${name}:error`
+
+The `error` event represents any error produced by the traceable function
+either synchronously or asynchronously. If an error is thrown in the
+synchronous portion of the traced function the error will be assigned to the
+`error` field of the event and the `error` event will be triggered. If an error
+is received asynchronously through a callback or promise rejection it will also
+be assigned to the `error` field of the event and trigger the `error` event.
+
+It is possible for a single traceable function call to produce errors multiple
+times so this should be considered when consuming this event. For example, if
+another async task is triggered internally which fails and then the sync part
+of the function then throws and error two `error` events will be emitted, one
+for the sync error and one for the async error.
+
 ### Built-in Channels
 
 > Stability: 1 - Experimental
@@ -462,8 +1097,20 @@ Emitted when a new TCP or pipe connection is received.
 
 Emitted when a new UDP socket is created.
 
+[TracingChannel Channels]: #tracingchannel-channels
 [`'uncaughtException'`]: process.md#event-uncaughtexception
+[`TracingChannel`]: #class-tracingchannel
+[`asyncEnd` event]: #asyncendevent
+[`asyncStart` event]: #asyncstartevent
+[`channel.bindStore(store)`]: #channelbindstorestore-transform
+[`channel.runStores(context, ...)`]: #channelrunstorescontext-fn-thisarg-args
 [`channel.subscribe(onMessage)`]: #channelsubscribeonmessage
+[`channel.unsubscribe(onMessage)`]: #channelunsubscribeonmessage
 [`diagnostics_channel.channel(name)`]: #diagnostics_channelchannelname
 [`diagnostics_channel.subscribe(name, onMessage)`]: #diagnostics_channelsubscribename-onmessage
+[`diagnostics_channel.tracingChannel()`]: #diagnostics_channeltracingchannelnameorchannels
 [`diagnostics_channel.unsubscribe(name, onMessage)`]: #diagnostics_channelunsubscribename-onmessage
+[`end` event]: #endevent
+[`error` event]: #errorevent
+[`start` event]: #startevent
+[context loss]: async_context.md#troubleshooting-context-loss
diff --git a/doc/api/errors.md b/doc/api/errors.md
index 9c88b7d7d4de0f..fee0ed89e4b844 100644
--- a/doc/api/errors.md
+++ b/doc/api/errors.md
@@ -1762,7 +1762,8 @@ added:
   - v16.14.0
 -->
 
-An import assertion has failed, preventing the specified module to be imported.
+An import `type` attribute was provided, but the specified module is of a
+different type.
 
 
 
@@ -1774,7 +1775,7 @@ added:
   - v16.14.0
 -->
 
-An import assertion is missing, preventing the specified module to be imported.
+An import attribute is missing, preventing the specified module to be imported.
 
 
 
@@ -1786,7 +1787,17 @@ added:
   - v16.14.0
 -->
 
-An import assertion is not supported by this version of Node.js.
+An import attribute is not supported by this version of Node.js.
+
+
+
+### `ERR_IMPORT_ATTRIBUTE_UNSUPPORTED`
+
+
+
+An import attribute is not supported by this version of Node.js.
 
 
 
@@ -2708,6 +2719,20 @@ This error represents a failed test. Additional information about the failure
 is available via the `cause` property. The `failureType` property specifies
 what the test was doing when the failure occurred.
 
+
+
+### `ERR_TLS_ALPN_CALLBACK_INVALID_RESULT`
+
+This error is thrown when an `ALPNCallback` returns a value that is not in the
+list of ALPN protocols offered by the client.
+
+
+
+### `ERR_TLS_ALPN_CALLBACK_WITH_PROTOCOLS`
+
+This error is thrown when creating a `TLSServer` if the TLS options include
+both `ALPNProtocols` and `ALPNCallback`. These options are mutually exclusive.
+
 
 
 ### `ERR_TLS_CERT_ALTNAME_FORMAT`
diff --git a/doc/api/esm.md b/doc/api/esm.md
index 8f147b9c2445b2..9b629f2a2a997d 100644
--- a/doc/api/esm.md
+++ b/doc/api/esm.md
@@ -7,21 +7,24 @@
 
 
@@ -230,17 +234,28 @@ absolute URL strings.
 import fs from 'node:fs/promises';
 ```
 
-## Import assertions
+
+
+## Import attributes
 
 
 
-> Stability: 1 - Experimental
+> Stability: 1.1 - Active development
 
-The [Import Assertions proposal][] adds an inline syntax for module import
+> This feature was previously named "Import assertions", and using the `assert`
+> keyword instead of `with`. Because the version of V8 on this release line does
+> not support the `with` keyword, you need to keep using `assert` to support
+> this version of Node.js.
+
+The [Import Attributes proposal][] adds an inline syntax for module import
 statements to pass on more information alongside the module specifier.
 
 ```js
@@ -250,10 +265,10 @@ const { default: barData } =
   await import('./bar.json', { assert: { type: 'json' } });
 ```
 
-Node.js supports the following `type` values, for which the assertion is
+Node.js supports the following `type` values, for which the attribute is
 mandatory:
 
-| Assertion `type` | Needed for       |
+| Attribute `type` | Needed for       |
 | ---------------- | ---------------- |
 | `'json'`         | [JSON modules][] |
 
@@ -318,13 +333,24 @@ import { readFileSync } from 'node:fs';
 const buffer = readFileSync(new URL('./data.proto', import.meta.url));
 ```
 
-### `import.meta.resolve(specifier[, parent])`
+### `import.meta.resolve(specifier)`
 
-
 
-> Stability: 1 - Experimental
-
-This feature is only available with the `--experimental-import-meta-resolve`
-command flag enabled.
+> Stability: 1.2 - Release candidate
 
-* `specifier` {string} The module specifier to resolve relative to `parent`.
-* `parent` {string|URL} The absolute parent module URL to resolve from. If none
-  is specified, the value of `import.meta.url` is used as the default.
-* Returns: {Promise}
+* `specifier` {string} The module specifier to resolve relative to the
+  current module.
+* Returns: {string} The absolute URL string that the specifier would resolve to.
 
-Provides a module-relative resolution function scoped to each module, returning
-the URL string.
-
-
+[`import.meta.resolve`][] is a module-relative resolution function scoped to
+each module, returning the URL string.
 
 ```js
-const dependencyAsset = await import.meta.resolve('component-lib/asset.css');
+const dependencyAsset = import.meta.resolve('component-lib/asset.css');
+// file:///app/node_modules/component-lib/asset.css
+import.meta.resolve('./dep.js');
+// file:///app/dep.js
 ```
 
-`import.meta.resolve` also accepts a second argument which is the parent module
-from which to resolve from:
+All features of the Node.js module resolution are supported. Dependency
+resolutions are subject to the permitted exports resolutions within the package.
 
-
+**Caveats**:
 
-```js
-await import.meta.resolve('./dep', import.meta.url);
-```
+* This can result in synchronous file-system operations, which
+  can impact performance similarly to `require.resolve`.
+* This feature is not available within custom loaders (it would
+  create a deadlock).
+
+**Non-standard API**:
 
-This function is asynchronous because the ES module resolver in Node.js is
-allowed to be asynchronous.
+When using the `--experimental-import-meta-resolve` flag, that function accepts
+a second argument:
+
+* `parent` {string|URL} An optional absolute parent module URL to resolve from.
+  **Default:** `import.meta.url`
 
 ## Interoperability with CommonJS
 
@@ -497,8 +526,8 @@ They can instead be loaded with [`module.createRequire()`][] or
 
 Relative resolution can be handled via `new URL('./local', import.meta.url)`.
 
-For a complete `require.resolve` replacement, there is a flagged experimental
-[`import.meta.resolve`][] API.
+For a complete `require.resolve` replacement, there is the
+[import.meta.resolve][] API.
 
 Alternatively `module.createRequire()` can be used.
 
@@ -509,8 +538,8 @@ if this behavior is desired.
 
 #### No `require.extensions`
 
-`require.extensions` is not used by `import`. The expectation is that loader
-hooks can provide this workflow in the future.
+`require.extensions` is not used by `import`. Module customization hooks can
+provide a replacement.
 
 #### No `require.cache`
 
@@ -529,7 +558,7 @@ JSON files can be referenced by `import`:
 import packageConfig from './package.json' assert { type: 'json' };
 ```
 
-The `assert { type: 'json' }` syntax is mandatory; see [Import Assertions][].
+The `assert { type: 'json' }` syntax is mandatory; see [Import Attributes][].
 
 The imported JSON only exposes a `default` export. There is no support for named
 exports. A cache entry is created in the CommonJS cache to avoid duplication.
@@ -678,530 +707,8 @@ of Node.js applications.
 
 ## Loaders
 
-
-
-> Stability: 1 - Experimental
-
-> This API is currently being redesigned and will still change.
-
-
-
-To customize the default module resolution, loader hooks can optionally be
-provided via a `--experimental-loader ./loader-name.mjs` argument to Node.js.
-
-When hooks are used they apply to the entry point and all `import` calls. They
-won't apply to `require` calls; those still follow [CommonJS][] rules.
-
-Loaders follow the pattern of `--require`:
-
-```console
-node \
-  --experimental-loader unpkg \
-  --experimental-loader http-to-https \
-  --experimental-loader cache-buster
-```
-
-These are called in the following sequence: `cache-buster` calls
-`http-to-https` which calls `unpkg`.
-
-### Hooks
-
-Hooks are part of a chain, even if that chain consists of only one custom
-(user-provided) hook and the default hook, which is always present. Hook
-functions nest: each one must always return a plain object, and chaining happens
-as a result of each function calling `next()`, which is a reference
-to the subsequent loader’s hook.
-
-A hook that returns a value lacking a required property triggers an exception.
-A hook that returns without calling `next()` _and_ without returning
-`shortCircuit: true` also triggers an exception. These errors are to help
-prevent unintentional breaks in the chain.
-
-#### `resolve(specifier, context, nextResolve)`
-
-
-
-> The loaders API is being redesigned. This hook may disappear or its
-> signature may change. Do not rely on the API described below.
-
-* `specifier` {string}
-* `context` {Object}
-  * `conditions` {string\[]} Export conditions of the relevant `package.json`
-  * `importAssertions` {Object}
-  * `parentURL` {string|undefined} The module importing this one, or undefined
-    if this is the Node.js entry point
-* `nextResolve` {Function} The subsequent `resolve` hook in the chain, or the
-  Node.js default `resolve` hook after the last user-supplied `resolve` hook
-  * `specifier` {string}
-  * `context` {Object}
-* Returns: {Object}
-  * `format` {string|null|undefined} A hint to the load hook (it might be
-    ignored)
-    `'builtin' | 'commonjs' | 'json' | 'module' | 'wasm'`
-  * `shortCircuit` {undefined|boolean} A signal that this hook intends to
-    terminate the chain of `resolve` hooks. **Default:** `false`
-  * `url` {string} The absolute URL to which this input resolves
-
-The `resolve` hook chain is responsible for resolving file URL for a given
-module specifier and parent URL, and optionally its format (such as `'module'`)
-as a hint to the `load` hook. If a format is specified, the `load` hook is
-ultimately responsible for providing the final `format` value (and it is free to
-ignore the hint provided by `resolve`); if `resolve` provides a `format`, a
-custom `load` hook is required even if only to pass the value to the Node.js
-default `load` hook.
-
-The module specifier is the string in an `import` statement or
-`import()` expression.
-
-The parent URL is the URL of the module that imported this one, or `undefined`
-if this is the main entry point for the application.
-
-The `conditions` property in `context` is an array of conditions for
-[package exports conditions][Conditional Exports] that apply to this resolution
-request. They can be used for looking up conditional mappings elsewhere or to
-modify the list when calling the default resolution logic.
-
-The current [package exports conditions][Conditional Exports] are always in
-the `context.conditions` array passed into the hook. To guarantee _default
-Node.js module specifier resolution behavior_ when calling `defaultResolve`, the
-`context.conditions` array passed to it _must_ include _all_ elements of the
-`context.conditions` array originally passed into the `resolve` hook.
-
-```js
-export async function resolve(specifier, context, nextResolve) {
-  const { parentURL = null } = context;
-
-  if (Math.random() > 0.5) { // Some condition.
-    // For some or all specifiers, do some custom logic for resolving.
-    // Always return an object of the form {url: }.
-    return {
-      shortCircuit: true,
-      url: parentURL ?
-        new URL(specifier, parentURL).href :
-        new URL(specifier).href,
-    };
-  }
-
-  if (Math.random() < 0.5) { // Another condition.
-    // When calling `defaultResolve`, the arguments can be modified. In this
-    // case it's adding another value for matching conditional exports.
-    return nextResolve(specifier, {
-      ...context,
-      conditions: [...context.conditions, 'another-condition'],
-    });
-  }
-
-  // Defer to the next hook in the chain, which would be the
-  // Node.js default resolve if this is the last user-specified loader.
-  return nextResolve(specifier);
-}
-```
-
-#### `load(url, context, nextLoad)`
-
-
-
-> The loaders API is being redesigned. This hook may disappear or its
-> signature may change. Do not rely on the API described below.
-
-> In a previous version of this API, this was split across 3 separate, now
-> deprecated, hooks (`getFormat`, `getSource`, and `transformSource`).
-
-* `url` {string} The URL returned by the `resolve` chain
-* `context` {Object}
-  * `conditions` {string\[]} Export conditions of the relevant `package.json`
-  * `format` {string|null|undefined} The format optionally supplied by the
-    `resolve` hook chain
-  * `importAssertions` {Object}
-* `nextLoad` {Function} The subsequent `load` hook in the chain, or the
-  Node.js default `load` hook after the last user-supplied `load` hook
-  * `specifier` {string}
-  * `context` {Object}
-* Returns: {Object}
-  * `format` {string}
-  * `shortCircuit` {undefined|boolean} A signal that this hook intends to
-    terminate the chain of `resolve` hooks. **Default:** `false`
-  * `source` {string|ArrayBuffer|TypedArray} The source for Node.js to evaluate
-
-The `load` hook provides a way to define a custom method of determining how
-a URL should be interpreted, retrieved, and parsed. It is also in charge of
-validating the import assertion.
-
-The final value of `format` must be one of the following:
-
-| `format`     | Description                    | Acceptable types for `source` returned by `load`      |
-| ------------ | ------------------------------ | ----------------------------------------------------- |
-| `'builtin'`  | Load a Node.js builtin module  | Not applicable                                        |
-| `'commonjs'` | Load a Node.js CommonJS module | Not applicable                                        |
-| `'json'`     | Load a JSON file               | { [`string`][], [`ArrayBuffer`][], [`TypedArray`][] } |
-| `'module'`   | Load an ES module              | { [`string`][], [`ArrayBuffer`][], [`TypedArray`][] } |
-| `'wasm'`     | Load a WebAssembly module      | { [`ArrayBuffer`][], [`TypedArray`][] }               |
-
-The value of `source` is ignored for type `'builtin'` because currently it is
-not possible to replace the value of a Node.js builtin (core) module. The value
-of `source` is ignored for type `'commonjs'` because the CommonJS module loader
-does not provide a mechanism for the ES module loader to override the
-[CommonJS module return value](#commonjs-namespaces). This limitation might be
-overcome in the future.
-
-> **Caveat**: The ESM `load` hook and namespaced exports from CommonJS modules
-> are incompatible. Attempting to use them together will result in an empty
-> object from the import. This may be addressed in the future.
-
-> These types all correspond to classes defined in ECMAScript.
-
-* The specific [`ArrayBuffer`][] object is a [`SharedArrayBuffer`][].
-* The specific [`TypedArray`][] object is a [`Uint8Array`][].
-
-If the source value of a text-based format (i.e., `'json'`, `'module'`)
-is not a string, it is converted to a string using [`util.TextDecoder`][].
-
-The `load` hook provides a way to define a custom method for retrieving the
-source code of an ES module specifier. This would allow a loader to potentially
-avoid reading files from disk. It could also be used to map an unrecognized
-format to a supported one, for example `yaml` to `module`.
-
-```js
-export async function load(url, context, nextLoad) {
-  const { format } = context;
-
-  if (Math.random() > 0.5) { // Some condition
-    /*
-      For some or all URLs, do some custom logic for retrieving the source.
-      Always return an object of the form {
-        format: ,
-        source: ,
-      }.
-    */
-    return {
-      format,
-      shortCircuit: true,
-      source: '...',
-    };
-  }
-
-  // Defer to the next hook in the chain.
-  return nextLoad(url);
-}
-```
-
-In a more advanced scenario, this can also be used to transform an unsupported
-source to a supported one (see [Examples](#examples) below).
-
-#### `globalPreload()`
-
-
-
-> The loaders API is being redesigned. This hook may disappear or its
-> signature may change. Do not rely on the API described below.
-
-> In a previous version of this API, this hook was named
-> `getGlobalPreloadCode`.
-
-* `context` {Object} Information to assist the preload code
-  * `port` {MessagePort}
-* Returns: {string} Code to run before application startup
-
-Sometimes it might be necessary to run some code inside of the same global
-scope that the application runs in. This hook allows the return of a string
-that is run as a sloppy-mode script on startup.
-
-Similar to how CommonJS wrappers work, the code runs in an implicit function
-scope. The only argument is a `require`-like function that can be used to load
-builtins like "fs": `getBuiltin(request: string)`.
-
-If the code needs more advanced `require` features, it has to construct
-its own `require` using  `module.createRequire()`.
-
-```js
-export function globalPreload(context) {
-  return `\
-globalThis.someInjectedProperty = 42;
-console.log('I just set some globals!');
-
-const { createRequire } = getBuiltin('module');
-const { cwd } = getBuiltin('process');
-
-const require = createRequire(cwd() + '/');
-// [...]
-`;
-}
-```
-
-In order to allow communication between the application and the loader, another
-argument is provided to the preload code: `port`. This is available as a
-parameter to the loader hook and inside of the source text returned by the hook.
-Some care must be taken in order to properly call [`port.ref()`][] and
-[`port.unref()`][] to prevent a process from being in a state where it won't
-close normally.
-
-```js
-/**
- * This example has the application context send a message to the loader
- * and sends the message back to the application context
- */
-export function globalPreload({ port }) {
-  port.onmessage = (evt) => {
-    port.postMessage(evt.data);
-  };
-  return `\
-    port.postMessage('console.log("I went to the Loader and back");');
-    port.onmessage = (evt) => {
-      eval(evt.data);
-    };
-  `;
-}
-```
-
-### Examples
-
-The various loader hooks can be used together to accomplish wide-ranging
-customizations of the Node.js code loading and evaluation behaviors.
-
-#### HTTPS loader
-
-In current Node.js, specifiers starting with `https://` are experimental (see
-[HTTPS and HTTP imports][]).
-
-The loader below registers hooks to enable rudimentary support for such
-specifiers. While this may seem like a significant improvement to Node.js core
-functionality, there are substantial downsides to actually using this loader:
-performance is much slower than loading files from disk, there is no caching,
-and there is no security.
-
-```js
-// https-loader.mjs
-import { get } from 'node:https';
-
-export function load(url, context, nextLoad) {
-  // For JavaScript to be loaded over the network, we need to fetch and
-  // return it.
-  if (url.startsWith('https://')) {
-    return new Promise((resolve, reject) => {
-      get(url, (res) => {
-        let data = '';
-        res.setEncoding('utf8');
-        res.on('data', (chunk) => data += chunk);
-        res.on('end', () => resolve({
-          // This example assumes all network-provided JavaScript is ES module
-          // code.
-          format: 'module',
-          shortCircuit: true,
-          source: data,
-        }));
-      }).on('error', (err) => reject(err));
-    });
-  }
-
-  // Let Node.js handle all other URLs.
-  return nextLoad(url);
-}
-```
-
-```js
-// main.mjs
-import { VERSION } from 'https://coffeescript.org/browser-compiler-modern/coffeescript.js';
-
-console.log(VERSION);
-```
-
-With the preceding loader, running
-`node --experimental-loader ./https-loader.mjs ./main.mjs`
-prints the current version of CoffeeScript per the module at the URL in
-`main.mjs`.
-
-#### Transpiler loader
-
-Sources that are in formats Node.js doesn't understand can be converted into
-JavaScript using the [`load` hook][load hook].
-
-This is less performant than transpiling source files before running
-Node.js; a transpiler loader should only be used for development and testing
-purposes.
-
-```js
-// coffeescript-loader.mjs
-import { readFile } from 'node:fs/promises';
-import { dirname, extname, resolve as resolvePath } from 'node:path';
-import { cwd } from 'node:process';
-import { fileURLToPath, pathToFileURL } from 'node:url';
-import CoffeeScript from 'coffeescript';
-
-const baseURL = pathToFileURL(`${cwd()}/`).href;
-
-export async function load(url, context, nextLoad) {
-  if (extensionsRegex.test(url)) {
-    // Now that we patched resolve to let CoffeeScript URLs through, we need to
-    // tell Node.js what format such URLs should be interpreted as. Because
-    // CoffeeScript transpiles into JavaScript, it should be one of the two
-    // JavaScript formats: 'commonjs' or 'module'.
-
-    // CoffeeScript files can be either CommonJS or ES modules, so we want any
-    // CoffeeScript file to be treated by Node.js the same as a .js file at the
-    // same location. To determine how Node.js would interpret an arbitrary .js
-    // file, search up the file system for the nearest parent package.json file
-    // and read its "type" field.
-    const format = await getPackageType(url);
-    // When a hook returns a format of 'commonjs', `source` is ignored.
-    // To handle CommonJS files, a handler needs to be registered with
-    // `require.extensions` in order to process the files with the CommonJS
-    // loader. Avoiding the need for a separate CommonJS handler is a future
-    // enhancement planned for ES module loaders.
-    if (format === 'commonjs') {
-      return {
-        format,
-        shortCircuit: true,
-      };
-    }
-
-    const { source: rawSource } = await nextLoad(url, { ...context, format });
-    // This hook converts CoffeeScript source code into JavaScript source code
-    // for all imported CoffeeScript files.
-    const transformedSource = coffeeCompile(rawSource.toString(), url);
-
-    return {
-      format,
-      shortCircuit: true,
-      source: transformedSource,
-    };
-  }
-
-  // Let Node.js handle all other URLs.
-  return nextLoad(url);
-}
-
-async function getPackageType(url) {
-  // `url` is only a file path during the first iteration when passed the
-  // resolved url from the load() hook
-  // an actual file path from load() will contain a file extension as it's
-  // required by the spec
-  // this simple truthy check for whether `url` contains a file extension will
-  // work for most projects but does not cover some edge-cases (such as
-  // extensionless files or a url ending in a trailing space)
-  const isFilePath = !!extname(url);
-  // If it is a file path, get the directory it's in
-  const dir = isFilePath ?
-    dirname(fileURLToPath(url)) :
-    url;
-  // Compose a file path to a package.json in the same directory,
-  // which may or may not exist
-  const packagePath = resolvePath(dir, 'package.json');
-  // Try to read the possibly nonexistent package.json
-  const type = await readFile(packagePath, { encoding: 'utf8' })
-    .then((filestring) => JSON.parse(filestring).type)
-    .catch((err) => {
-      if (err?.code !== 'ENOENT') console.error(err);
-    });
-  // Ff package.json existed and contained a `type` field with a value, voila
-  if (type) return type;
-  // Otherwise, (if not at the root) continue checking the next directory up
-  // If at the root, stop and return false
-  return dir.length > 1 && getPackageType(resolvePath(dir, '..'));
-}
-```
-
-```coffee
-# main.coffee
-import { scream } from './scream.coffee'
-console.log scream 'hello, world'
-
-import { version } from 'node:process'
-console.log "Brought to you by Node.js version #{version}"
-```
-
-```coffee
-# scream.coffee
-export scream = (str) -> str.toUpperCase()
-```
-
-With the preceding loader, running
-`node --experimental-loader ./coffeescript-loader.mjs main.coffee`
-causes `main.coffee` to be turned into JavaScript after its source code is
-loaded from disk but before Node.js executes it; and so on for any `.coffee`,
-`.litcoffee` or `.coffee.md` files referenced via `import` statements of any
-loaded file.
-
-#### "import map" loader
-
-The previous two loaders defined `load` hooks. This is an example of a loader
-that does its work via the `resolve` hook. This loader reads an
-`import-map.json` file that specifies which specifiers to override to another
-URL (this is a very simplistic implemenation of a small subset of the
-"import maps" specification).
-
-```js
-// import-map-loader.js
-import fs from 'node:fs/promises';
-
-const { imports } = JSON.parse(await fs.readFile('import-map.json'));
-
-export async function resolve(specifier, context, nextResolve) {
-  if (Object.hasOwn(imports, specifier)) {
-    return nextResolve(imports[specifier], context);
-  }
-
-  return nextResolve(specifier, context);
-}
-```
-
-Let's assume we have these files:
-
-```js
-// main.js
-import 'a-module';
-```
-
-```json
-// import-map.json
-{
-  "imports": {
-    "a-module": "./some-module.js"
-  }
-}
-```
-
-```js
-// some-module.js
-console.log('some module!');
-```
-
-If you run `node --experimental-loader ./import-map-loader.js main.js`
-the output will be `some module!`.
+The former Loaders documentation is now at
+[Modules: Customization hooks][Module customization hooks].
 
 ## Resolution and loading algorithm
 
@@ -1512,8 +1019,12 @@ _isImports_, _conditions_)
 > 5. Let _packageURL_ be the result of **LOOKUP\_PACKAGE\_SCOPE**(_url_).
 > 6. Let _pjson_ be the result of **READ\_PACKAGE\_JSON**(_packageURL_).
 > 7. If _pjson?.type_ exists and is _"module"_, then
->    1. If _url_ ends in _".js"_, then
->       1. Return _"module"_.
+>    1. If _url_ ends in _".js"_ or has no file extension, then
+>       1. If `--experimental-wasm-modules` is enabled and the file at _url_
+>          contains the header for a WebAssembly module, then
+>          1. Return _"wasm"_.
+>       2. Otherwise,
+>          1. Return _"module"_.
 >    2. Return **undefined**.
 > 8. Otherwise,
 >    1. Return **undefined**.
@@ -1544,8 +1055,8 @@ _isImports_, _conditions_)
 > Stability: 1 - Experimental
 
 > Do not rely on this flag. We plan to remove it once the
-> [Loaders API][] has advanced to the point that equivalent functionality can
-> be achieved via custom loaders.
+> [Module customization hooks][] have advanced to the point that equivalent
+> functionality can be achieved via custom hooks.
 
 The current specifier resolution does not support all default behavior of
 the CommonJS loader. One of the behavior differences is automatic resolution
@@ -1572,43 +1083,34 @@ success!
 [6.1.7 Array Index]: https://tc39.es/ecma262/#integer-index
 [Addons]: addons.md
 [CommonJS]: modules.md
-[Conditional exports]: packages.md#conditional-exports
 [Core modules]: modules.md#core-modules
 [Determining module system]: packages.md#determining-module-system
 [Dynamic `import()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import
 [ES Module Integration Proposal for WebAssembly]: https://github.com/webassembly/esm-integration
-[HTTPS and HTTP imports]: #https-and-http-imports
-[Import Assertions]: #import-assertions
-[Import Assertions proposal]: https://github.com/tc39/proposal-import-assertions
+[Import Attributes]: #import-attributes
+[Import Attributes proposal]: https://github.com/tc39/proposal-import-attributes
 [JSON modules]: #json-modules
-[Loaders API]: #loaders
+[Module customization hooks]: module.md#customization-hooks
 [Node.js Module Resolution And Loading Algorithm]: #resolution-algorithm-specification
 [Terminology]: #terminology
 [URL]: https://url.spec.whatwg.org/
 [`"exports"`]: packages.md#exports
 [`"type"`]: packages.md#type
+[`--experimental-default-type`]: cli.md#--experimental-default-typetype
 [`--input-type`]: cli.md#--input-typetype
-[`ArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer
-[`SharedArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer
-[`TypedArray`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray
-[`Uint8Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array
 [`data:` URLs]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
 [`export`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export
 [`import()`]: #import-expressions
-[`import.meta.resolve`]: #importmetaresolvespecifier-parent
+[`import.meta.resolve`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import.meta/resolve
 [`import.meta.url`]: #importmetaurl
 [`import`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
 [`module.createRequire()`]: module.md#modulecreaterequirefilename
 [`module.syncBuiltinESMExports()`]: module.md#modulesyncbuiltinesmexports
 [`package.json`]: packages.md#nodejs-packagejson-field-definitions
-[`port.ref()`]: https://nodejs.org/dist/latest-v17.x/docs/api/worker_threads.html#portref
-[`port.unref()`]: https://nodejs.org/dist/latest-v17.x/docs/api/worker_threads.html#portunref
 [`process.dlopen`]: process.md#processdlopenmodule-filename-flags
-[`string`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String
-[`util.TextDecoder`]: util.md#class-utiltextdecoder
 [cjs-module-lexer]: https://github.com/nodejs/cjs-module-lexer/tree/1.2.2
-[custom https loader]: #https-loader
-[load hook]: #loadurl-context-nextload
+[custom https loader]: module.md#import-from-https
+[import.meta.resolve]: #importmetaresolvespecifier
 [percent-encoded]: url.md#percent-encoding-in-urls
 [special scheme]: https://url.spec.whatwg.org/#special-scheme
 [status code]: process.md#exit-codes
diff --git a/doc/api/fs.md b/doc/api/fs.md
index 893eb7befb7fe5..bc2d6b64ca2e51 100644
--- a/doc/api/fs.md
+++ b/doc/api/fs.md
@@ -444,7 +444,7 @@ Reads data from the file and stores that in the given buffer.
 If the file is not modified concurrently, the end-of-file is reached when the
 number of bytes read is zero.
 
-#### `filehandle.readableWebStream(options)`
+#### `filehandle.readableWebStream([options])`
 
 
 
-* `prefix` {string}
+* `prefix` {string|Buffer|URL}
 * `options` {string|Object}
   * `encoding` {string} **Default:** `'utf8'`
 * Returns: {Promise}  Fulfills with a string containing the file system path
@@ -2319,7 +2323,8 @@ changes:
   * `errorOnExist` {boolean} when `force` is `false`, and the destination
     exists, throw an error. **Default:** `false`.
   * `filter` {Function} Function to filter copied files/directories. Return
-    `true` to copy the item, `false` to ignore it. Can also return a `Promise`
+    `true` to copy the item, `false` to ignore it. When ignoring a directory,
+    all of its contents will be skipped as well. Can also return a `Promise`
     that resolves to `true` or `false` **Default:** `undefined`.
     * `src` {string} source path to copy.
     * `dest` {string} destination path to copy to.
@@ -3225,6 +3230,9 @@ See the POSIX mkdir(2) documentation for more details.
 
 
-* `prefix` {string}
+* `prefix` {string|Buffer|URL}
 * `options` {string|Object}
   * `encoding` {string} **Default:** `'utf8'`
 * `callback` {Function}
@@ -5184,7 +5192,8 @@ changes:
   * `errorOnExist` {boolean} when `force` is `false`, and the destination
     exists, throw an error. **Default:** `false`.
   * `filter` {Function} Function to filter copied files/directories. Return
-    `true` to copy the item, `false` to ignore it. **Default:** `undefined`
+    `true` to copy the item, `false` to ignore it. When ignoring a directory,
+    all of its contents will be skipped as well. **Default:** `undefined`
     * `src` {string} source path to copy.
     * `dest` {string} destination path to copy to.
     * Returns: {boolean}
@@ -5478,6 +5487,9 @@ See the POSIX mkdir(2) documentation for more details.
 
 
-* `prefix` {string}
+* `prefix` {string|Buffer|URL}
 * `options` {string|Object}
   * `encoding` {string} **Default:** `'utf8'`
 * Returns: {string}
diff --git a/doc/api/http.md b/doc/api/http.md
index 10909e8ebaa913..162a37384f371e 100644
--- a/doc/api/http.md
+++ b/doc/api/http.md
@@ -187,7 +187,14 @@ of these values set to their respective defaults.
 
 To configure any of them, a custom [`http.Agent`][] instance must be created.
 
-```js
+```mjs
+import { Agent, request } from 'node:http';
+const keepAliveAgent = new Agent({ keepAlive: true });
+options.agent = keepAliveAgent;
+request(options, onResponseCallback);
+```
+
+```cjs
 const http = require('node:http');
 const keepAliveAgent = new http.Agent({ keepAlive: true });
 options.agent = keepAliveAgent;
@@ -472,7 +479,62 @@ type other than {net.Socket}.
 
 A client and server pair demonstrating how to listen for the `'connect'` event:
 
-```js
+```mjs
+import { createServer, request } from 'node:http';
+import { connect } from 'node:net';
+import { URL } from 'node:url';
+
+// Create an HTTP tunneling proxy
+const proxy = createServer((req, res) => {
+  res.writeHead(200, { 'Content-Type': 'text/plain' });
+  res.end('okay');
+});
+proxy.on('connect', (req, clientSocket, head) => {
+  // Connect to an origin server
+  const { port, hostname } = new URL(`http://${req.url}`);
+  const serverSocket = connect(port || 80, hostname, () => {
+    clientSocket.write('HTTP/1.1 200 Connection Established\r\n' +
+                    'Proxy-agent: Node.js-Proxy\r\n' +
+                    '\r\n');
+    serverSocket.write(head);
+    serverSocket.pipe(clientSocket);
+    clientSocket.pipe(serverSocket);
+  });
+});
+
+// Now that proxy is running
+proxy.listen(1337, '127.0.0.1', () => {
+
+  // Make a request to a tunneling proxy
+  const options = {
+    port: 1337,
+    host: '127.0.0.1',
+    method: 'CONNECT',
+    path: 'www.google.com:80',
+  };
+
+  const req = request(options);
+  req.end();
+
+  req.on('connect', (res, socket, head) => {
+    console.log('got connected!');
+
+    // Make a request over an HTTP tunnel
+    socket.write('GET / HTTP/1.1\r\n' +
+                 'Host: www.google.com:80\r\n' +
+                 'Connection: close\r\n' +
+                 '\r\n');
+    socket.on('data', (chunk) => {
+      console.log(chunk.toString());
+    });
+    socket.on('end', () => {
+      proxy.close();
+    });
+  });
+});
+```
+
+```cjs
 const http = require('node:http');
 const net = require('node:net');
 const { URL } = require('node:url');
@@ -568,7 +630,25 @@ Upgrade). The listeners of this event will receive an object containing the
 HTTP version, status code, status message, key-value headers object,
 and array with the raw header names followed by their respective values.
 
-```js
+```mjs
+import { request } from 'node:http';
+
+const options = {
+  host: '127.0.0.1',
+  port: 8080,
+  path: '/length_request',
+};
+
+// Make a request
+const req = request(options);
+req.end();
+
+req.on('information', (info) => {
+  console.log(`Got information prior to main response: ${info.statusCode}`);
+});
+```
+
+```cjs
 const http = require('node:http');
 
 const options = {
@@ -646,7 +726,49 @@ type other than {net.Socket}.
 
 A client server pair demonstrating how to listen for the `'upgrade'` event.
 
-```js
+```mjs
+import http from 'node:http';
+import process from 'node:process';
+
+// Create an HTTP server
+const server = http.createServer((req, res) => {
+  res.writeHead(200, { 'Content-Type': 'text/plain' });
+  res.end('okay');
+});
+server.on('upgrade', (req, socket, head) => {
+  socket.write('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
+               'Upgrade: WebSocket\r\n' +
+               'Connection: Upgrade\r\n' +
+               '\r\n');
+
+  socket.pipe(socket); // echo back
+});
+
+// Now that server is running
+server.listen(1337, '127.0.0.1', () => {
+
+  // make a request
+  const options = {
+    port: 1337,
+    host: '127.0.0.1',
+    headers: {
+      'Connection': 'Upgrade',
+      'Upgrade': 'websocket',
+    },
+  };
+
+  const req = http.request(options);
+  req.end();
+
+  req.on('upgrade', (res, socket, upgradeHead) => {
+    console.log('got upgraded!');
+    socket.end();
+    process.exit(0);
+  });
+});
+```
+
+```cjs
 const http = require('node:http');
 
 // Create an HTTP server
@@ -1017,7 +1139,28 @@ When sending request through a keep-alive enabled agent, the underlying socket
 might be reused. But if server closes connection at unfortunate time, client
 may run into a 'ECONNRESET' error.
 
-```js
+```mjs
+import http from 'node:http';
+
+// Server has a 5 seconds keep-alive timeout by default
+http
+  .createServer((req, res) => {
+    res.write('hello\n');
+    res.end();
+  })
+  .listen(3000);
+
+setInterval(() => {
+  // Adapting a keep-alive agent
+  http.get('http://localhost:3000', { agent }, (res) => {
+    res.on('data', (data) => {
+      // Do nothing
+    });
+  });
+}, 5000); // Sending request on 5s interval so it's easy to hit idle timeout
+```
+
+```cjs
 const http = require('node:http');
 
 // Server has a 5 seconds keep-alive timeout by default
@@ -1041,7 +1184,27 @@ setInterval(() => {
 By marking a request whether it reused socket or not, we can do
 automatic error retry base on it.
 
-```js
+```mjs
+import http from 'node:http';
+const agent = new http.Agent({ keepAlive: true });
+
+function retriableRequest() {
+  const req = http
+    .get('http://localhost:3000', { agent }, (res) => {
+      // ...
+    })
+    .on('error', (err) => {
+      // Check if retry is needed
+      if (req.reusedSocket && err.code === 'ECONNRESET') {
+        retriableRequest();
+      }
+    });
+}
+
+retriableRequest();
+```
+
+```cjs
 const http = require('node:http');
 const agent = new http.Agent({ keepAlive: true });
 
@@ -1151,7 +1314,22 @@ Reference to the underlying socket. Usually users will not want to access
 this property. In particular, the socket will not emit `'readable'` events
 because of how the protocol parser attaches to the socket.
 
-```js
+```mjs
+import http from 'node:http';
+const options = {
+  host: 'www.google.com',
+};
+const req = http.get(options);
+req.end();
+req.once('response', (res) => {
+  const ip = req.socket.localAddress;
+  const port = req.socket.localPort;
+  console.log(`Your IP address is ${ip} and your source port is ${port}.`);
+  // Consume response object
+});
+```
+
+```cjs
 const http = require('node:http');
 const options = {
   host: 'www.google.com',
@@ -1324,7 +1502,19 @@ immediately destroyed.
 
 `socket` is the [`net.Socket`][] object that the error originated from.
 
-```js
+```mjs
+import http from 'node:http';
+
+const server = http.createServer((req, res) => {
+  res.end();
+});
+server.on('clientError', (err, socket) => {
+  socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
+});
+server.listen(8000);
+```
+
+```cjs
 const http = require('node:http');
 
 const server = http.createServer((req, res) => {
@@ -2008,7 +2198,16 @@ this property. In particular, the socket will not emit `'readable'` events
 because of how the protocol parser attaches to the socket. After
 `response.end()`, the property is nulled.
 
-```js
+```mjs
+import http from 'node:http';
+const server = http.createServer((req, res) => {
+  const ip = res.socket.remoteAddress;
+  const port = res.socket.remotePort;
+  res.end(`Your IP address is ${ip} and your source port is ${port}.`);
+}).listen(3000);
+```
+
+```cjs
 const http = require('node:http');
 const server = http.createServer((req, res) => {
   const ip = res.socket.remoteAddress;
@@ -3248,6 +3447,20 @@ Returns a new instance of [`http.Server`][].
 The `requestListener` is a function which is automatically
 added to the [`'request'`][] event.
 
+```mjs
+import http from 'node:http';
+
+// Create a local server to receive data from
+const server = http.createServer((req, res) => {
+  res.writeHead(200, { 'Content-Type': 'application/json' });
+  res.end(JSON.stringify({
+    data: 'Hello World!',
+  }));
+});
+
+server.listen(8000);
+```
+
 ```cjs
 const http = require('node:http');
 
@@ -3262,6 +3475,23 @@ const server = http.createServer((req, res) => {
 server.listen(8000);
 ```
 
+```mjs
+import http from 'node:http';
+
+// Create a local server to receive data from
+const server = http.createServer();
+
+// Listen to the request event
+server.on('request', (request, res) => {
+  res.writeHead(200, { 'Content-Type': 'application/json' });
+  res.end(JSON.stringify({
+    data: 'Hello World!',
+  }));
+});
+
+server.listen(8000);
+```
+
 ```cjs
 const http = require('node:http');
 
@@ -3506,7 +3736,47 @@ the [`'response'`][] event.
 class. The `ClientRequest` instance is a writable stream. If one needs to
 upload a file with a POST request, then write to the `ClientRequest` object.
 
-```js
+```mjs
+import http from 'node:http';
+import { Buffer } from 'node:buffer';
+
+const postData = JSON.stringify({
+  'msg': 'Hello World!',
+});
+
+const options = {
+  hostname: 'www.google.com',
+  port: 80,
+  path: '/upload',
+  method: 'POST',
+  headers: {
+    'Content-Type': 'application/json',
+    'Content-Length': Buffer.byteLength(postData),
+  },
+};
+
+const req = http.request(options, (res) => {
+  console.log(`STATUS: ${res.statusCode}`);
+  console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
+  res.setEncoding('utf8');
+  res.on('data', (chunk) => {
+    console.log(`BODY: ${chunk}`);
+  });
+  res.on('end', () => {
+    console.log('No more data in response.');
+  });
+});
+
+req.on('error', (e) => {
+  console.error(`problem with request: ${e.message}`);
+});
+
+// Write data to request body
+req.write(postData);
+req.end();
+```
+
+```cjs
 const http = require('node:http');
 
 const postData = JSON.stringify({
@@ -3712,7 +3982,19 @@ Examples:
 
 Example:
 
-```js
+```mjs
+import { validateHeaderName } from 'node:http';
+
+try {
+  validateHeaderName('');
+} catch (err) {
+  console.error(err instanceof TypeError); // --> true
+  console.error(err.code); // --> 'ERR_INVALID_HTTP_TOKEN'
+  console.error(err.message); // --> 'Header name must be a valid HTTP token [""]'
+}
+```
+
+```cjs
 const { validateHeaderName } = require('node:http');
 
 try {
@@ -3746,7 +4028,27 @@ or response. The HTTP module will automatically validate such headers.
 
 Examples:
 
-```js
+```mjs
+import { validateHeaderValue } from 'node:http';
+
+try {
+  validateHeaderValue('x-my-header', undefined);
+} catch (err) {
+  console.error(err instanceof TypeError); // --> true
+  console.error(err.code === 'ERR_HTTP_INVALID_HEADER_VALUE'); // --> true
+  console.error(err.message); // --> 'Invalid value "undefined" for header "x-my-header"'
+}
+
+try {
+  validateHeaderValue('x-my-header', 'oʊmɪɡə');
+} catch (err) {
+  console.error(err instanceof TypeError); // --> true
+  console.error(err.code === 'ERR_INVALID_CHAR'); // --> true
+  console.error(err.message); // --> 'Invalid character in header content ["x-my-header"]'
+}
+```
+
+```cjs
 const { validateHeaderValue } = require('node:http');
 
 try {
diff --git a/doc/api/module.md b/doc/api/module.md
index cb0b27cb612be7..b5e9e26f529e9c 100644
--- a/doc/api/module.md
+++ b/doc/api/module.md
@@ -78,6 +78,33 @@ isBuiltin('fs'); // true
 isBuiltin('wss'); // false
 ```
 
+### `module.register(specifier[, parentURL][, options])`
+
+
+
+> Stability: 1.1 - Active development
+
+* `specifier` {string|URL} Customization hooks to be registered; this should be
+  the same string that would be passed to `import()`, except that if it is
+  relative, it is resolved relative to `parentURL`.
+* `parentURL` {string|URL} If you want to resolve `specifier` relative to a base
+  URL, such as `import.meta.url`, you can pass that URL here. **Default:**
+  `'data:'`
+* `options` {Object}
+  * `data` {any} Any arbitrary, cloneable JavaScript value to pass into the
+    [`initialize`][] hook.
+  * `transferList` {Object\[]} [transferrable objects][] to be passed into the
+    `initialize` hook.
+
+Register a module that exports [hooks][] that customize Node.js module
+resolution and loading behavior. See [Customization hooks][].
+
 ### `module.syncBuiltinESMExports()`
 
 
+
+> Stability: 1.1 - Active development
+
+
+
+
+
+### Enabling
+
+Module resolution and loading can be customized by registering a file which
+exports a set of hooks. This can be done using the [`register`][] method
+from `node:module`, which you can run before your application code by
+using the `--import` flag:
+
+```bash
+node --import ./register-hooks.js ./my-app.js
+```
+
+```mjs
+// register-hooks.js
+import { register } from 'node:module';
+
+register('./hooks.mjs', import.meta.url);
+```
+
+```cjs
+// register-hooks.js
+const { register } = require('node:module');
+const { pathToFileURL } = require('node:url');
+
+register('./hooks.mjs', pathToFileURL(__filename));
+```
+
+The file passed to `--import` can also be an export from a dependency:
+
+```bash
+node --import some-package/register ./my-app.js
+```
+
+Where `some-package` has an [`"exports"`][] field defining the `/register`
+export to map to a file that calls `register()`, like the following `register-hooks.js`
+example.
+
+Using `--import` ensures that the hooks are registered before any application
+files are imported, including the entry point of the application. Alternatively,
+`register` can be called from the entry point, but dynamic `import()` must be
+used for any code that should be run after the hooks are registered:
+
+```mjs
+import { register } from 'node:module';
+
+register('http-to-https', import.meta.url);
+
+// Because this is a dynamic `import()`, the `http-to-https` hooks will run
+// to handle `./my-app.js` and any other files it imports or requires.
+await import('./my-app.js');
+```
+
+```cjs
+const { register } = require('node:module');
+const { pathToFileURL } = require('node:url');
+
+register('http-to-https', pathToFileURL(__filename));
+
+// Because this is a dynamic `import()`, the `http-to-https` hooks will run
+// to handle `./my-app.js` and any other files it imports or requires.
+import('./my-app.js');
+```
+
+In this example, we are registering the `http-to-https` hooks, but they will
+only be available for subsequently imported modules—in this case, `my-app.js`
+and anything it references via `import` (and optionally `require`). If the
+`import('./my-app.js')` had instead been a static `import './my-app.js'`, the
+app would have _already_ been loaded **before** the `http-to-https` hooks were
+registered. This due to the ES modules specification, where static imports are
+evaluated from the leaves of the tree first, then back to the trunk. There can
+be static imports _within_ `my-app.js`, which will not be evaluated until
+`my-app.js` is dynamically imported.
+
+`my-app.js` can also be CommonJS. Customization hooks will run for any
+modules that it references via `import` (and optionally `require`).
+
+Finally, if all you want to do is register hooks before your app runs and you
+don't want to create a separate file for that purpose, you can pass a `data:`
+URL to `--import`:
+
+```bash
+node --import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; register("http-to-https", pathToFileURL("./"));' ./my-app.js
+```
+
+### Chaining
+
+It's possible to call `register` more than once:
+
+```mjs
+// entrypoint.mjs
+import { register } from 'node:module';
+
+register('./first.mjs', import.meta.url);
+register('./second.mjs', import.meta.url);
+await import('./my-app.mjs');
+```
+
+```cjs
+// entrypoint.cjs
+const { register } = require('node:module');
+const { pathToFileURL } = require('node:url');
+
+const parentURL = pathToFileURL(__filename);
+register('./first.mjs', parentURL);
+register('./second.mjs', parentURL);
+import('./my-app.mjs');
+```
+
+In this example, the registered hooks will form chains. If both `first.mjs` and
+`second.mjs` define a `resolve` hook, both will be called, in the order they
+were registered. The same applies to all the other hooks.
+
+The registered hooks also affect `register` itself. In this example,
+`second.mjs` will be resolved and loaded per the hooks registered by
+`first.mjs`. This allows for things like writing hooks in non-JavaScript
+languages, so long as an earlier registered loader is one that transpiles into
+JavaScript.
+
+The `register` method cannot be called from within the module that defines the
+hooks.
+
+### Communication with module customization hooks
+
+Module customization hooks run on a dedicated thread, separate from the main
+thread that runs application code. This means mutating global variables won't
+affect the other thread(s), and message channels must be used to communicate
+between the threads.
+
+The `register` method can be used to pass data to an [`initialize`][] hook. The
+data passed to the hook may include transferrable objects like ports.
+
+```mjs
+import { register } from 'node:module';
+import { MessageChannel } from 'node:worker_threads';
+
+// This example demonstrates how a message channel can be used to
+// communicate with the hooks, by sending `port2` to the hooks.
+const { port1, port2 } = new MessageChannel();
+
+port1.on('message', (msg) => {
+  console.log(msg);
+});
+
+register('./my-hooks.mjs', {
+  parentURL: import.meta.url,
+  data: { number: 1, port: port2 },
+  transferList: [port2],
+});
+```
+
+```cjs
+const { register } = require('node:module');
+const { pathToFileURL } = require('node:url');
+const { MessageChannel } = require('node:worker_threads');
+
+// This example showcases how a message channel can be used to
+// communicate with the hooks, by sending `port2` to the hooks.
+const { port1, port2 } = new MessageChannel();
+
+port1.on('message', (msg) => {
+  console.log(msg);
+});
+
+register('./my-hooks.mjs', {
+  parentURL: pathToFileURL(__filename),
+  data: { number: 1, port: port2 },
+  transferList: [port2],
+});
+```
+
+### Hooks
+
+The [`register`][] method can be used to register a module that exports a set of
+hooks. The hooks are functions that are called by Node.js to customize the
+module resolution and loading process. The exported functions must have specific
+names and signatures, and they must be exported as named exports.
+
+```mjs
+export async function initialize({ number, port }) {
+  // Receives data from `register`.
+}
+
+export async function resolve(specifier, context, nextResolve) {
+  // Take an `import` or `require` specifier and resolve it to a URL.
+}
+
+export async function load(url, context, nextLoad) {
+  // Take a resolved URL and return the source code to be evaluated.
+}
+```
+
+Hooks are part of a chain, even if that chain consists of only one custom
+(user-provided) hook and the default hook, which is always present. Hook
+functions nest: each one must always return a plain object, and chaining happens
+as a result of each function calling `next()`, which is a reference to
+the subsequent loader's hook.
+
+A hook that returns a value lacking a required property triggers an exception. A
+hook that returns without calling `next()` _and_ without returning
+`shortCircuit: true` also triggers an exception. These errors are to help
+prevent unintentional breaks in the chain. Return `shortCircuit: true` from a
+hook to signal that the chain is intentionally ending at your hook.
+
+Hooks are run in a separate thread, isolated from the main thread where
+application code runs. That means it is a different [realm][]. The hooks thread
+may be terminated by the main thread at any time, so do not depend on
+asynchronous operations (like `console.log`) to complete.
+
+#### `initialize()`
+
+
+
+> Stability: 1.1 - Active development
+
+* `data` {any} The data from `register(loader, import.meta.url, { data })`.
+
+The `initialize` hook provides a way to define a custom function that runs in
+the hooks thread when the hooks module is initialized. Initialization happens
+when the hooks module is registered via [`register`][].
+
+This hook can receive data from a [`register`][] invocation, including
+ports and other transferrable objects. The return value of `initialize` can be a
+{Promise}, in which case it will be awaited before the main application thread
+execution resumes.
+
+Module customization code:
+
+```mjs
+// path-to-my-hooks.js
+
+export async function initialize({ number, port }) {
+  port.postMessage(`increment: ${number + 1}`);
+}
+```
+
+Caller code:
+
+```mjs
+import assert from 'node:assert';
+import { register } from 'node:module';
+import { MessageChannel } from 'node:worker_threads';
+
+// This example showcases how a message channel can be used to communicate
+// between the main (application) thread and the hooks running on the hooks
+// thread, by sending `port2` to the `initialize` hook.
+const { port1, port2 } = new MessageChannel();
+
+port1.on('message', (msg) => {
+  assert.strictEqual(msg, 'increment: 2');
+});
+
+register('./path-to-my-hooks.js', {
+  parentURL: import.meta.url,
+  data: { number: 1, port: port2 },
+  transferList: [port2],
+});
+```
+
+```cjs
+const assert = require('node:assert');
+const { register } = require('node:module');
+const { pathToFileURL } = require('node:url');
+const { MessageChannel } = require('node:worker_threads');
+
+// This example showcases how a message channel can be used to communicate
+// between the main (application) thread and the hooks running on the hooks
+// thread, by sending `port2` to the `initialize` hook.
+const { port1, port2 } = new MessageChannel();
+
+port1.on('message', (msg) => {
+  assert.strictEqual(msg, 'increment: 2');
+});
+
+register('./path-to-my-hooks.js', {
+  parentURL: pathToFileURL(__filename),
+  data: { number: 1, port: port2 },
+  transferList: [port2],
+});
+```
+
+#### `resolve(specifier, context, nextResolve)`
+
+
+
+> Stability: 1.2 - Release candidate
+
+* `specifier` {string}
+* `context` {Object}
+  * `conditions` {string\[]} Export conditions of the relevant `package.json`
+  * `importAttributes` {Object} An object whose key-value pairs represent the
+    attributes for the module to import
+  * `parentURL` {string|undefined} The module importing this one, or undefined
+    if this is the Node.js entry point
+* `nextResolve` {Function} The subsequent `resolve` hook in the chain, or the
+  Node.js default `resolve` hook after the last user-supplied `resolve` hook
+  * `specifier` {string}
+  * `context` {Object}
+* Returns: {Object|Promise}
+  * `format` {string|null|undefined} A hint to the load hook (it might be
+    ignored)
+    `'builtin' | 'commonjs' | 'json' | 'module' | 'wasm'`
+  * `importAttributes` {Object|undefined} The import attributes to use when
+    caching the module (optional; if excluded the input will be used)
+  * `shortCircuit` {undefined|boolean} A signal that this hook intends to
+    terminate the chain of `resolve` hooks. **Default:** `false`
+  * `url` {string} The absolute URL to which this input resolves
+
+> **Warning** Despite support for returning promises and async functions, calls
+> to `resolve` may block the main thread which can impact performance.
+
+The `resolve` hook chain is responsible for telling Node.js where to find and
+how to cache a given `import` statement or expression, or `require` call. It can
+optionally return a format (such as `'module'`) as a hint to the `load` hook. If
+a format is specified, the `load` hook is ultimately responsible for providing
+the final `format` value (and it is free to ignore the hint provided by
+`resolve`); if `resolve` provides a `format`, a custom `load` hook is required
+even if only to pass the value to the Node.js default `load` hook.
+
+Import type attributes are part of the cache key for saving loaded modules into
+the internal module cache. The `resolve` hook is responsible for returning an
+`importAttributes` object if the module should be cached with different
+attributes than were present in the source code.
+
+The `conditions` property in `context` is an array of conditions for
+[package exports conditions][Conditional exports] that apply to this resolution
+request. They can be used for looking up conditional mappings elsewhere or to
+modify the list when calling the default resolution logic.
+
+The current [package exports conditions][Conditional exports] are always in
+the `context.conditions` array passed into the hook. To guarantee _default
+Node.js module specifier resolution behavior_ when calling `defaultResolve`, the
+`context.conditions` array passed to it _must_ include _all_ elements of the
+`context.conditions` array originally passed into the `resolve` hook.
+
+```mjs
+export async function resolve(specifier, context, nextResolve) {
+  const { parentURL = null } = context;
+
+  if (Math.random() > 0.5) { // Some condition.
+    // For some or all specifiers, do some custom logic for resolving.
+    // Always return an object of the form {url: }.
+    return {
+      shortCircuit: true,
+      url: parentURL ?
+        new URL(specifier, parentURL).href :
+        new URL(specifier).href,
+    };
+  }
+
+  if (Math.random() < 0.5) { // Another condition.
+    // When calling `defaultResolve`, the arguments can be modified. In this
+    // case it's adding another value for matching conditional exports.
+    return nextResolve(specifier, {
+      ...context,
+      conditions: [...context.conditions, 'another-condition'],
+    });
+  }
+
+  // Defer to the next hook in the chain, which would be the
+  // Node.js default resolve if this is the last user-specified loader.
+  return nextResolve(specifier);
+}
+```
+
+#### `load(url, context, nextLoad)`
+
+
+
+> Stability: 1.2 - Release candidate
+
+* `url` {string} The URL returned by the `resolve` chain
+* `context` {Object}
+  * `conditions` {string\[]} Export conditions of the relevant `package.json`
+  * `format` {string|null|undefined} The format optionally supplied by the
+    `resolve` hook chain
+  * `importAttributes` {Object}
+* `nextLoad` {Function} The subsequent `load` hook in the chain, or the
+  Node.js default `load` hook after the last user-supplied `load` hook
+  * `specifier` {string}
+  * `context` {Object}
+* Returns: {Object}
+  * `format` {string}
+  * `shortCircuit` {undefined|boolean} A signal that this hook intends to
+    terminate the chain of `resolve` hooks. **Default:** `false`
+  * `source` {string|ArrayBuffer|TypedArray} The source for Node.js to evaluate
+
+The `load` hook provides a way to define a custom method of determining how a
+URL should be interpreted, retrieved, and parsed. It is also in charge of
+validating the import assertion.
+
+The final value of `format` must be one of the following:
+
+| `format`     | Description                    | Acceptable types for `source` returned by `load`      |
+| ------------ | ------------------------------ | ----------------------------------------------------- |
+| `'builtin'`  | Load a Node.js builtin module  | Not applicable                                        |
+| `'commonjs'` | Load a Node.js CommonJS module | Not applicable                                        |
+| `'json'`     | Load a JSON file               | { [`string`][], [`ArrayBuffer`][], [`TypedArray`][] } |
+| `'module'`   | Load an ES module              | { [`string`][], [`ArrayBuffer`][], [`TypedArray`][] } |
+| `'wasm'`     | Load a WebAssembly module      | { [`ArrayBuffer`][], [`TypedArray`][] }               |
+
+The value of `source` is ignored for type `'builtin'` because currently it is
+not possible to replace the value of a Node.js builtin (core) module. The value
+of `source` is ignored for type `'commonjs'` because the CommonJS module loader
+does not provide a mechanism for the ES module loader to override the
+[CommonJS module return value](esm.md#commonjs-namespaces). This limitation
+might be overcome in the future.
+
+> **Warning**: The ESM `load` hook and namespaced exports from CommonJS modules
+> are incompatible. Attempting to use them together will result in an empty
+> object from the import. This may be addressed in the future.
+
+> These types all correspond to classes defined in ECMAScript.
+
+* The specific [`ArrayBuffer`][] object is a [`SharedArrayBuffer`][].
+* The specific [`TypedArray`][] object is a [`Uint8Array`][].
+
+If the source value of a text-based format (i.e., `'json'`, `'module'`)
+is not a string, it is converted to a string using [`util.TextDecoder`][].
+
+The `load` hook provides a way to define a custom method for retrieving the
+source code of a resolved URL. This would allow a loader to potentially avoid
+reading files from disk. It could also be used to map an unrecognized format to
+a supported one, for example `yaml` to `module`.
+
+```mjs
+export async function load(url, context, nextLoad) {
+  const { format } = context;
+
+  if (Math.random() > 0.5) { // Some condition
+    /*
+      For some or all URLs, do some custom logic for retrieving the source.
+      Always return an object of the form {
+        format: ,
+        source: ,
+      }.
+    */
+    return {
+      format,
+      shortCircuit: true,
+      source: '...',
+    };
+  }
+
+  // Defer to the next hook in the chain.
+  return nextLoad(url);
+}
+```
+
+In a more advanced scenario, this can also be used to transform an unsupported
+source to a supported one (see [Examples](#examples) below).
+
+#### `globalPreload()`
+
+
+
+> Stability: 1.0 - Early development
+
+> **Warning:** This hook will be removed in a future version. Use
+> [`initialize`][] instead. When a hooks module has an `initialize` export,
+> `globalPreload` will be ignored.
+
+* `context` {Object} Information to assist the preload code
+  * `port` {MessagePort}
+* Returns: {string} Code to run before application startup
+
+Sometimes it might be necessary to run some code inside of the same global
+scope that the application runs in. This hook allows the return of a string
+that is run as a sloppy-mode script on startup.
+
+Similar to how CommonJS wrappers work, the code runs in an implicit function
+scope. The only argument is a `require`-like function that can be used to load
+builtins like "fs": `getBuiltin(request: string)`.
+
+If the code needs more advanced `require` features, it has to construct
+its own `require` using  `module.createRequire()`.
+
+```mjs
+export function globalPreload(context) {
+  return `\
+globalThis.someInjectedProperty = 42;
+console.log('I just set some globals!');
+
+const { createRequire } = getBuiltin('module');
+const { cwd } = getBuiltin('process');
+
+const require = createRequire(cwd() + '/');
+// [...]
+`;
+}
+```
+
+Another argument is provided to the preload code: `port`. This is available as a
+parameter to the hook and inside of the source text returned by the hook. This
+functionality has been moved to the `initialize` hook.
+
+Care must be taken in order to properly call [`port.ref()`][] and
+[`port.unref()`][] to prevent a process from being in a state where it won't
+close normally.
+
+```mjs
+/**
+ * This example has the application context send a message to the hook
+ * and sends the message back to the application context
+ */
+export function globalPreload({ port }) {
+  port.on('message', (msg) => {
+    port.postMessage(msg);
+  });
+  return `\
+    port.postMessage('console.log("I went to the hook and back");');
+    port.on('message', (msg) => {
+      eval(msg);
+    });
+  `;
+}
+```
+
+### Examples
+
+The various module customization hooks can be used together to accomplish
+wide-ranging customizations of the Node.js code loading and evaluation
+behaviors.
+
+#### Import from HTTPS
+
+In current Node.js, specifiers starting with `https://` are experimental (see
+[HTTPS and HTTP imports][]).
+
+The hook below registers hooks to enable rudimentary support for such
+specifiers. While this may seem like a significant improvement to Node.js core
+functionality, there are substantial downsides to actually using these hooks:
+performance is much slower than loading files from disk, there is no caching,
+and there is no security.
+
+```mjs
+// https-hooks.mjs
+import { get } from 'node:https';
+
+export function load(url, context, nextLoad) {
+  // For JavaScript to be loaded over the network, we need to fetch and
+  // return it.
+  if (url.startsWith('https://')) {
+    return new Promise((resolve, reject) => {
+      get(url, (res) => {
+        let data = '';
+        res.setEncoding('utf8');
+        res.on('data', (chunk) => data += chunk);
+        res.on('end', () => resolve({
+          // This example assumes all network-provided JavaScript is ES module
+          // code.
+          format: 'module',
+          shortCircuit: true,
+          source: data,
+        }));
+      }).on('error', (err) => reject(err));
+    });
+  }
+
+  // Let Node.js handle all other URLs.
+  return nextLoad(url);
+}
+```
+
+```mjs
+// main.mjs
+import { VERSION } from 'https://coffeescript.org/browser-compiler-modern/coffeescript.js';
+
+console.log(VERSION);
+```
+
+With the preceding hooks module, running
+`node --import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; register(pathToFileURL("./https-hooks.mjs"));' ./main.mjs`
+prints the current version of CoffeeScript per the module at the URL in
+`main.mjs`.
+
+#### Transpilation
+
+Sources that are in formats Node.js doesn't understand can be converted into
+JavaScript using the [`load` hook][load hook].
+
+This is less performant than transpiling source files before running Node.js;
+transpiler hooks should only be used for development and testing purposes.
+
+```mjs
+// coffeescript-hooks.mjs
+import { readFile } from 'node:fs/promises';
+import { dirname, extname, resolve as resolvePath } from 'node:path';
+import { cwd } from 'node:process';
+import { fileURLToPath, pathToFileURL } from 'node:url';
+import coffeescript from 'coffeescript';
+
+const extensionsRegex = /\.(coffee|litcoffee|coffee\.md)$/;
+
+export async function load(url, context, nextLoad) {
+  if (extensionsRegex.test(url)) {
+    // CoffeeScript files can be either CommonJS or ES modules, so we want any
+    // CoffeeScript file to be treated by Node.js the same as a .js file at the
+    // same location. To determine how Node.js would interpret an arbitrary .js
+    // file, search up the file system for the nearest parent package.json file
+    // and read its "type" field.
+    const format = await getPackageType(url);
+
+    const { source: rawSource } = await nextLoad(url, { ...context, format });
+    // This hook converts CoffeeScript source code into JavaScript source code
+    // for all imported CoffeeScript files.
+    const transformedSource = coffeescript.compile(rawSource.toString(), url);
+
+    return {
+      format,
+      shortCircuit: true,
+      source: transformedSource,
+    };
+  }
+
+  // Let Node.js handle all other URLs.
+  return nextLoad(url);
+}
+
+async function getPackageType(url) {
+  // `url` is only a file path during the first iteration when passed the
+  // resolved url from the load() hook
+  // an actual file path from load() will contain a file extension as it's
+  // required by the spec
+  // this simple truthy check for whether `url` contains a file extension will
+  // work for most projects but does not cover some edge-cases (such as
+  // extensionless files or a url ending in a trailing space)
+  const isFilePath = !!extname(url);
+  // If it is a file path, get the directory it's in
+  const dir = isFilePath ?
+    dirname(fileURLToPath(url)) :
+    url;
+  // Compose a file path to a package.json in the same directory,
+  // which may or may not exist
+  const packagePath = resolvePath(dir, 'package.json');
+  // Try to read the possibly nonexistent package.json
+  const type = await readFile(packagePath, { encoding: 'utf8' })
+    .then((filestring) => JSON.parse(filestring).type)
+    .catch((err) => {
+      if (err?.code !== 'ENOENT') console.error(err);
+    });
+  // Ff package.json existed and contained a `type` field with a value, voila
+  if (type) return type;
+  // Otherwise, (if not at the root) continue checking the next directory up
+  // If at the root, stop and return false
+  return dir.length > 1 && getPackageType(resolvePath(dir, '..'));
+}
+```
+
+```coffee
+# main.coffee
+import { scream } from './scream.coffee'
+console.log scream 'hello, world'
+
+import { version } from 'node:process'
+console.log "Brought to you by Node.js version #{version}"
+```
+
+```coffee
+# scream.coffee
+export scream = (str) -> str.toUpperCase()
+```
+
+With the preceding hooks module, running
+`node --import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; register(pathToFileURL("./coffeescript-hooks.mjs"));' ./main.coffee`
+causes `main.coffee` to be turned into JavaScript after its source code is
+loaded from disk but before Node.js executes it; and so on for any `.coffee`,
+`.litcoffee` or `.coffee.md` files referenced via `import` statements of any
+loaded file.
+
+#### Import maps
+
+The previous two examples defined `load` hooks. This is an example of a
+`resolve` hook. This hooks module reads an `import-map.json` file that defines
+which specifiers to override to other URLs (this is a very simplistic
+implementation of a small subset of the "import maps" specification).
+
+```mjs
+// import-map-hooks.js
+import fs from 'node:fs/promises';
+
+const { imports } = JSON.parse(await fs.readFile('import-map.json'));
+
+export async function resolve(specifier, context, nextResolve) {
+  if (Object.hasOwn(imports, specifier)) {
+    return nextResolve(imports[specifier], context);
+  }
+
+  return nextResolve(specifier, context);
+}
+```
+
+With these files:
+
+```mjs
+// main.js
+import 'a-module';
+```
+
+```json
+// import-map.json
+{
+  "imports": {
+    "a-module": "./some-module.js"
+  }
+}
+```
+
+```mjs
+// some-module.js
+console.log('some module!');
+```
+
+Running `node --import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; register(pathToFileURL("./import-map-hooks.js"));' main.js`
+should print `some module!`.
+
 ## Source map v3 support
 
 
 
 
-    
-    
-    
-    
-  
-  
-    
-    
-    
-    
-  
-  
-    
-    
-    
-    
+    
+    
-    
-    
-    
-    
+    
+    
-    
-    
-    
-    
+    
+    
-
123
v6.xv6.14.2*
v8.xv8.6.0**v8.10.0*v8.11.2Node-API versionSupported In
v9.xv9.0.0*v9.3.0*v9.11.0*9v18.17.0+, 20.3.0+, 21.0.0 and all later versions
≥ v10.xall releasesall releasesall releases8v12.22.0+, v14.17.0+, v15.12.0+, 16.0.0 and all later versions
- - - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - - - - - - - - - + + + - - - - - - + + - - - - - - + +
456787v10.23.0+, v12.19.0+, v14.12.0+, 15.0.0 and all later versions
v10.xv10.16.0v10.17.0v10.20.0v10.23.06v10.20.0+, v12.17.0+, 14.0.0 and all later versions
v11.xv11.8.05v10.17.0+, v12.11.0+, 13.0.0 and all later versions
v12.xv12.0.0v12.11.0v12.17.0v12.19.0v12.22.04v10.16.0+, v11.8.0+, 12.0.0 and all later versions
v13.xv13.0.0v13.0.0
v14.xv14.0.0v14.0.0v14.0.0v14.12.0v14.17.0
3v6.14.2*, 8.11.2+, v9.11.0+*, 10.0.0 and all later versions
v15.xv15.0.0v15.0.0v15.0.0v15.0.0v15.12.02v8.10.0+*, v9.3.0+*, 10.0.0 and all later versions
v16.xv16.0.0v16.0.0v16.0.0v16.0.0v16.0.01v8.6.0+**, v9.0.0+*, 10.0.0 and all later versions
@@ -398,7 +346,7 @@ napi_value create_addon(napi_env env); // addon.c #include "addon.h" -#define NAPI_CALL(env, call) \ +#define NODE_API_CALL(env, call) \ do { \ napi_status status = (call); \ if (status != napi_ok) { \ @@ -407,13 +355,14 @@ napi_value create_addon(napi_env env); const char* err_message = error_info->error_message; \ bool is_pending; \ napi_is_exception_pending((env), &is_pending); \ + /* If an exception is already pending, don't rethrow it */ \ if (!is_pending) { \ const char* message = (err_message == NULL) \ ? "empty error message" \ : err_message; \ napi_throw_error((env), NULL, message); \ - return NULL; \ } \ + return NULL; \ } \ } while(0) @@ -425,20 +374,20 @@ DoSomethingUseful(napi_env env, napi_callback_info info) { napi_value create_addon(napi_env env) { napi_value result; - NAPI_CALL(env, napi_create_object(env, &result)); + NODE_API_CALL(env, napi_create_object(env, &result)); napi_value exported_function; - NAPI_CALL(env, napi_create_function(env, - "doSomethingUseful", - NAPI_AUTO_LENGTH, - DoSomethingUseful, - NULL, - &exported_function)); - - NAPI_CALL(env, napi_set_named_property(env, - result, - "doSomethingUseful", - exported_function)); + NODE_API_CALL(env, napi_create_function(env, + "doSomethingUseful", + NAPI_AUTO_LENGTH, + DoSomethingUseful, + NULL, + &exported_function)); + + NODE_API_CALL(env, napi_set_named_property(env, + result, + "doSomethingUseful", + exported_function)); return result; } @@ -3118,13 +3067,18 @@ napi_status napi_get_buffer_info(napi_env env, ``` * `[in] env`: The environment that the API is invoked under. -* `[in] value`: `napi_value` representing the `node::Buffer` being queried. -* `[out] data`: The underlying data buffer of the `node::Buffer`. - If length is `0`, this may be `NULL` or any other pointer value. +* `[in] value`: `napi_value` representing the `node::Buffer` or `Uint8Array` + being queried. +* `[out] data`: The underlying data buffer of the `node::Buffer` or + `Uint8Array`. If length is `0`, this may be `NULL` or any other pointer value. * `[out] length`: Length in bytes of the underlying data buffer. Returns `napi_ok` if the API succeeded. +This method returns the identical `data` and `byte_length` as +[`napi_get_typedarray_info`][]. And `napi_get_typedarray_info` accepts a +`node::Buffer` (a Uint8Array) as the value too. + This API is used to retrieve the underlying data buffer of a `node::Buffer` and its length. @@ -3875,12 +3829,14 @@ napi_status napi_is_buffer(napi_env env, napi_value value, bool* result) * `[in] env`: The environment that the API is invoked under. * `[in] value`: The JavaScript value to check. -* `[out] result`: Whether the given `napi_value` represents a `node::Buffer` - object. +* `[out] result`: Whether the given `napi_value` represents a `node::Buffer` or + `Uint8Array` object. Returns `napi_ok` if the API succeeded. -This API checks if the `Object` passed in is a buffer. +This API checks if the `Object` passed in is a buffer or Uint8Array. +[`napi_is_typedarray`][] should be preferred if the caller needs to check if the +value is a Uint8Array. ### `napi_is_date` @@ -5464,6 +5420,42 @@ invocation. If it is deleted before then, then the finalize callback may never be invoked. Therefore, when obtaining a reference a finalize callback is also required in order to enable correct disposal of the reference. +#### `node_api_post_finalizer` + + + +> Stability: 1 - Experimental + +```c +napi_status node_api_post_finalizer(napi_env env, + napi_finalize finalize_cb, + void* finalize_data, + void* finalize_hint); +``` + +* `[in] env`: The environment that the API is invoked under. +* `[in] finalize_cb`: Native callback that will be used to free the + native data when the JavaScript object has been garbage-collected. + [`napi_finalize`][] provides more details. +* `[in] finalize_data`: Optional data to be passed to `finalize_cb`. +* `[in] finalize_hint`: Optional contextual hint that is passed to the + finalize callback. + +Returns `napi_ok` if the API succeeded. + +Schedules a `napi_finalize` callback to be called asynchronously in the +event loop. + +Normally, finalizers are called while the GC (garbage collector) collects +objects. At that point calling any Node-API that may cause changes in the GC +state will be disabled and will crash Node.js. + +`node_api_post_finalizer` helps to work around this limitation by allowing the +add-on to defer calls to such Node-APIs to a point in time outside of the GC +finalization. + ## Simple asynchronous operations Addon modules often need to leverage async helpers from libuv as part of their @@ -5681,7 +5673,7 @@ problems like loss of async context when using the `AsyncLocalStorage` API. In order to retain ABI compatibility with previous versions, passing `NULL` for `async_resource` does not result in an error. However, this is not -recommended as this will result poor results with `async_hooks` +recommended as this will result in undesirable behavior with `async_hooks` [`init` hooks][] and `async_hooks.executionAsyncResource()` as the resource is now required by the underlying `async_hooks` implementation in order to provide the linkage between async callbacks. @@ -6285,6 +6277,13 @@ napi_create_threadsafe_function(napi_env env, [`napi_threadsafe_function_call_js`][] provides more details. * `[out] result`: The asynchronous thread-safe JavaScript function. +**Change History:** + +* Experimental (`NAPI_EXPERIMENTAL` is defined): + + Uncaught exceptions thrown in `call_js_cb` are handled with the + [`'uncaughtException'`][] event, instead of being ignored. + ### `napi_get_threadsafe_function_context` + +> Stability: 1 - Experimental + +* {boolean} + +The `process.sourceMapsEnabled` property returns whether the +[Source Map v3][Source Map] support for stack traces is enabled. + ## `process.stderr` * {Stream} diff --git a/doc/api/readline.md b/doc/api/readline.md index 188fae575aa840..f646edb9bbc97f 100644 --- a/doc/api/readline.md +++ b/doc/api/readline.md @@ -1302,8 +1302,8 @@ const { createInterface } = require('node:readline'); Meta+Y - Cycle among previously deleted lines - Only available when the last keystroke is Ctrl+Y + Cycle among previously deleted texts + Only available when the last keystroke is Ctrl+Y or Meta+Y Ctrl+A diff --git a/doc/api/single-executable-applications.md b/doc/api/single-executable-applications.md index 5933ae98b1cd73..147c927ee354d1 100644 --- a/doc/api/single-executable-applications.md +++ b/doc/api/single-executable-applications.md @@ -39,7 +39,24 @@ tool, [postject][]: $ cp $(command -v node) hello ``` -3. Inject the JavaScript file into the copied binary by running `postject` with +3. Remove the signature of the binary: + + * On macOS: + + ```console + $ codesign --remove-signature hello + ``` + + * On Windows (optional): + + [signtool][] can be used from the installed [Windows SDK][]. If this step is + skipped, ignore any signature-related warning from postject. + + ```console + $ signtool remove /s hello + ``` + +4. Inject the JavaScript file into the copied binary by running `postject` with the following options: * `hello` - The name of the copy of the `node` executable created in step 2. @@ -67,7 +84,24 @@ tool, [postject][]: --macho-segment-name NODE_JS ``` -4. Run the binary: +5. Sign the binary: + + * On macOS: + + ```console + $ codesign --sign - hello + ``` + + * On Windows (optional): + + A certificate needs to be present for this to work. However, the unsigned + binary would still be runnable. + + ```console + $ signtool sign /fd SHA256 hello + ``` + +6. Run the binary: ```console $ ./hello world Hello, world! @@ -125,7 +159,8 @@ platforms: * Windows * macOS -* Linux (AMD64 only) +* Linux (all distributions [supported by Node.js][] except Alpine and all + architectures [supported by Node.js][] except s390x and ppc64) This is due to a lack of better tools to generate single-executables that can be used to test this feature on other platforms. @@ -138,9 +173,12 @@ to help us document them. [ELF]: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format [Mach-O]: https://en.wikipedia.org/wiki/Mach-O [PE]: https://en.wikipedia.org/wiki/Portable_Executable +[Windows SDK]: https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/ [`process.execPath`]: process.md#processexecpath [`require()`]: modules.md#requireid [`require.main`]: modules.md#accessing-the-main-module [fuse]: https://www.electronjs.org/docs/latest/tutorial/fuses [postject]: https://github.com/nodejs/postject +[signtool]: https://learn.microsoft.com/en-us/windows/win32/seccrypto/signtool [single executable applications]: https://github.com/nodejs/single-executable +[supported by Node.js]: https://github.com/nodejs/node/blob/main/BUILDING.md#platform-list diff --git a/doc/api/stream.md b/doc/api/stream.md index 8c1f3aa2051b5f..2a1d6a7df4100d 100644 --- a/doc/api/stream.md +++ b/doc/api/stream.md @@ -278,7 +278,7 @@ run().catch(console.error); rs.resume(); // Drain the stream. ``` -The `finished` API provides [callback version][stream-finished]: +The `finished` API also provides a [callback version][stream-finished]. ### Object mode @@ -2008,6 +2008,10 @@ showBoth(); added: - v17.4.0 - v16.14.0 +changes: + - version: v18.19.0 + pr-url: https://github.com/nodejs/node/pull/49249 + description: added `highWaterMark` in options. --> > Stability: 1 - Experimental @@ -2021,6 +2025,8 @@ added: * `options` {Object} * `concurrency` {number} the maximum concurrent invocation of `fn` to call on the stream at once. **Default:** `1`. + * `highWaterMark` {number} how many items to buffer while waiting for user + consumption of the mapped items. **Default:** `concurrency * 2 - 1`. * `signal` {AbortSignal} allows destroying the stream if the signal is aborted. * Returns: {Readable} a stream mapped with the function `fn`. @@ -2055,6 +2061,10 @@ for await (const result of dnsResults) { added: - v17.4.0 - v16.14.0 +changes: + - version: v18.19.0 + pr-url: https://github.com/nodejs/node/pull/49249 + description: added `highWaterMark` in options. --> > Stability: 1 - Experimental @@ -2067,6 +2077,8 @@ added: * `options` {Object} * `concurrency` {number} the maximum concurrent invocation of `fn` to call on the stream at once. **Default:** `1`. + * `highWaterMark` {number} how many items to buffer while waiting for user + consumption of the filtered items. **Default:** `concurrency * 2 - 1`. * `signal` {AbortSignal} allows destroying the stream if the signal is aborted. * Returns: {Readable} a stream filtered with the predicate `fn`. diff --git a/doc/api/string_decoder.md b/doc/api/string_decoder.md index 70387d2edba696..18960f6acb1736 100644 --- a/doc/api/string_decoder.md +++ b/doc/api/string_decoder.md @@ -21,10 +21,10 @@ const { StringDecoder } = require('node:string_decoder'); const decoder = new StringDecoder('utf8'); const cent = Buffer.from([0xC2, 0xA2]); -console.log(decoder.write(cent)); +console.log(decoder.write(cent)); // Prints: ¢ const euro = Buffer.from([0xE2, 0x82, 0xAC]); -console.log(decoder.write(euro)); +console.log(decoder.write(euro)); // Prints: € ``` When a `Buffer` instance is written to the `StringDecoder` instance, an @@ -41,7 +41,7 @@ const decoder = new StringDecoder('utf8'); decoder.write(Buffer.from([0xE2])); decoder.write(Buffer.from([0x82])); -console.log(decoder.end(Buffer.from([0xAC]))); +console.log(decoder.end(Buffer.from([0xAC]))); // Prints: € ``` ## Class: `StringDecoder` @@ -63,8 +63,7 @@ Creates a new `StringDecoder` instance. added: v0.9.3 --> -* `buffer` {Buffer|TypedArray|DataView} A `Buffer`, or `TypedArray`, or - `DataView` containing the bytes to decode. +* `buffer` {string|Buffer|TypedArray|DataView} The bytes to decode. * Returns: {string} Returns any remaining input stored in the internal buffer as a string. Bytes @@ -86,8 +85,7 @@ changes: character instead of one for each individual byte. --> -* `buffer` {Buffer|TypedArray|DataView} A `Buffer`, or `TypedArray`, or - `DataView` containing the bytes to decode. +* `buffer` {string|Buffer|TypedArray|DataView} The bytes to decode. * Returns: {string} Returns a decoded string, ensuring that any incomplete multibyte characters at diff --git a/doc/api/test.md b/doc/api/test.md index da7f512d41ef62..7f04a11354bcae 100644 --- a/doc/api/test.md +++ b/doc/api/test.md @@ -367,11 +367,12 @@ When searching for test files to execute, the test runner behaves as follows: automatically executed by the test runner, but are supported if explicitly provided on the command line. -Each matching test file is executed in a separate child process. If the child -process finishes with an exit code of 0, the test is considered passing. -Otherwise, the test is considered to be a failure. Test files must be -executable by Node.js, but are not required to use the `node:test` module -internally. +Each matching test file is executed in a separate child process. The maximum +number of child processes running at any time is controlled by the +[`--test-concurrency`][] flag. If the child process finishes with an exit code +of 0, the test is considered passing. Otherwise, the test is considered to be a +failure. Test files must be executable by Node.js, but are not required to use +the `node:test` module internally. Each test file is executed as if it was a regular script. That is, if the test file itself uses `node:test` to define tests, all of those tests will be @@ -507,6 +508,116 @@ test('spies on an object method', (t) => { }); ``` +### Timers + +Mocking timers is a technique commonly used in software testing to simulate and +control the behavior of timers, such as `setInterval` and `setTimeout`, +without actually waiting for the specified time intervals. + +Refer to the [`MockTimers`][] class for a full list of methods and features. + +This allows developers to write more reliable and +predictable tests for time-dependent functionality. + +The example below shows how to mock `setTimeout`. +Using `.enable(['setTimeout']);` +it will mock the `setTimeout` functions in the [node:timers](./timers.md) and +[node:timers/promises](./timers.md#timers-promises-api) modules, +as well as from the Node.js global context. + +**Note:** Destructuring functions such as +`import { setTimeout } from 'node:timers'` +is currently not supported by this API. + +```mjs +import assert from 'node:assert'; +import { mock, test } from 'node:test'; + +test('mocks setTimeout to be executed synchronously without having to actually wait for it', () => { + const fn = mock.fn(); + + // Optionally choose what to mock + mock.timers.enable(['setTimeout']); + setTimeout(fn, 9999); + assert.strictEqual(fn.mock.callCount(), 0); + + // Advance in time + mock.timers.tick(9999); + assert.strictEqual(fn.mock.callCount(), 1); + + // Reset the globally tracked mocks. + mock.timers.reset(); + + // If you call reset mock instance, it will also reset timers instance + mock.reset(); +}); +``` + +```js +const assert = require('node:assert'); +const { mock, test } = require('node:test'); + +test('mocks setTimeout to be executed synchronously without having to actually wait for it', () => { + const fn = mock.fn(); + + // Optionally choose what to mock + mock.timers.enable(['setTimeout']); + setTimeout(fn, 9999); + assert.strictEqual(fn.mock.callCount(), 0); + + // Advance in time + mock.timers.tick(9999); + assert.strictEqual(fn.mock.callCount(), 1); + + // Reset the globally tracked mocks. + mock.timers.reset(); + + // If you call reset mock instance, it'll also reset timers instance + mock.reset(); +}); +``` + +The same mocking functionality is also exposed in the mock property on the [`TestContext`][] object +of each test. The benefit of mocking via the test context is +that the test runner will automatically restore all mocked timers +functionality once the test finishes. + +```mjs +import assert from 'node:assert'; +import { test } from 'node:test'; + +test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => { + const fn = context.mock.fn(); + + // Optionally choose what to mock + context.mock.timers.enable(['setTimeout']); + setTimeout(fn, 9999); + assert.strictEqual(fn.mock.callCount(), 0); + + // Advance in time + context.mock.timers.tick(9999); + assert.strictEqual(fn.mock.callCount(), 1); +}); +``` + +```js +const assert = require('node:assert'); +const { test } = require('node:test'); + +test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => { + const fn = context.mock.fn(); + + // Optionally choose what to mock + context.mock.timers.enable(['setTimeout']); + setTimeout(fn, 9999); + assert.strictEqual(fn.mock.callCount(), 0); + + // Advance in time + context.mock.timers.tick(9999); + assert.strictEqual(fn.mock.callCount(), 1); +}); +``` + ## Test reporters + +> Stability: 1 - Experimental + +Mocking timers is a technique commonly used in software testing to simulate and +control the behavior of timers, such as `setInterval` and `setTimeout`, +without actually waiting for the specified time intervals. + +The [`MockTracker`][] provides a top-level `timers` export +which is a `MockTimers` instance. + +### `timers.enable([timers])` + + + +Enables timer mocking for the specified timers. + +* `timers` {Array} An optional array containing the timers to mock. + The currently supported timer values are `'setInterval'`, `'setTimeout'`, + and `'setImmediate'`. If no value is provided, all timers (`'setInterval'`, + `'clearInterval'`, `'setTimeout'`, `'clearTimeout'`, `'setImmediate'`, + and `'clearImmediate'`) will be mocked by default. + +**Note:** When you enable mocking for a specific timer, its associated +clear function will also be implicitly mocked. + +Example usage: + +```mjs +import { mock } from 'node:test'; +mock.timers.enable(['setInterval']); +``` + +```cjs +const { mock } = require('node:test'); +mock.timers.enable(['setInterval']); +``` + +The above example enables mocking for the `setInterval` timer and +implicitly mocks the `clearInterval` function. Only the `setInterval` +and `clearInterval` functions from [node:timers](./timers.md), +[node:timers/promises](./timers.md#timers-promises-api), and +`globalThis` will be mocked. + +Alternatively, if you call `mock.timers.enable()` without any parameters: + +All timers (`'setInterval'`, `'clearInterval'`, `'setTimeout'`, and `'clearTimeout'`) +will be mocked. The `setInterval`, `clearInterval`, `setTimeout`, and `clearTimeout` +functions from `node:timers`, `node:timers/promises`, +and `globalThis` will be mocked. + +### `timers.reset()` + + + +This function restores the default behavior of all mocks that were previously +created by this `MockTimers` instance and disassociates the mocks +from the `MockTracker` instance. + +**Note:** After each test completes, this function is called on +the test context's `MockTracker`. + +```mjs +import { mock } from 'node:test'; +mock.timers.reset(); +``` + +```cjs +const { mock } = require('node:test'); +mock.timers.reset(); +``` + +### `timers[Symbol.dispose]()` + +Calls `timers.reset()`. + +### `timers.tick(milliseconds)` + + + +Advances time for all mocked timers. + +* `milliseconds` {number} The amount of time, in milliseconds, + to advance the timers. + +**Note:** This diverges from how `setTimeout` in Node.js behaves and accepts +only positive numbers. In Node.js, `setTimeout` with negative numbers is +only supported for web compatibility reasons. + +The following example mocks a `setTimeout` function and +by using `.tick` advances in +time triggering all pending timers. + +```mjs +import assert from 'node:assert'; +import { test } from 'node:test'; + +test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => { + const fn = context.mock.fn(); + + context.mock.timers.enable(['setTimeout']); + + setTimeout(fn, 9999); + + assert.strictEqual(fn.mock.callCount(), 0); + + // Advance in time + context.mock.timers.tick(9999); + + assert.strictEqual(fn.mock.callCount(), 1); +}); +``` + +```cjs +const assert = require('node:assert'); +const { test } = require('node:test'); + +test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => { + const fn = context.mock.fn(); + context.mock.timers.enable(['setTimeout']); + + setTimeout(fn, 9999); + assert.strictEqual(fn.mock.callCount(), 0); + + // Advance in time + context.mock.timers.tick(9999); + + assert.strictEqual(fn.mock.callCount(), 1); +}); +``` + +Alternativelly, the `.tick` function can be called many times + +```mjs +import assert from 'node:assert'; +import { test } from 'node:test'; + +test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => { + const fn = context.mock.fn(); + context.mock.timers.enable(['setTimeout']); + const nineSecs = 9000; + setTimeout(fn, nineSecs); + + const twoSeconds = 3000; + context.mock.timers.tick(twoSeconds); + context.mock.timers.tick(twoSeconds); + context.mock.timers.tick(twoSeconds); + + assert.strictEqual(fn.mock.callCount(), 1); +}); +``` + +```cjs +const assert = require('node:assert'); +const { test } = require('node:test'); + +test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => { + const fn = context.mock.fn(); + context.mock.timers.enable(['setTimeout']); + const nineSecs = 9000; + setTimeout(fn, nineSecs); + + const twoSeconds = 3000; + context.mock.timers.tick(twoSeconds); + context.mock.timers.tick(twoSeconds); + context.mock.timers.tick(twoSeconds); + + assert.strictEqual(fn.mock.callCount(), 1); +}); +``` + +#### Using clear functions + +As mentioned, all clear functions from timers (`clearTimeout` and `clearInterval`) +are implicity mocked. Take a look at this example using `setTimeout`: + +```mjs +import assert from 'node:assert'; +import { test } from 'node:test'; + +test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => { + const fn = context.mock.fn(); + + // Optionally choose what to mock + context.mock.timers.enable(['setTimeout']); + const id = setTimeout(fn, 9999); + + // Implicity mocked as well + clearTimeout(id); + context.mock.timers.tick(9999); + + // As that setTimeout was cleared the mock function will never be called + assert.strictEqual(fn.mock.callCount(), 0); +}); +``` + +```cjs +const assert = require('node:assert'); +const { test } = require('node:test'); + +test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => { + const fn = context.mock.fn(); + + // Optionally choose what to mock + context.mock.timers.enable(['setTimeout']); + const id = setTimeout(fn, 9999); + + // Implicity mocked as well + clearTimeout(id); + context.mock.timers.tick(9999); + + // As that setTimeout was cleared the mock function will never be called + assert.strictEqual(fn.mock.callCount(), 0); +}); +``` + +#### Working with Node.js timers modules + +Once you enable mocking timers, [node:timers](./timers.md), +[node:timers/promises](./timers.md#timers-promises-api) modules, +and timers from the Node.js global context are enabled: + +**Note:** Destructuring functions such as +`import { setTimeout } from 'node:timers'` is currently +not supported by this API. + +```mjs +import assert from 'node:assert'; +import { test } from 'node:test'; +import nodeTimers from 'node:timers'; +import nodeTimersPromises from 'node:timers/promises'; + +test('mocks setTimeout to be executed synchronously without having to actually wait for it', async (context) => { + const globalTimeoutObjectSpy = context.mock.fn(); + const nodeTimerSpy = context.mock.fn(); + const nodeTimerPromiseSpy = context.mock.fn(); + + // Optionally choose what to mock + context.mock.timers.enable(['setTimeout']); + setTimeout(globalTimeoutObjectSpy, 9999); + nodeTimers.setTimeout(nodeTimerSpy, 9999); + + const promise = nodeTimersPromises.setTimeout(9999).then(nodeTimerPromiseSpy); + + // Advance in time + context.mock.timers.tick(9999); + assert.strictEqual(globalTimeoutObjectSpy.mock.callCount(), 1); + assert.strictEqual(nodeTimerSpy.mock.callCount(), 1); + await promise; + assert.strictEqual(nodeTimerPromiseSpy.mock.callCount(), 1); +}); +``` + +```cjs +const assert = require('node:assert'); +const { test } = require('node:test'); +const nodeTimers = require('node:timers'); +const nodeTimersPromises = require('node:timers/promises'); + +test('mocks setTimeout to be executed synchronously without having to actually wait for it', async (context) => { + const globalTimeoutObjectSpy = context.mock.fn(); + const nodeTimerSpy = context.mock.fn(); + const nodeTimerPromiseSpy = context.mock.fn(); + + // Optionally choose what to mock + context.mock.timers.enable(['setTimeout']); + setTimeout(globalTimeoutObjectSpy, 9999); + nodeTimers.setTimeout(nodeTimerSpy, 9999); + + const promise = nodeTimersPromises.setTimeout(9999).then(nodeTimerPromiseSpy); + + // Advance in time + context.mock.timers.tick(9999); + assert.strictEqual(globalTimeoutObjectSpy.mock.callCount(), 1); + assert.strictEqual(nodeTimerSpy.mock.callCount(), 1); + await promise; + assert.strictEqual(nodeTimerPromiseSpy.mock.callCount(), 1); +}); +``` + +In Node.js, `setInterval` from [node:timers/promises](./timers.md#timers-promises-api) +is an `AsyncGenerator` and is also supported by this API: + +```mjs +import assert from 'node:assert'; +import { test } from 'node:test'; +import nodeTimersPromises from 'node:timers/promises'; +test('should tick five times testing a real use case', async (context) => { + context.mock.timers.enable(['setInterval']); + + const expectedIterations = 3; + const interval = 1000; + const startedAt = Date.now(); + async function run() { + const times = []; + for await (const time of nodeTimersPromises.setInterval(interval, startedAt)) { + times.push(time); + if (times.length === expectedIterations) break; + } + return times; + } + + const r = run(); + context.mock.timers.tick(interval); + context.mock.timers.tick(interval); + context.mock.timers.tick(interval); + + const timeResults = await r; + assert.strictEqual(timeResults.length, expectedIterations); + for (let it = 1; it < expectedIterations; it++) { + assert.strictEqual(timeResults[it - 1], startedAt + (interval * it)); + } +}); +``` + +```cjs +const assert = require('node:assert'); +const { test } = require('node:test'); +const nodeTimersPromises = require('node:timers/promises'); +test('should tick five times testing a real use case', async (context) => { + context.mock.timers.enable(['setInterval']); + + const expectedIterations = 3; + const interval = 1000; + const startedAt = Date.now(); + async function run() { + const times = []; + for await (const time of nodeTimersPromises.setInterval(interval, startedAt)) { + times.push(time); + if (times.length === expectedIterations) break; + } + return times; + } + + const r = run(); + context.mock.timers.tick(interval); + context.mock.timers.tick(interval); + context.mock.timers.tick(interval); + + const timeResults = await r; + assert.strictEqual(timeResults.length, expectedIterations); + for (let it = 1; it < expectedIterations; it++) { + assert.strictEqual(timeResults[it - 1], startedAt + (interval * it)); + } +}); +``` + +### `timers.runAll()` + + + +Triggers all pending mocked timers immediately. + +The example below triggers all pending timers immediately, +causing them to execute without any delay. + +```mjs +import assert from 'node:assert'; +import { test } from 'node:test'; + +test('runAll functions following the given order', (context) => { + context.mock.timers.enable(['setTimeout']); + const results = []; + setTimeout(() => results.push(1), 9999); + + // Notice that if both timers have the same timeout, + // the order of execution is guaranteed + setTimeout(() => results.push(3), 8888); + setTimeout(() => results.push(2), 8888); + + assert.deepStrictEqual(results, []); + + context.mock.timers.runAll(); + + assert.deepStrictEqual(results, [3, 2, 1]); +}); +``` + +```cjs +const assert = require('node:assert'); +const { test } = require('node:test'); + +test('runAll functions following the given order', (context) => { + context.mock.timers.enable(['setTimeout']); + const results = []; + setTimeout(() => results.push(1), 9999); + + // Notice that if both timers have the same timeout, + // the order of execution is guaranteed + setTimeout(() => results.push(3), 8888); + setTimeout(() => results.push(2), 8888); + + assert.deepStrictEqual(results, []); + + context.mock.timers.runAll(); + + assert.deepStrictEqual(results, [3, 2, 1]); +}); +``` + +**Note:** The `runAll()` function is specifically designed for +triggering timers in the context of timer mocking. +It does not have any effect on real-time system +clocks or actual timers outside of the mocking environment. + ## Class: `TestsStream` * Extends {ReadableStream} @@ -1397,8 +1990,12 @@ Emitted when code coverage is enabled and all tests have completed. ### Event: `'test:dequeue'` * `data` {Object} + * `column` {number|undefined} The column number where the test is defined, or + `undefined` if the test was run through the REPL. * `file` {string|undefined} The path of the test file, `undefined` if test was run through the REPL. + * `line` {number|undefined} The line number where the test is defined, or + `undefined` if the test was run through the REPL. * `name` {string} The test name. * `nesting` {number} The nesting level of the test. @@ -1407,8 +2004,12 @@ Emitted when a test is dequeued, right before it is executed. ### Event: `'test:diagnostic'` * `data` {Object} + * `column` {number|undefined} The column number where the test is defined, or + `undefined` if the test was run through the REPL. * `file` {string|undefined} The path of the test file, `undefined` if test was run through the REPL. + * `line` {number|undefined} The line number where the test is defined, or + `undefined` if the test was run through the REPL. * `message` {string} The diagnostic message. * `nesting` {number} The nesting level of the test. @@ -1417,8 +2018,12 @@ Emitted when [`context.diagnostic`][] is called. ### Event: `'test:enqueue'` * `data` {Object} + * `column` {number|undefined} The column number where the test is defined, or + `undefined` if the test was run through the REPL. * `file` {string|undefined} The path of the test file, `undefined` if test was run through the REPL. + * `line` {number|undefined} The line number where the test is defined, or + `undefined` if the test was run through the REPL. * `name` {string} The test name. * `nesting` {number} The nesting level of the test. @@ -1427,11 +2032,18 @@ Emitted when a test is enqueued for execution. ### Event: `'test:fail'` * `data` {Object} + * `column` {number|undefined} The column number where the test is defined, or + `undefined` if the test was run through the REPL. * `details` {Object} Additional execution metadata. - * `duration` {number} The duration of the test in milliseconds. - * `error` {Error} The error thrown by the test. + * `duration_ms` {number} The duration of the test in milliseconds. + * `error` {Error} An error wrapping the error thrown by the test. + * `cause` {Error} The actual error thrown by the test. + * `type` {string|undefined} The type of the test, used to denote whether + this is a suite. * `file` {string|undefined} The path of the test file, `undefined` if test was run through the REPL. + * `line` {number|undefined} The line number where the test is defined, or + `undefined` if the test was run through the REPL. * `name` {string} The test name. * `nesting` {number} The nesting level of the test. * `testNumber` {number} The ordinal number of the test. @@ -1443,10 +2055,16 @@ Emitted when a test fails. ### Event: `'test:pass'` * `data` {Object} + * `column` {number|undefined} The column number where the test is defined, or + `undefined` if the test was run through the REPL. * `details` {Object} Additional execution metadata. - * `duration` {number} The duration of the test in milliseconds. + * `duration_ms` {number} The duration of the test in milliseconds. + * `type` {string|undefined} The type of the test, used to denote whether + this is a suite. * `file` {string|undefined} The path of the test file, `undefined` if test was run through the REPL. + * `line` {number|undefined} The line number where the test is defined, or + `undefined` if the test was run through the REPL. * `name` {string} The test name. * `nesting` {number} The nesting level of the test. * `testNumber` {number} The ordinal number of the test. @@ -1458,8 +2076,12 @@ Emitted when a test passes. ### Event: `'test:plan'` * `data` {Object} + * `column` {number|undefined} The column number where the test is defined, or + `undefined` if the test was run through the REPL. * `file` {string|undefined} The path of the test file, `undefined` if test was run through the REPL. + * `line` {number|undefined} The line number where the test is defined, or + `undefined` if the test was run through the REPL. * `nesting` {number} The nesting level of the test. * `count` {number} The number of subtests that have ran. @@ -1468,8 +2090,12 @@ Emitted when all subtests have completed for a given test. ### Event: `'test:start'` * `data` {Object} + * `column` {number|undefined} The column number where the test is defined, or + `undefined` if the test was run through the REPL. * `file` {string|undefined} The path of the test file, `undefined` if test was run through the REPL. + * `line` {number|undefined} The line number where the test is defined, or + `undefined` if the test was run through the REPL. * `name` {string} The test name. * `nesting` {number} The nesting level of the test. @@ -1480,7 +2106,11 @@ defined. ### Event: `'test:stderr'` * `data` {Object} + * `column` {number|undefined} The column number where the test is defined, or + `undefined` if the test was run through the REPL. * `file` {string} The path of the test file. + * `line` {number|undefined} The line number where the test is defined, or + `undefined` if the test was run through the REPL. * `message` {string} The message written to `stderr`. Emitted when a running test writes to `stderr`. @@ -1489,7 +2119,11 @@ This event is only emitted if `--test` flag is passed. ### Event: `'test:stdout'` * `data` {Object} + * `column` {number|undefined} The column number where the test is defined, or + `undefined` if the test was run through the REPL. * `file` {string} The path of the test file. + * `line` {number|undefined} The line number where the test is defined, or + `undefined` if the test was run through the REPL. * `message` {string} The message written to `stdout`. Emitted when a running test writes to `stdout`. @@ -1816,12 +2450,14 @@ added: v18.7.0 [TAP]: https://testanything.org/ [TTY]: tty.md [`--experimental-test-coverage`]: cli.md#--experimental-test-coverage +[`--test-concurrency`]: cli.md#--test-concurrency [`--test-name-pattern`]: cli.md#--test-name-pattern [`--test-only`]: cli.md#--test-only [`--test-reporter-destination`]: cli.md#--test-reporter-destination [`--test-reporter`]: cli.md#--test-reporter [`--test`]: cli.md#--test [`MockFunctionContext`]: #class-mockfunctioncontext +[`MockTimers`]: #class-mocktimers [`MockTracker.method`]: #mockmethodobject-methodname-implementation-options [`MockTracker`]: #class-mocktracker [`NODE_V8_COVERAGE`]: cli.md#node_v8_coveragedir diff --git a/doc/api/tls.md b/doc/api/tls.md index ec2cb286fe31c6..333cfe56ed1dff 100644 --- a/doc/api/tls.md +++ b/doc/api/tls.md @@ -2045,6 +2045,9 @@ where `secureSocket` has the same API as `pair.cleartext`. + * `linker` {Function} * `specifier` {string} The specifier of the requested module: ```mjs @@ -623,15 +631,14 @@ The identifier of the current module, as set in the constructor. * `referencingModule` {vm.Module} The `Module` object `link()` is called on. * `extra` {Object} - * `assert` {Object} The data from the assertion: - - ```js + * `attributes` {Object} The data from the attribute: + ```mjs import foo from 'foo' assert { name: 'value' }; - // ^^^^^^^^^^^^^^^^^ the assertion + // ^^^^^^^^^^^^^^^^^ the attribute ``` - Per ECMA-262, hosts are expected to ignore assertions that they do not - support, as opposed to, for example, triggering an error if an - unsupported assertion is present. + Per ECMA-262, hosts are expected to trigger an error if an + unsupported attribute is present. + * `assert` {Object} Alias for `extra.attributes`. * Returns: {vm.Module|Promise} * Returns: {Promise} @@ -730,7 +737,7 @@ changes: - v17.0.0 - v16.12.0 pr-url: https://github.com/nodejs/node/pull/40249 - description: Added support for import assertions to the + description: Added support for import attributes to the `importModuleDynamically` parameter. --> @@ -760,7 +767,7 @@ changes: `import()` will reject with [`ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING`][]. * `specifier` {string} specifier passed to `import()` * `module` {vm.Module} - * `importAssertions` {Object} The `"assert"` value passed to the + * `importAttributes` {Object} The `"assert"` value passed to the [`optionsExpression`][] optional parameter, or an empty object if no value was provided. * Returns: {Module Namespace Object|vm.Module} Returning a `vm.Module` is @@ -974,7 +981,7 @@ changes: - v17.0.0 - v16.12.0 pr-url: https://github.com/nodejs/node/pull/40249 - description: Added support for import assertions to the + description: Added support for import attributes to the `importModuleDynamically` parameter. - version: v15.9.0 pr-url: https://github.com/nodejs/node/pull/35431 @@ -1018,7 +1025,7 @@ changes: considered stable. * `specifier` {string} specifier passed to `import()` * `function` {Function} - * `importAssertions` {Object} The `"assert"` value passed to the + * `importAttributes` {Object} The `"assert"` value passed to the [`optionsExpression`][] optional parameter, or an empty object if no value was provided. * Returns: {Module Namespace Object|vm.Module} Returning a `vm.Module` is @@ -1204,7 +1211,7 @@ changes: - v17.0.0 - v16.12.0 pr-url: https://github.com/nodejs/node/pull/40249 - description: Added support for import assertions to the + description: Added support for import attributes to the `importModuleDynamically` parameter. - version: v6.3.0 pr-url: https://github.com/nodejs/node/pull/6635 @@ -1242,7 +1249,7 @@ changes: using it in a production environment. * `specifier` {string} specifier passed to `import()` * `script` {vm.Script} - * `importAssertions` {Object} The `"assert"` value passed to the + * `importAttributes` {Object} The `"assert"` value passed to the [`optionsExpression`][] optional parameter, or an empty object if no value was provided. * Returns: {Module Namespace Object|vm.Module} Returning a `vm.Module` is @@ -1282,7 +1289,7 @@ changes: - v17.0.0 - v16.12.0 pr-url: https://github.com/nodejs/node/pull/40249 - description: Added support for import assertions to the + description: Added support for import attributes to the `importModuleDynamically` parameter. - version: v14.6.0 pr-url: https://github.com/nodejs/node/pull/34023 @@ -1341,7 +1348,7 @@ changes: using it in a production environment. * `specifier` {string} specifier passed to `import()` * `script` {vm.Script} - * `importAssertions` {Object} The `"assert"` value passed to the + * `importAttributes` {Object} The `"assert"` value passed to the [`optionsExpression`][] optional parameter, or an empty object if no value was provided. * Returns: {Module Namespace Object|vm.Module} Returning a `vm.Module` is @@ -1385,7 +1392,7 @@ changes: - v17.0.0 - v16.12.0 pr-url: https://github.com/nodejs/node/pull/40249 - description: Added support for import assertions to the + description: Added support for import attributes to the `importModuleDynamically` parameter. - version: v6.3.0 pr-url: https://github.com/nodejs/node/pull/6635 @@ -1421,7 +1428,7 @@ changes: using it in a production environment. * `specifier` {string} specifier passed to `import()` * `script` {vm.Script} - * `importAssertions` {Object} The `"assert"` value passed to the + * `importAttributes` {Object} The `"assert"` value passed to the [`optionsExpression`][] optional parameter, or an empty object if no value was provided. * Returns: {Module Namespace Object|vm.Module} Returning a `vm.Module` is diff --git a/doc/api/webstreams.md b/doc/api/webstreams.md index e557a29b201158..4635e414fd89d0 100644 --- a/doc/api/webstreams.md +++ b/doc/api/webstreams.md @@ -850,7 +850,7 @@ added: v16.5.0 * Returns: {WritableStreamDefaultWriter} -Creates and creates a new writer instance that can be used to write +Creates and returns a new writer instance that can be used to write data into the `WritableStream`. #### `writableStream.locked` @@ -950,8 +950,8 @@ The amount of data required to fill the {WritableStream}'s queue. added: v16.5.0 --> -* type: A promise that is fulfilled with `undefined` when the - writer is ready to be used. +* Type: {Promise} Fulfilled with `undefined` when the writer is ready + to be used. #### `writableStreamDefaultWriter.releaseLock()` @@ -1172,13 +1172,13 @@ changes: description: This class is now exposed on the global object. --> -#### `new ByteLengthQueuingStrategy(options)` +#### `new ByteLengthQueuingStrategy(init)` -* `options` {Object} +* `init` {Object} * `highWaterMark` {number} #### `byteLengthQueuingStrategy.highWaterMark` @@ -1209,13 +1209,13 @@ changes: description: This class is now exposed on the global object. --> -#### `new CountQueuingStrategy(options)` +#### `new CountQueuingStrategy(init)` -* `options` {Object} +* `init` {Object} * `highWaterMark` {number} #### `countQueuingStrategy.highWaterMark` diff --git a/doc/api/worker_threads.md b/doc/api/worker_threads.md index 169d8c4124c142..e0caf303d08f10 100644 --- a/doc/api/worker_threads.md +++ b/doc/api/worker_threads.md @@ -844,7 +844,8 @@ Notable differences inside a Worker environment are: unless otherwise specified. Changes to one copy are not visible in other threads, and are not visible to native add-ons (unless [`worker.SHARE_ENV`][] is passed as the `env` option to the - [`Worker`][] constructor). + [`Worker`][] constructor). On Windows, unlike the main thread, a copy of the + environment variables operates in a case-sensitive manner. * [`process.title`][] cannot be modified. * Signals are not delivered through [`process.on('...')`][Signals events]. * Execution may stop at any point as a result of [`worker.terminate()`][] diff --git a/doc/changelogs/CHANGELOG_V18.md b/doc/changelogs/CHANGELOG_V18.md index d33bd11cb82f4b..e7c1ecbdbdb390 100644 --- a/doc/changelogs/CHANGELOG_V18.md +++ b/doc/changelogs/CHANGELOG_V18.md @@ -9,6 +9,7 @@ +18.19.0
18.18.2
18.18.1
18.18.0
@@ -62,6 +63,466 @@ * [io.js](CHANGELOG_IOJS.md) * [Archive](CHANGELOG_ARCHIVE.md) + + +## 2023-11-29, Version 18.19.0 'Hydrogen' (LTS), @targos + +### Notable Changes + +#### npm updated to v10 + +After two months of baking time in Node.js 20, npm 10 is backported, so that all +release lines include a supported version of npm. This release includes npm v10.2.3. + +Refer to for the plan to land npm 10. + +#### ESM and customization hook changes + +##### Leverage loaders when resolving subsequent loaders + +Loaders now apply to subsequent loaders, for example: `--experimental-loader ts-node --experimental-loader loader-written-in-typescript`. + +Contributed by Maël Nison in [#43772](https://github.com/nodejs/node/pull/43772). + +##### New `node:module` API `register` for module customization hooks; new `initialize` hook + +There is a new API `register` available on `node:module` to specify a file that exports module customization hooks, and pass data to the hooks, and establish communication channels with them. The “define the file with the hooks” part was previously handled by a flag `--experimental-loader`, but when the hooks moved into a dedicated thread in 20.0.0 there was a need to provide a way to communicate between the main (application) thread and the hooks thread. This can now be done by calling `register` from the main thread and passing data, including `MessageChannel` instances. + +We encourage users to migrate to an approach that uses [`--import`](https://nodejs.org/api/cli.html#--importmodule) with `register`, such as: + +```bash +node --import ./file-that-calls-register.js ./app.js +``` + +Using `--import` ensures that the customization hooks are registered before any application code runs, even the entry point. + +Contributed by João Lenon and Jacob Smith in [#46826](https://github.com/nodejs/node/pull/46826), Izaak Schroeder and Jacob Smith in [#48842](https://github.com/nodejs/node/pull/48842) and [#48559](https://github.com/nodejs/node/pull/48559). + +##### `import.meta.resolve` unflagged + +In ES modules, [`import.meta.resolve(specifier)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import.meta/resolve) +can be used to get an absolute URL string to which `specifier` resolves, similar +to `require.resolve` in CommonJS. This aligns Node.js with browsers and other server-side runtimes. + +Contributed by Guy Bedford in [#49028](https://github.com/nodejs/node/pull/49028). + +##### `--experimental-default-type` flag to flip module defaults + +The new flag `--experimental-default-type` can be used to flip the default +module system used by Node.js. Input that is already explicitly defined as ES +modules or CommonJS, such as by a `package.json` `"type"` field or `.mjs`/`.cjs` +file extension or the `--input-type` flag, is unaffected. What is currently +implicitly CommonJS would instead be interpreted as ES modules under +`--experimental-default-type=module`: + +* String input provided via `--eval` or STDIN, if `--input-type` is unspecified. + +* Files ending in `.js` or with no extension, if there is no `package.json` file + present in the same folder or any parent folder. + +* Files ending in `.js` or with no extension, if the nearest parent + `package.json` field lacks a `type` field; unless the folder is inside a + `node_modules` folder. + +In addition, extensionless files are interpreted as Wasm if +`--experimental-wasm-modules` is passed and the file contains the "magic bytes" +Wasm header. + +Contributed by Geoffrey Booth in [#49869](https://github.com/nodejs/node/pull/49869). + +##### Other ESM-related changes + +* \[[`ed2d46f4cc`](https://github.com/nodejs/node/commit/ed2d46f4cc)] - **doc**: move and rename loaders section (Geoffrey Booth) [#49261](https://github.com/nodejs/node/pull/49261) +* \[[`92734d4480`](https://github.com/nodejs/node/commit/92734d4480)] - **esm**: use import attributes instead of import assertions (Antoine du Hamel) [#50140](https://github.com/nodejs/node/pull/50140) +* \[[`e96f7ef881`](https://github.com/nodejs/node/commit/e96f7ef881)] - **(SEMVER-MINOR)** **vm**: use import attributes instead of import assertions (Antoine du Hamel) [#50141](https://github.com/nodejs/node/pull/50141) + +#### Test runner changes + +Many changes to the built-in test runner have been backported. This includes +the following additions: + +* \[[`b283ae4238`](https://github.com/nodejs/node/commit/b283ae4238)] - **(SEMVER-MINOR)** **test\_runner**: accept `testOnly` in `run` (Moshe Atlow) [#49753](https://github.com/nodejs/node/pull/49753) +* \[[`059b1945d8`](https://github.com/nodejs/node/commit/059b1945d8)] - **(SEMVER-MINOR)** **test\_runner**: add junit reporter (Moshe Atlow) [#49614](https://github.com/nodejs/node/pull/49614) +* \[[`d61a505546`](https://github.com/nodejs/node/commit/d61a505546)] - **(SEMVER-MINOR)** **test\_runner**: expose location of tests (Colin Ihrig) [#48975](https://github.com/nodejs/node/pull/48975) +* \[[`b55eb2a8d1`](https://github.com/nodejs/node/commit/b55eb2a8d1)] - **(SEMVER-MINOR)** **test\_runner**: add shards support (Raz Luvaton) [#48639](https://github.com/nodejs/node/pull/48639) +* \[[`05e7f28b40`](https://github.com/nodejs/node/commit/05e7f28b40)] - **(SEMVER-MINOR)** **test\_runner**: add initial draft for fakeTimers (Erick Wendel) [#47775](https://github.com/nodejs/node/pull/47775) +* \[[`428301ad27`](https://github.com/nodejs/node/commit/428301ad27)] - **(SEMVER-MINOR)** **test\_runner, cli**: add --test-concurrency flag (Colin Ihrig) [#49996](https://github.com/nodejs/node/pull/49996) + +#### Other notable changes + +* \[[`0c4a84e8e9`](https://github.com/nodejs/node/commit/0c4a84e8e9)] - **(SEMVER-MINOR)** **deps**: update uvwasi to 0.0.19 (Node.js GitHub Bot) [#49908](https://github.com/nodejs/node/pull/49908) +* \[[`fae60c5841`](https://github.com/nodejs/node/commit/fae60c5841)] - **stream**: use bitmap in readable state (Benjamin Gruenbaum) [#49745](https://github.com/nodejs/node/pull/49745) +* \[[`17246be158`](https://github.com/nodejs/node/commit/17246be158)] - **(SEMVER-MINOR)** **lib**: add api to detect whether source-maps are enabled (翠 / green) [#46391](https://github.com/nodejs/node/pull/46391) +* \[[`2e9f7284a1`](https://github.com/nodejs/node/commit/2e9f7284a1)] - **(SEMVER-MINOR)** **lib**: add tracing channel to diagnostics\_channel (Stephen Belanger) [#44943](https://github.com/nodejs/node/pull/44943) +* \[[`cc7bf1f641`](https://github.com/nodejs/node/commit/cc7bf1f641)] - **(SEMVER-MINOR)** **src**: add cjs\_module\_lexer\_version base64\_version (Jithil P Ponnan) [#45629](https://github.com/nodejs/node/pull/45629) +* \[[`b5d16cd8f0`](https://github.com/nodejs/node/commit/b5d16cd8f0)] - **(SEMVER-MINOR)** **tls**: add ALPNCallback server option for dynamic ALPN negotiation (Tim Perry) [#45190](https://github.com/nodejs/node/pull/45190) + +### Commits + +* \[[`0d0eb47e2a`](https://github.com/nodejs/node/commit/0d0eb47e2a)] - **benchmark**: add benchmarks for the test\_runner (Raz Luvaton) [#48931](https://github.com/nodejs/node/pull/48931) +* \[[`8bb03d10f4`](https://github.com/nodejs/node/commit/8bb03d10f4)] - **benchmark**: differentiate whatwg and legacy url (Yagiz Nizipli) [#47377](https://github.com/nodejs/node/pull/47377) +* \[[`3d7734cbe3`](https://github.com/nodejs/node/commit/3d7734cbe3)] - **benchmark**: lower URL.canParse runs (Khafra) [#47351](https://github.com/nodejs/node/pull/47351) +* \[[`24d3fcf415`](https://github.com/nodejs/node/commit/24d3fcf415)] - **benchmark**: stablize encode benchmark (Joyee Cheung) [#46658](https://github.com/nodejs/node/pull/46658) +* \[[`e08fd98bcc`](https://github.com/nodejs/node/commit/e08fd98bcc)] - **bootstrap**: use correct descriptor for Symbol.{dispose,asyncDispose} (Jordan Harband) [#48703](https://github.com/nodejs/node/pull/48703) +* \[[`cf9ddcd6c8`](https://github.com/nodejs/node/commit/cf9ddcd6c8)] - **bootstrap**: simplify initialization of source map handlers (Joyee Cheung) [#48304](https://github.com/nodejs/node/pull/48304) +* \[[`12d731e431`](https://github.com/nodejs/node/commit/12d731e431)] - **bootstrap**: log isolate data info in mksnapshot debug logs (Joyee Cheung) [#47768](https://github.com/nodejs/node/pull/47768) +* \[[`d66873871a`](https://github.com/nodejs/node/commit/d66873871a)] - **bootstrap**: store internal loaders in C++ via a binding (Joyee Cheung) [#47215](https://github.com/nodejs/node/pull/47215) +* \[[`1a499c5082`](https://github.com/nodejs/node/commit/1a499c5082)] - **bootstrap**: optimize modules loaded in the built-in snapshot (Joyee Cheung) [#45849](https://github.com/nodejs/node/pull/45849) +* \[[`e0e09caafe`](https://github.com/nodejs/node/commit/e0e09caafe)] - **bootstrap**: make CJS loader snapshotable (Joyee Cheung) [#45849](https://github.com/nodejs/node/pull/45849) +* \[[`5f37decd56`](https://github.com/nodejs/node/commit/5f37decd56)] - **bootstrap**: include event\_target into the built-in snapshot (Joyee Cheung) [#45849](https://github.com/nodejs/node/pull/45849) +* \[[`c3f56a3dee`](https://github.com/nodejs/node/commit/c3f56a3dee)] - **bootstrap**: support module\_wrap binding in snapshot (Joyee Cheung) [#45849](https://github.com/nodejs/node/pull/45849) +* \[[`6466acbc89`](https://github.com/nodejs/node/commit/6466acbc89)] - **bootstrap**: lazy load non-essential modules (Joyee Cheung) [#45659](https://github.com/nodejs/node/pull/45659) +* \[[`a0d4b69df4`](https://github.com/nodejs/node/commit/a0d4b69df4)] - **bootstrap**: lazy-load Performance.prototype.timeOrigin (Joyee Cheung) [#46425](https://github.com/nodejs/node/pull/46425) +* \[[`c1bc8118e3`](https://github.com/nodejs/node/commit/c1bc8118e3)] - **bootstrap**: generate bootstrapper arguments in BuiltinLoader (Joyee Cheung) [#44488](https://github.com/nodejs/node/pull/44488) +* \[[`075c57e88b`](https://github.com/nodejs/node/commit/075c57e88b)] - **build**: add symlink to `compile_commands.json` file if needed (Juan José) [#49260](https://github.com/nodejs/node/pull/49260) +* \[[`9e1c531b8d`](https://github.com/nodejs/node/commit/9e1c531b8d)] - **build**: expand when we run internet tests (Michael Dawson) [#49218](https://github.com/nodejs/node/pull/49218) +* \[[`a781d24624`](https://github.com/nodejs/node/commit/a781d24624)] - **build**: fix typo `libray` -> `library` (configure.py) (michalbiesek) [#49106](https://github.com/nodejs/node/pull/49106) +* \[[`f2eccb7a04`](https://github.com/nodejs/node/commit/f2eccb7a04)] - **build**: fix `configure --link-module` (Richard Lau) [#48522](https://github.com/nodejs/node/pull/48522) +* \[[`a44d555494`](https://github.com/nodejs/node/commit/a44d555494)] - **build**: fix IBM i build with Python 3.9 (Richard Lau) [#48056](https://github.com/nodejs/node/pull/48056) +* \[[`7f68e14ea2`](https://github.com/nodejs/node/commit/7f68e14ea2)] - **child\_process**: improve spawn performance on Linux (Keyhan Vakil) [#48523](https://github.com/nodejs/node/pull/48523) +* \[[`76e4d4117c`](https://github.com/nodejs/node/commit/76e4d4117c)] - **crypto**: ensure valid point on elliptic curve in SubtleCrypto.importKey (Filip Skokan) [#50234](https://github.com/nodejs/node/pull/50234) +* \[[`7af54279b5`](https://github.com/nodejs/node/commit/7af54279b5)] - **deps**: V8: cherry-pick 70caf337c3f6 (kxxt) [#50506](https://github.com/nodejs/node/pull/50506) +* \[[`49c5495339`](https://github.com/nodejs/node/commit/49c5495339)] - **deps**: update zlib to 1.2.13.1-motley-fef5869 (Node.js GitHub Bot) [#50085](https://github.com/nodejs/node/pull/50085) +* \[[`e0fd52bf07`](https://github.com/nodejs/node/commit/e0fd52bf07)] - **deps**: update googletest to 2dd1c13 (Node.js GitHub Bot) [#50081](https://github.com/nodejs/node/pull/50081) +* \[[`1b103cc567`](https://github.com/nodejs/node/commit/1b103cc567)] - **deps**: update googletest to e47544a (Node.js GitHub Bot) [#49982](https://github.com/nodejs/node/pull/49982) +* \[[`736c869eeb`](https://github.com/nodejs/node/commit/736c869eeb)] - **deps**: update googletest to d1467f5 (Node.js GitHub Bot) [#49676](https://github.com/nodejs/node/pull/49676) +* \[[`cd99ee1f35`](https://github.com/nodejs/node/commit/cd99ee1f35)] - **deps**: update googletest to 8a6feab (Node.js GitHub Bot) [#49463](https://github.com/nodejs/node/pull/49463) +* \[[`5c338573ff`](https://github.com/nodejs/node/commit/5c338573ff)] - **deps**: update zlib to 1.2.13.1-motley-f5fd0ad (Node.js GitHub Bot) [#49252](https://github.com/nodejs/node/pull/49252) +* \[[`374ec3d623`](https://github.com/nodejs/node/commit/374ec3d623)] - **deps**: update googletest to 7e33b6a (Node.js GitHub Bot) [#49034](https://github.com/nodejs/node/pull/49034) +* \[[`c15dd6679b`](https://github.com/nodejs/node/commit/c15dd6679b)] - **deps**: update zlib to 1.2.13.1-motley-526382e (Node.js GitHub Bot) [#49033](https://github.com/nodejs/node/pull/49033) +* \[[`588bd5e524`](https://github.com/nodejs/node/commit/588bd5e524)] - **deps**: update googletest to c875c4e (Node.js GitHub Bot) [#48964](https://github.com/nodejs/node/pull/48964) +* \[[`6059b59018`](https://github.com/nodejs/node/commit/6059b59018)] - **deps**: update zlib to 1.2.13.1-motley-61dc0bd (Node.js GitHub Bot) [#48788](https://github.com/nodejs/node/pull/48788) +* \[[`e455dd4003`](https://github.com/nodejs/node/commit/e455dd4003)] - **deps**: update googletest to cc36671 (Node.js GitHub Bot) [#48789](https://github.com/nodejs/node/pull/48789) +* \[[`747fbb49ca`](https://github.com/nodejs/node/commit/747fbb49ca)] - **deps**: V8: cherry-pick 1a782f6543ae (Keyhan Vakil) [#48523](https://github.com/nodejs/node/pull/48523) +* \[[`272e55c66f`](https://github.com/nodejs/node/commit/272e55c66f)] - **deps**: upgrade npm to 10.2.3 (npm team) [#50531](https://github.com/nodejs/node/pull/50531) +* \[[`3f6dcc62e5`](https://github.com/nodejs/node/commit/3f6dcc62e5)] - **deps**: update archs files for openssl-3.0.12+quic1 (Node.js GitHub Bot) [#50411](https://github.com/nodejs/node/pull/50411) +* \[[`da26cdbe84`](https://github.com/nodejs/node/commit/da26cdbe84)] - **deps**: upgrade openssl sources to quictls/openssl-3.0.12+quic1 (Node.js GitHub Bot) [#50411](https://github.com/nodejs/node/pull/50411) +* \[[`23069c34b2`](https://github.com/nodejs/node/commit/23069c34b2)] - **deps**: V8: cherry-pick d69c7937c99d (Michaël Zasso) [#46425](https://github.com/nodejs/node/pull/46425) +* \[[`5f852cc9fe`](https://github.com/nodejs/node/commit/5f852cc9fe)] - **deps**: V8: cherry-pick f7d000a7ae7b (Luke Albao) [#50344](https://github.com/nodejs/node/pull/50344) +* \[[`0c4a84e8e9`](https://github.com/nodejs/node/commit/0c4a84e8e9)] - **(SEMVER-MINOR)** **deps**: update uvwasi to 0.0.19 (Node.js GitHub Bot) [#49908](https://github.com/nodejs/node/pull/49908) +* \[[`8682b90d02`](https://github.com/nodejs/node/commit/8682b90d02)] - **deps**: update simdutf to 3.2.18 (Node.js GitHub Bot) [#50091](https://github.com/nodejs/node/pull/50091) +* \[[`11ecd06aeb`](https://github.com/nodejs/node/commit/11ecd06aeb)] - **deps**: update simdutf to 3.2.17 (Node.js GitHub Bot) [#49019](https://github.com/nodejs/node/pull/49019) +* \[[`43bfe5f020`](https://github.com/nodejs/node/commit/43bfe5f020)] - **deps**: upgrade npm to 10.2.0 (npm team) [#50027](https://github.com/nodejs/node/pull/50027) +* \[[`a140bc284b`](https://github.com/nodejs/node/commit/a140bc284b)] - **deps**: upgrade npm to 10.1.0 (npm team) [#49570](https://github.com/nodejs/node/pull/49570) +* \[[`65ca41c276`](https://github.com/nodejs/node/commit/65ca41c276)] - **(SEMVER-MINOR)** **deps**: upgrade npm to 10.0.0 (npm team) [#49423](https://github.com/nodejs/node/pull/49423) +* \[[`df1ff8e3da`](https://github.com/nodejs/node/commit/df1ff8e3da)] - **deps**: fix call to undeclared functions 'ntohl' and 'htons' (MatteoBax) [#49979](https://github.com/nodejs/node/pull/49979) +* \[[`f228dc7955`](https://github.com/nodejs/node/commit/f228dc7955)] - **deps**: update corepack to 0.22.0 (Node.js GitHub Bot) [#50325](https://github.com/nodejs/node/pull/50325) +* \[[`4324ebab67`](https://github.com/nodejs/node/commit/4324ebab67)] - **deps**: update corepack to 0.21.0 (Node.js GitHub Bot) [#50088](https://github.com/nodejs/node/pull/50088) +* \[[`1cabb77659`](https://github.com/nodejs/node/commit/1cabb77659)] - **deps**: update corepack to 0.20.0 (Node.js GitHub Bot) [#49464](https://github.com/nodejs/node/pull/49464) +* \[[`04227b287e`](https://github.com/nodejs/node/commit/04227b287e)] - **deps**: update c-ares to 1.20.1 (Node.js GitHub Bot) [#50082](https://github.com/nodejs/node/pull/50082) +* \[[`13e69ee11c`](https://github.com/nodejs/node/commit/13e69ee11c)] - **deps**: update c-ares to 1.20.0 (Node.js GitHub Bot) [#50082](https://github.com/nodejs/node/pull/50082) +* \[[`ac717df17e`](https://github.com/nodejs/node/commit/ac717df17e)] - **deps**: update ada to 2.7.2 (Node.js GitHub Bot) [#50338](https://github.com/nodejs/node/pull/50338) +* \[[`6885fc9386`](https://github.com/nodejs/node/commit/6885fc9386)] - **deps**: update ada to 2.6.10 (Node.js GitHub Bot) [#49984](https://github.com/nodejs/node/pull/49984) +* \[[`76c5f4039f`](https://github.com/nodejs/node/commit/76c5f4039f)] - **deps**: update ada to 2.6.9 (Node.js GitHub Bot) [#49340](https://github.com/nodejs/node/pull/49340) +* \[[`597ea77422`](https://github.com/nodejs/node/commit/597ea77422)] - **deps**: update ada to 2.6.8 (Node.js GitHub Bot) [#49340](https://github.com/nodejs/node/pull/49340) +* \[[`8e7dcba553`](https://github.com/nodejs/node/commit/8e7dcba553)] - **deps**: update ada to 2.6.7 (Node.js GitHub Bot) [#49340](https://github.com/nodejs/node/pull/49340) +* \[[`9f2037e8ee`](https://github.com/nodejs/node/commit/9f2037e8ee)] - **deps**: update ada to 2.6.5 (Node.js GitHub Bot) [#49340](https://github.com/nodejs/node/pull/49340) +* \[[`4723976703`](https://github.com/nodejs/node/commit/4723976703)] - **deps**: update ada to 2.6.3 (Node.js GitHub Bot) [#49340](https://github.com/nodejs/node/pull/49340) +* \[[`7ccb478664`](https://github.com/nodejs/node/commit/7ccb478664)] - **deps**: update undici to 5.26.4 (Node.js GitHub Bot) [#50274](https://github.com/nodejs/node/pull/50274) +* \[[`88f9ebb770`](https://github.com/nodejs/node/commit/88f9ebb770)] - **diagnostics\_channel**: fix ref counting bug when reaching zero subscribers (Stephen Belanger) [#47520](https://github.com/nodejs/node/pull/47520) +* \[[`284a869540`](https://github.com/nodejs/node/commit/284a869540)] - **dns**: call `ada::idna::to_ascii` directly from c++ (Yagiz Nizipli) [#47920](https://github.com/nodejs/node/pull/47920) +* \[[`10968370b5`](https://github.com/nodejs/node/commit/10968370b5)] - **doc**: drop github actions check in sec release process (Rafael Gonzaga) [#48978](https://github.com/nodejs/node/pull/48978) +* \[[`07c3b88c74`](https://github.com/nodejs/node/commit/07c3b88c74)] - **doc**: remove `@anonrig` from performance initiative (Yagiz Nizipli) [#49641](https://github.com/nodejs/node/pull/49641) +* \[[`e26b89e8be`](https://github.com/nodejs/node/commit/e26b89e8be)] - **doc**: fix node-api call example (Chengzhong Wu) [#49395](https://github.com/nodejs/node/pull/49395) +* \[[`4c93905f6c`](https://github.com/nodejs/node/commit/4c93905f6c)] - **doc**: add news issue for Diagnostics WG (Michael Dawson) [#49306](https://github.com/nodejs/node/pull/49306) +* \[[`3f1a237a8f`](https://github.com/nodejs/node/commit/3f1a237a8f)] - **doc**: add print results for examples in `StringDecoder` (Jungku Lee) [#49326](https://github.com/nodejs/node/pull/49326) +* \[[`45caad82bb`](https://github.com/nodejs/node/commit/45caad82bb)] - **doc**: update outdated reference to NIST SP 800-131A (Tobias Nießen) [#49316](https://github.com/nodejs/node/pull/49316) +* \[[`62f823d5a2`](https://github.com/nodejs/node/commit/62f823d5a2)] - **doc**: use `cjs` as block code's type in `MockTimers` (Deokjin Kim) [#49309](https://github.com/nodejs/node/pull/49309) +* \[[`0dda724d3f`](https://github.com/nodejs/node/commit/0dda724d3f)] - **doc**: update `options.filter` description for `fs.cp` (Shubham Pandey) [#49289](https://github.com/nodejs/node/pull/49289) +* \[[`4ba11e352b`](https://github.com/nodejs/node/commit/4ba11e352b)] - **doc**: avoid "not currently recommended" (Tobias Nießen) [#49300](https://github.com/nodejs/node/pull/49300) +* \[[`9ca85b58b3`](https://github.com/nodejs/node/commit/9ca85b58b3)] - **doc**: modify param description for end(),write() in `StringDecoder` (Jungku Lee) [#49285](https://github.com/nodejs/node/pull/49285) +* \[[`3f771cab67`](https://github.com/nodejs/node/commit/3f771cab67)] - **doc**: use NODE\_API\_SUPPORTED\_VERSION\_MAX in release doc (Cheng Zhao) [#49268](https://github.com/nodejs/node/pull/49268) +* \[[`f181c37e75`](https://github.com/nodejs/node/commit/f181c37e75)] - **doc**: fix typo in `stream.finished` documentation (Antoine du Hamel) [#49271](https://github.com/nodejs/node/pull/49271) +* \[[`c70945ddc2`](https://github.com/nodejs/node/commit/c70945ddc2)] - **doc**: update description for `percent_encode` sets in `WHATWG API` (Jungku Lee) [#49258](https://github.com/nodejs/node/pull/49258) +* \[[`f9c2a3fb3e`](https://github.com/nodejs/node/commit/f9c2a3fb3e)] - **doc**: clarify use of Uint8Array for n-api (Fedor Indutny) [#48742](https://github.com/nodejs/node/pull/48742) +* \[[`bf22a5f66e`](https://github.com/nodejs/node/commit/bf22a5f66e)] - **doc**: use same name in the doc as in the code (Hyunjin Kim) [#49216](https://github.com/nodejs/node/pull/49216) +* \[[`72bd527fb6`](https://github.com/nodejs/node/commit/72bd527fb6)] - **doc**: add notable-change label mention to PR template (Rafael Gonzaga) [#49188](https://github.com/nodejs/node/pull/49188) +* \[[`2247e52fe0`](https://github.com/nodejs/node/commit/2247e52fe0)] - **doc**: add h1 summary to security release process (Rafael Gonzaga) [#49112](https://github.com/nodejs/node/pull/49112) +* \[[`3b82e9aed1`](https://github.com/nodejs/node/commit/3b82e9aed1)] - **doc**: fix wording in napi\_async\_init (Tobias Nießen) [#49180](https://github.com/nodejs/node/pull/49180) +* \[[`55171d88a0`](https://github.com/nodejs/node/commit/55171d88a0)] - **doc**: fix `Type` notation in webstreams (Deokjin Kim) [#49121](https://github.com/nodejs/node/pull/49121) +* \[[`79c0497398`](https://github.com/nodejs/node/commit/79c0497398)] - **doc**: make the NODE\_VERSION\_IS\_RELEASE revert clear (Rafael Gonzaga) [#49114](https://github.com/nodejs/node/pull/49114) +* \[[`7ee26fb8df`](https://github.com/nodejs/node/commit/7ee26fb8df)] - **doc**: update with latest security release (Rafael Gonzaga) [#49085](https://github.com/nodejs/node/pull/49085) +* \[[`9ce73964be`](https://github.com/nodejs/node/commit/9ce73964be)] - **doc**: add description for `--port` flag of `node inspect` (Michael Bianco) [#48785](https://github.com/nodejs/node/pull/48785) +* \[[`633b8cd181`](https://github.com/nodejs/node/commit/633b8cd181)] - **doc**: add missing period (Rich Trott) [#49094](https://github.com/nodejs/node/pull/49094) +* \[[`6daa9ec2a4`](https://github.com/nodejs/node/commit/6daa9ec2a4)] - **doc**: add ESM examples in http.md (btea) [#47763](https://github.com/nodejs/node/pull/47763) +* \[[`12b83e81b9`](https://github.com/nodejs/node/commit/12b83e81b9)] - **doc**: detailed description of keystrokes Ctrl-Y and Meta-Y (Ray) [#43529](https://github.com/nodejs/node/pull/43529) +* \[[`ead654f976`](https://github.com/nodejs/node/commit/ead654f976)] - **doc**: clarify use of process.env in worker threads on Windows (Daeyeon Jeong) [#49008](https://github.com/nodejs/node/pull/49008) +* \[[`4047947838`](https://github.com/nodejs/node/commit/4047947838)] - **doc**: remove v14 mention (Rafael Gonzaga) [#49005](https://github.com/nodejs/node/pull/49005) +* \[[`833c643eb4`](https://github.com/nodejs/node/commit/833c643eb4)] - **doc**: run license-builder (github-actions\[bot]) [#48898](https://github.com/nodejs/node/pull/48898) +* \[[`cb43717c97`](https://github.com/nodejs/node/commit/cb43717c97)] - **doc**: add ver of 18.x where Node-api 9 is supported (Michael Dawson) [#48876](https://github.com/nodejs/node/pull/48876) +* \[[`a8d5c16a2a`](https://github.com/nodejs/node/commit/a8d5c16a2a)] - **doc**: include experimental features assessment (Rafael Gonzaga) [#48824](https://github.com/nodejs/node/pull/48824) +* \[[`e6d8735e2b`](https://github.com/nodejs/node/commit/e6d8735e2b)] - **doc**: add new TSC members (Michael Dawson) [#48841](https://github.com/nodejs/node/pull/48841) +* \[[`d4fe00d0c7`](https://github.com/nodejs/node/commit/d4fe00d0c7)] - **doc**: refactor node-api support matrix (Michael Dawson) [#48774](https://github.com/nodejs/node/pull/48774) +* \[[`629132d84c`](https://github.com/nodejs/node/commit/629132d84c)] - **doc**: declare `path` on example of `async_hooks.executionAsyncId()` (Deokjin Kim) [#48556](https://github.com/nodejs/node/pull/48556) +* \[[`dfd368ac9f`](https://github.com/nodejs/node/commit/dfd368ac9f)] - **doc**: remove the . in the end to reduce confusing (Jason) [#48719](https://github.com/nodejs/node/pull/48719) +* \[[`74d8f96413`](https://github.com/nodejs/node/commit/74d8f96413)] - **doc**: nodejs-social over nodejs/tweet (Rafael Gonzaga) [#48769](https://github.com/nodejs/node/pull/48769) +* \[[`73a7e00d06`](https://github.com/nodejs/node/commit/73a7e00d06)] - **doc**: add missing history info for `import.meta.resolve` (Antoine du Hamel) [#49700](https://github.com/nodejs/node/pull/49700) +* \[[`c20fdb4e52`](https://github.com/nodejs/node/commit/c20fdb4e52)] - **doc**: edit `import.meta.resolve` documentation (Antoine du Hamel) [#49247](https://github.com/nodejs/node/pull/49247) +* \[[`1ac389ecef`](https://github.com/nodejs/node/commit/1ac389ecef)] - **doc**: update module hooks docs (Geoffrey Booth) [#49265](https://github.com/nodejs/node/pull/49265) +* \[[`ed2d46f4cc`](https://github.com/nodejs/node/commit/ed2d46f4cc)] - **doc**: move and rename loaders section (Geoffrey Booth) [#49261](https://github.com/nodejs/node/pull/49261) +* \[[`258df0e72d`](https://github.com/nodejs/node/commit/258df0e72d)] - **doc**: add signature for `module.register` (Geoffrey Booth) [#49251](https://github.com/nodejs/node/pull/49251) +* \[[`58eaf3f6ae`](https://github.com/nodejs/node/commit/58eaf3f6ae)] - **doc**: caveat unavailability of `import.meta.resolve` in custom loaders (Jacob Smith) [#49242](https://github.com/nodejs/node/pull/49242) +* \[[`2fef28b2b9`](https://github.com/nodejs/node/commit/2fef28b2b9)] - **doc**: fix name of the flag in `initialize()` docs (Antoine du Hamel) [#49158](https://github.com/nodejs/node/pull/49158) +* \[[`15280fb42c`](https://github.com/nodejs/node/commit/15280fb42c)] - **doc**: add steps about signing the binary in single-executable docs (Darshan Sen) [#46764](https://github.com/nodejs/node/pull/46764) +* \[[`e374ba296c`](https://github.com/nodejs/node/commit/e374ba296c)] - **doc**: add "type" to test runner event details (Phil Nash) [#49014](https://github.com/nodejs/node/pull/49014) +* \[[`ec0a6c1f1b`](https://github.com/nodejs/node/commit/ec0a6c1f1b)] - **doc**: add new reporter events to custom reporter examples (Chemi Atlow) [#48903](https://github.com/nodejs/node/pull/48903) +* \[[`e8a32fb49b`](https://github.com/nodejs/node/commit/e8a32fb49b)] - **doc**: change duration to duration\_ms on test documentation (Ardi\_Nugraha) [#48892](https://github.com/nodejs/node/pull/48892) +* \[[`2b30c8b8a3`](https://github.com/nodejs/node/commit/2b30c8b8a3)] - **doc**: fix `globalPreload` example (bmacnaughton) [#50300](https://github.com/nodejs/node/pull/50300) +* \[[`8a57182769`](https://github.com/nodejs/node/commit/8a57182769)] - **doc,test**: extend the list of platforms supported by single-executables (Darshan Sen) [#47026](https://github.com/nodejs/node/pull/47026) +* \[[`92734d4480`](https://github.com/nodejs/node/commit/92734d4480)] - **esm**: use import attributes instead of import assertions (Antoine du Hamel) [#50140](https://github.com/nodejs/node/pull/50140) +* \[[`c3c945e654`](https://github.com/nodejs/node/commit/c3c945e654)] - **esm**: bypass CommonJS loader under --default-type (Geoffrey Booth) [#49986](https://github.com/nodejs/node/pull/49986) +* \[[`fe691984b2`](https://github.com/nodejs/node/commit/fe691984b2)] - **esm**: unflag extensionless javascript and wasm in module scope (Geoffrey Booth) [#49974](https://github.com/nodejs/node/pull/49974) +* \[[`56bd9a88ac`](https://github.com/nodejs/node/commit/56bd9a88ac)] - **esm**: --experimental-default-type flag to flip module defaults (Geoffrey Booth) [#49869](https://github.com/nodejs/node/pull/49869) +* \[[`72644d62e7`](https://github.com/nodejs/node/commit/72644d62e7)] - **esm**: improve JSDoc annotation of internal functions (Antoine du Hamel) [#49959](https://github.com/nodejs/node/pull/49959) +* \[[`957725f601`](https://github.com/nodejs/node/commit/957725f601)] - **esm**: require braces for modules code (Geoffrey Booth) [#49657](https://github.com/nodejs/node/pull/49657) +* \[[`c12685f82d`](https://github.com/nodejs/node/commit/c12685f82d)] - **esm**: fix cache collision on JSON files using file: URL (Antoine du Hamel) [#49887](https://github.com/nodejs/node/pull/49887) +* \[[`ed8dd33493`](https://github.com/nodejs/node/commit/ed8dd33493)] - **esm**: identify parent importing a url with invalid host (Jacob Smith) [#49736](https://github.com/nodejs/node/pull/49736) +* \[[`46d730ab75`](https://github.com/nodejs/node/commit/46d730ab75)] - **esm**: fix return type of `import.meta.resolve` (Antoine du Hamel) [#49698](https://github.com/nodejs/node/pull/49698) +* \[[`12cb700478`](https://github.com/nodejs/node/commit/12cb700478)] - **esm**: update loaders warning (Geoffrey Booth) [#49633](https://github.com/nodejs/node/pull/49633) +* \[[`47193a347e`](https://github.com/nodejs/node/commit/47193a347e)] - **esm**: fix support for `URL` instances in `register` (Antoine du Hamel) [#49655](https://github.com/nodejs/node/pull/49655) +* \[[`51ced0f1a1`](https://github.com/nodejs/node/commit/51ced0f1a1)] - **esm**: clarify ERR\_REQUIRE\_ESM errors (Daniel Compton) [#49521](https://github.com/nodejs/node/pull/49521) +* \[[`4be5612bae`](https://github.com/nodejs/node/commit/4be5612bae)] - **esm**: remove return value for `Module.register` (Antoine du Hamel) [#49529](https://github.com/nodejs/node/pull/49529) +* \[[`0875867e27`](https://github.com/nodejs/node/commit/0875867e27)] - **esm**: refactor test-esm-loader-resolve-type (Geoffrey Booth) [#49493](https://github.com/nodejs/node/pull/49493) +* \[[`9b7c9d93e9`](https://github.com/nodejs/node/commit/9b7c9d93e9)] - **esm**: refactor test-esm-named-exports (Geoffrey Booth) [#49493](https://github.com/nodejs/node/pull/49493) +* \[[`d1f5514917`](https://github.com/nodejs/node/commit/d1f5514917)] - **esm**: refactor mocking test (Geoffrey Booth) [#49465](https://github.com/nodejs/node/pull/49465) +* \[[`01ca6d277d`](https://github.com/nodejs/node/commit/01ca6d277d)] - **esm**: fix `globalPreload` warning (Antoine du Hamel) [#49069](https://github.com/nodejs/node/pull/49069) +* \[[`c1a84398b4`](https://github.com/nodejs/node/commit/c1a84398b4)] - **esm**: unflag import.meta.resolve (Guy Bedford) [#49028](https://github.com/nodejs/node/pull/49028) +* \[[`ef43f084e9`](https://github.com/nodejs/node/commit/ef43f084e9)] - **esm**: import.meta.resolve exact module not found errors should return (Guy Bedford) [#49038](https://github.com/nodejs/node/pull/49038) +* \[[`385f24c9cc`](https://github.com/nodejs/node/commit/385f24c9cc)] - **esm**: protect `ERR_UNSUPPORTED_DIR_IMPORT` against prototype pollution (Antoine du Hamel) [#49060](https://github.com/nodejs/node/pull/49060) +* \[[`10e7c3a376`](https://github.com/nodejs/node/commit/10e7c3a376)] - **esm**: add `initialize` hook, integrate with `register` (Izaak Schroeder) [#48842](https://github.com/nodejs/node/pull/48842) +* \[[`f96b610268`](https://github.com/nodejs/node/commit/f96b610268)] - **esm**: fix typo `parentUrl` -> `parentURL` (Antoine du Hamel) [#48999](https://github.com/nodejs/node/pull/48999) +* \[[`03c1b5e647`](https://github.com/nodejs/node/commit/03c1b5e647)] - **esm**: unflag `Module.register` and allow nested loader `import()` (Izaak Schroeder) [#48559](https://github.com/nodejs/node/pull/48559) +* \[[`63aa5d7270`](https://github.com/nodejs/node/commit/63aa5d7270)] - **esm**: add back `globalPreload` tests and fix failing ones (Antoine du Hamel) [#48779](https://github.com/nodejs/node/pull/48779) +* \[[`1c7be606f1`](https://github.com/nodejs/node/commit/1c7be606f1)] - **esm**: remove support for arrays in `import` internal method (Antoine du Hamel) [#48296](https://github.com/nodejs/node/pull/48296) +* \[[`655111fa00`](https://github.com/nodejs/node/commit/655111fa00)] - **esm**: handle `globalPreload` hook returning a nullish value (Antoine du Hamel) [#48249](https://github.com/nodejs/node/pull/48249) +* \[[`9938a8bf13`](https://github.com/nodejs/node/commit/9938a8bf13)] - **esm**: handle more error types thrown from the loader thread (Antoine du Hamel) [#48247](https://github.com/nodejs/node/pull/48247) +* \[[`8cab32a5d1`](https://github.com/nodejs/node/commit/8cab32a5d1)] - **esm**: do not use `'beforeExit'` on the main thread (Antoine du Hamel) [#47964](https://github.com/nodejs/node/pull/47964) +* \[[`b61efcce95`](https://github.com/nodejs/node/commit/b61efcce95)] - **esm**: rename `URLCanParse` to be consistent (Antoine du Hamel) [#47668](https://github.com/nodejs/node/pull/47668) +* \[[`ca20f5931d`](https://github.com/nodejs/node/commit/ca20f5931d)] - **esm**: remove support for deprecated hooks (Antoine du Hamel) [#47580](https://github.com/nodejs/node/pull/47580) +* \[[`5de37a1e37`](https://github.com/nodejs/node/commit/5de37a1e37)] - **esm**: initialize `import.meta` on eval (Antoine du Hamel) [#47551](https://github.com/nodejs/node/pull/47551) +* \[[`39fbce7313`](https://github.com/nodejs/node/commit/39fbce7313)] - **esm**: propagate `process.exit` from the loader thread to the main thread (Antoine du Hamel) [#47548](https://github.com/nodejs/node/pull/47548) +* \[[`2a528b76e6`](https://github.com/nodejs/node/commit/2a528b76e6)] - **esm**: avoid try/catch when validating urls (Yagiz Nizipli) [#47541](https://github.com/nodejs/node/pull/47541) +* \[[`bac9b1758f`](https://github.com/nodejs/node/commit/bac9b1758f)] - **esm**: move hook execution to separate thread (Jacob Smith) [#44710](https://github.com/nodejs/node/pull/44710) +* \[[`dfa444477a`](https://github.com/nodejs/node/commit/dfa444477a)] - **esm**: skip file: URL conversion to path when possible (Antoine du Hamel) [#46305](https://github.com/nodejs/node/pull/46305) +* \[[`45de8d1bd7`](https://github.com/nodejs/node/commit/45de8d1bd7)] - **esm**: allow resolve to return import assertions (Geoffrey Booth) [#46153](https://github.com/nodejs/node/pull/46153) +* \[[`5ffc90a06b`](https://github.com/nodejs/node/commit/5ffc90a06b)] - **esm**: move hooks handling into separate class (Geoffrey Booth) [#45869](https://github.com/nodejs/node/pull/45869) +* \[[`490b598dbf`](https://github.com/nodejs/node/commit/490b598dbf)] - **esm**: leverage loaders when resolving subsequent loaders (Maël Nison) [#43772](https://github.com/nodejs/node/pull/43772) +* \[[`acd987287c`](https://github.com/nodejs/node/commit/acd987287c)] - **events**: remove weak listener for event target (Raz Luvaton) [#48952](https://github.com/nodejs/node/pull/48952) +* \[[`69b7f91a92`](https://github.com/nodejs/node/commit/69b7f91a92)] - **fs**: remove redundant code in readableWebStream() (Deokjin Kim) [#49298](https://github.com/nodejs/node/pull/49298) +* \[[`ae8bb162b4`](https://github.com/nodejs/node/commit/ae8bb162b4)] - **fs**: remove redundant `nullCheck` (Livia Medeiros) [#48826](https://github.com/nodejs/node/pull/48826) +* \[[`48c25b154b`](https://github.com/nodejs/node/commit/48c25b154b)] - **fs**: make `mkdtemp` accept buffers and URL (LiviaMedeiros) [#48828](https://github.com/nodejs/node/pull/48828) +* \[[`edf46c1b59`](https://github.com/nodejs/node/commit/edf46c1b59)] - **fs**: move fs\_use\_promises\_symbol to per-isolate symbols (Joyee Cheung) [#47768](https://github.com/nodejs/node/pull/47768) +* \[[`fe41d22afc`](https://github.com/nodejs/node/commit/fe41d22afc)] - **fs**: use kResistStopPropagation (Chemi Atlow) [#48521](https://github.com/nodejs/node/pull/48521) +* \[[`7c758f60ab`](https://github.com/nodejs/node/commit/7c758f60ab)] - **fs**: fix readdir recursive sync & callback (Ethan Arrowood) [#48698](https://github.com/nodejs/node/pull/48698) +* \[[`8874b2e11d`](https://github.com/nodejs/node/commit/8874b2e11d)] - **http**: start connections checking interval on listen (Paolo Insogna) [#48611](https://github.com/nodejs/node/pull/48611) +* \[[`29697229b6`](https://github.com/nodejs/node/commit/29697229b6)] - **https**: fix connection checking interval not clearing on server close (Nitzan Uziely) [#48383](https://github.com/nodejs/node/pull/48383) +* \[[`981aa7866d`](https://github.com/nodejs/node/commit/981aa7866d)] - **lib**: fix MIME overmatch in data URLs (André Alves) [#49104](https://github.com/nodejs/node/pull/49104) +* \[[`fe26f8a860`](https://github.com/nodejs/node/commit/fe26f8a860)] - **lib**: merge cjs and esm package json reader caches (Yagiz Nizipli) [#48477](https://github.com/nodejs/node/pull/48477) +* \[[`17246be158`](https://github.com/nodejs/node/commit/17246be158)] - **(SEMVER-MINOR)** **lib**: add api to detect whether source-maps are enabled (翠 / green) [#46391](https://github.com/nodejs/node/pull/46391) +* \[[`2e9f7284a1`](https://github.com/nodejs/node/commit/2e9f7284a1)] - **(SEMVER-MINOR)** **lib**: add tracing channel to diagnostics\_channel (Stephen Belanger) [#44943](https://github.com/nodejs/node/pull/44943) +* \[[`04dad9c2f6`](https://github.com/nodejs/node/commit/04dad9c2f6)] - **lib**: fix BroadcastChannel initialization location (Shelley Vohr) [#46864](https://github.com/nodejs/node/pull/46864) +* \[[`671d2c0067`](https://github.com/nodejs/node/commit/671d2c0067)] - **lib**: fix DOMException property descriptors after being lazy loaded (Filip Skokan) [#46799](https://github.com/nodejs/node/pull/46799) +* \[[`9a4b57d6d4`](https://github.com/nodejs/node/commit/9a4b57d6d4)] - **lib**: improve esm resolve performance (Yagiz Nizipli) [#46652](https://github.com/nodejs/node/pull/46652) +* \[[`c6b2f56723`](https://github.com/nodejs/node/commit/c6b2f56723)] - **lib**: lazy-load deps in modules/run\_main.js (Joyee Cheung) [#45849](https://github.com/nodejs/node/pull/45849) +* \[[`baa280a4f6`](https://github.com/nodejs/node/commit/baa280a4f6)] - **lib**: lazy-load deps in source\_map\_cache.js (Joyee Cheung) [#45849](https://github.com/nodejs/node/pull/45849) +* \[[`00bdb72b6e`](https://github.com/nodejs/node/commit/00bdb72b6e)] - **lib**: add getLazy() method to internal/util (Joyee Cheung) [#45849](https://github.com/nodejs/node/pull/45849) +* \[[`b77a6b2376`](https://github.com/nodejs/node/commit/b77a6b2376)] - **loader**: use default loader as cascaded loader in the in loader worker (Joyee Cheung) [#47620](https://github.com/nodejs/node/pull/47620) +* \[[`7778e190b0`](https://github.com/nodejs/node/commit/7778e190b0)] - **meta**: move Trott to TSC regular member (Rich Trott) [#50297](https://github.com/nodejs/node/pull/50297) +* \[[`5b9575dd30`](https://github.com/nodejs/node/commit/5b9575dd30)] - **meta**: ping TSC for offboarding (Tobias Nießen) [#50147](https://github.com/nodejs/node/pull/50147) +* \[[`d24c3a0692`](https://github.com/nodejs/node/commit/d24c3a0692)] - **meta**: update website team with new name (Rich Trott) [#49883](https://github.com/nodejs/node/pull/49883) +* \[[`332d2aedb4`](https://github.com/nodejs/node/commit/332d2aedb4)] - **meta**: fix linter error (Antoine du Hamel) [#49755](https://github.com/nodejs/node/pull/49755) +* \[[`dc70c444f4`](https://github.com/nodejs/node/commit/dc70c444f4)] - **meta**: add primordials strategic initiative (Benjamin Gruenbaum) [#49706](https://github.com/nodejs/node/pull/49706) +* \[[`213a9f8a4b`](https://github.com/nodejs/node/commit/213a9f8a4b)] - **meta**: bump rtCamp/action-slack-notify from 2.2.0 to 2.2.1 (dependabot\[bot]) [#49437](https://github.com/nodejs/node/pull/49437) +* \[[`2827779faa`](https://github.com/nodejs/node/commit/2827779faa)] - **meta**: remove modules team from CODEOWNERS (Benjamin Gruenbaum) [#49412](https://github.com/nodejs/node/pull/49412) +* \[[`5d6daf0d01`](https://github.com/nodejs/node/commit/5d6daf0d01)] - **meta**: add test/reporters to codeowners (Chemi Atlow) [#49186](https://github.com/nodejs/node/pull/49186) +* \[[`dee7dc5d54`](https://github.com/nodejs/node/commit/dee7dc5d54)] - **meta**: bump actions/upload-artifact from 3.1.2 to 3.1.3 (dependabot\[bot]) [#50000](https://github.com/nodejs/node/pull/50000) +* \[[`98294fdeee`](https://github.com/nodejs/node/commit/98294fdeee)] - **meta**: bump actions/cache from 3.3.1 to 3.3.2 (dependabot\[bot]) [#50003](https://github.com/nodejs/node/pull/50003) +* \[[`79270327d0`](https://github.com/nodejs/node/commit/79270327d0)] - **meta**: bump github/codeql-action from 2.21.5 to 2.21.9 (dependabot\[bot]) [#50002](https://github.com/nodejs/node/pull/50002) +* \[[`6591a03c89`](https://github.com/nodejs/node/commit/6591a03c89)] - **meta**: bump github/codeql-action from 2.21.2 to 2.21.5 (dependabot\[bot]) [#49438](https://github.com/nodejs/node/pull/49438) +* \[[`3a107f80bc`](https://github.com/nodejs/node/commit/3a107f80bc)] - **meta**: bump actions/checkout from 3.6.0 to 4.1.0 (dependabot\[bot]) [#50001](https://github.com/nodejs/node/pull/50001) +* \[[`26c5c3c4a2`](https://github.com/nodejs/node/commit/26c5c3c4a2)] - **meta**: bump actions/checkout from 3.5.3 to 3.6.0 (dependabot\[bot]) [#49436](https://github.com/nodejs/node/pull/49436) +* \[[`0fc0b88d97`](https://github.com/nodejs/node/commit/0fc0b88d97)] - **meta**: bump step-security/harden-runner from 2.5.0 to 2.5.1 (dependabot\[bot]) [#49435](https://github.com/nodejs/node/pull/49435) +* \[[`dad5785d5d`](https://github.com/nodejs/node/commit/dad5785d5d)] - **meta**: bump actions/setup-node from 3.7.0 to 3.8.1 (dependabot\[bot]) [#49434](https://github.com/nodejs/node/pull/49434) +* \[[`155a275acb`](https://github.com/nodejs/node/commit/155a275acb)] - **meta**: move one or more collaborators to emeritus (Node.js GitHub Bot) [#49264](https://github.com/nodejs/node/pull/49264) +* \[[`bd17f0b992`](https://github.com/nodejs/node/commit/bd17f0b992)] - **meta**: mention nodejs/tsc when changing GH templates (Rafael Gonzaga) [#49189](https://github.com/nodejs/node/pull/49189) +* \[[`f6e68a0238`](https://github.com/nodejs/node/commit/f6e68a0238)] - **meta**: bump github/codeql-action from 2.20.1 to 2.21.2 (dependabot\[bot]) [#48986](https://github.com/nodejs/node/pull/48986) +* \[[`5c352eeecb`](https://github.com/nodejs/node/commit/5c352eeecb)] - **meta**: bump step-security/harden-runner from 2.4.1 to 2.5.0 (dependabot\[bot]) [#48985](https://github.com/nodejs/node/pull/48985) +* \[[`42ac5a6e5f`](https://github.com/nodejs/node/commit/42ac5a6e5f)] - **meta**: bump actions/setup-node from 3.6.0 to 3.7.0 (dependabot\[bot]) [#48984](https://github.com/nodejs/node/pull/48984) +* \[[`b0d769fe7c`](https://github.com/nodejs/node/commit/b0d769fe7c)] - **meta**: bump actions/setup-python from 4.6.1 to 4.7.0 (dependabot\[bot]) [#48983](https://github.com/nodejs/node/pull/48983) +* \[[`f62b24276c`](https://github.com/nodejs/node/commit/f62b24276c)] - **meta**: add mailmap entry for atlowChemi (Chemi Atlow) [#48810](https://github.com/nodejs/node/pull/48810) +* \[[`8c55f317a3`](https://github.com/nodejs/node/commit/8c55f317a3)] - **module**: move helpers out of cjs loader (Geoffrey Booth) [#49912](https://github.com/nodejs/node/pull/49912) +* \[[`14e148ee6c`](https://github.com/nodejs/node/commit/14e148ee6c)] - **module**: ensure successful import returns the same result (Antoine du Hamel) [#46662](https://github.com/nodejs/node/pull/46662) +* \[[`65dfe85f03`](https://github.com/nodejs/node/commit/65dfe85f03)] - **module**: implement `register` utility (João Lenon) [#46826](https://github.com/nodejs/node/pull/46826) +* \[[`6f0458d0a6`](https://github.com/nodejs/node/commit/6f0458d0a6)] - **module**: refactor to use `normalizeRequirableId` in the CJS module loader (Darshan Sen) [#47896](https://github.com/nodejs/node/pull/47896) +* \[[`89ed24b94a`](https://github.com/nodejs/node/commit/89ed24b94a)] - **module**: do less CJS module loader initialization at run time (Joyee Cheung) [#47194](https://github.com/nodejs/node/pull/47194) +* \[[`939c8764b8`](https://github.com/nodejs/node/commit/939c8764b8)] - **module**: move callbacks and conditions into modules/esm/utils.js (Joyee Cheung) [#45849](https://github.com/nodejs/node/pull/45849) +* \[[`a3b0f4cf55`](https://github.com/nodejs/node/commit/a3b0f4cf55)] - **module**: move modules/cjs/helpers.js to modules/helpers.js (Joyee Cheung) [#45849](https://github.com/nodejs/node/pull/45849) +* \[[`97579895f2`](https://github.com/nodejs/node/commit/97579895f2)] - **module, esm**: jsdoc for modules files (Geoffrey Booth) [#49523](https://github.com/nodejs/node/pull/49523) +* \[[`daca87bbef`](https://github.com/nodejs/node/commit/daca87bbef)] - **net**: use asserts in JS Socket Stream to catch races in future (Tim Perry) [#49400](https://github.com/nodejs/node/pull/49400) +* \[[`03063bd022`](https://github.com/nodejs/node/commit/03063bd022)] - **net**: fix crash due to simultaneous close/shutdown on JS Stream Sockets (Tim Perry) [#49400](https://github.com/nodejs/node/pull/49400) +* \[[`67fe7d8822`](https://github.com/nodejs/node/commit/67fe7d8822)] - **net**: fix setting of value in 'setDefaultAutoSelectFamilyAttemptTimeout' (Deokjin Kim) [#47012](https://github.com/nodejs/node/pull/47012) +* \[[`f449b222fd`](https://github.com/nodejs/node/commit/f449b222fd)] - **node-api**: update headers for better wasm support (Toyo Li) [#49037](https://github.com/nodejs/node/pull/49037) +* \[[`5148f030b8`](https://github.com/nodejs/node/commit/5148f030b8)] - **node-api**: run finalizers directly from GC (Vladimir Morozov) [#42651](https://github.com/nodejs/node/pull/42651) +* \[[`edef4fa668`](https://github.com/nodejs/node/commit/edef4fa668)] - **node-api**: enable uncaught exceptions policy by default (Chengzhong Wu) [#49313](https://github.com/nodejs/node/pull/49313) +* \[[`48a1b9336b`](https://github.com/nodejs/node/commit/48a1b9336b)] - **node-api**: fix compiler warning in node\_api.h (Michael Graeb) [#49103](https://github.com/nodejs/node/pull/49103) +* \[[`57966318fe`](https://github.com/nodejs/node/commit/57966318fe)] - **node-api**: avoid macro redefinition (Tobias Nießen) [#48879](https://github.com/nodejs/node/pull/48879) +* \[[`d4f26f4651`](https://github.com/nodejs/node/commit/d4f26f4651)] - **policy**: fix path to URL conversion (Antoine du Hamel) [#49133](https://github.com/nodejs/node/pull/49133) +* \[[`a625f22acb`](https://github.com/nodejs/node/commit/a625f22acb)] - **readline**: add paste bracket mode (Jakub Jankiewicz) [#47150](https://github.com/nodejs/node/pull/47150) +* \[[`bbafd42d75`](https://github.com/nodejs/node/commit/bbafd42d75)] - **repl**: display dynamic import variant in static import error messages (Hemanth HM) [#48129](https://github.com/nodejs/node/pull/48129) +* \[[`b8634eeb16`](https://github.com/nodejs/node/commit/b8634eeb16)] - **sea**: allow requiring core modules with the "node:" prefix (Darshan Sen) [#47779](https://github.com/nodejs/node/pull/47779) +* \[[`066d9d4492`](https://github.com/nodejs/node/commit/066d9d4492)] - **src**: remove unused function `GetName()` in node\_perf (Jungku Lee) [#49244](https://github.com/nodejs/node/pull/49244) +* \[[`158c91a38a`](https://github.com/nodejs/node/commit/158c91a38a)] - **src**: use ARES\_SUCCESS instead of 0 (Jungku Lee) [#49048](https://github.com/nodejs/node/pull/49048) +* \[[`8c33731ac6`](https://github.com/nodejs/node/commit/8c33731ac6)] - **src**: add a condition if the argument of `DomainToUnicode` is empty (Jungku Lee) [#49097](https://github.com/nodejs/node/pull/49097) +* \[[`67dba57d77`](https://github.com/nodejs/node/commit/67dba57d77)] - **src**: use ARES\_SUCCESS instead of 0 (Hyunjin Kim) [#48834](https://github.com/nodejs/node/pull/48834) +* \[[`97d87495c7`](https://github.com/nodejs/node/commit/97d87495c7)] - **src**: remove unnecessary temporary creation (Jason) [#48734](https://github.com/nodejs/node/pull/48734) +* \[[`f5384c3262`](https://github.com/nodejs/node/commit/f5384c3262)] - **src**: fix nullptr access on realm (Jan Olaf Krems) [#48802](https://github.com/nodejs/node/pull/48802) +* \[[`358273d77f`](https://github.com/nodejs/node/commit/358273d77f)] - **src**: remove OnScopeLeaveImpl's move assignment overload (Jason) [#48732](https://github.com/nodejs/node/pull/48732) +* \[[`cc7bf1f641`](https://github.com/nodejs/node/commit/cc7bf1f641)] - **(SEMVER-MINOR)** **src**: add cjs\_module\_lexer\_version base64\_version (Jithil P Ponnan) [#45629](https://github.com/nodejs/node/pull/45629) +* \[[`0a950c3752`](https://github.com/nodejs/node/commit/0a950c3752)] - **src**: add missing to\_ascii method in dns queries (Daniel Lemire) [#48354](https://github.com/nodejs/node/pull/48354) +* \[[`3552afb904`](https://github.com/nodejs/node/commit/3552afb904)] - **src**: fix duplication of externalized builtin code (Keyhan Vakil) [#47079](https://github.com/nodejs/node/pull/47079) +* \[[`66e4ba5062`](https://github.com/nodejs/node/commit/66e4ba5062)] - **src**: fix AliasedBuffer memory attribution in heap snapshots (Joyee Cheung) [#46817](https://github.com/nodejs/node/pull/46817) +* \[[`946f19b5e3`](https://github.com/nodejs/node/commit/946f19b5e3)] - **src**: move AliasedBuffer implementation to -inl.h (Joyee Cheung) [#46817](https://github.com/nodejs/node/pull/46817) +* \[[`d35f8702c9`](https://github.com/nodejs/node/commit/d35f8702c9)] - **src**: bootstrap prepare stack trace callback in shadow realm (Chengzhong Wu) [#47107](https://github.com/nodejs/node/pull/47107) +* \[[`3551a19205`](https://github.com/nodejs/node/commit/3551a19205)] - **src**: make BuiltinLoader threadsafe and non-global (Anna Henningsen) [#45942](https://github.com/nodejs/node/pull/45942) +* \[[`92311a0801`](https://github.com/nodejs/node/commit/92311a0801)] - **src**: define per-isolate internal bindings registration callback (Chengzhong Wu) [#45547](https://github.com/nodejs/node/pull/45547) +* \[[`629fc774ca`](https://github.com/nodejs/node/commit/629fc774ca)] - **src**: use an array for faster binding data lookup (Joyee Cheung) [#46620](https://github.com/nodejs/node/pull/46620) +* \[[`62e2e590fc`](https://github.com/nodejs/node/commit/62e2e590fc)] - **src**: fix TLSWrap lifetime bug in ALPN callback (Ben Noordhuis) [#49635](https://github.com/nodejs/node/pull/49635) +* \[[`fae60c5841`](https://github.com/nodejs/node/commit/fae60c5841)] - **stream**: use bitmap in readable state (Benjamin Gruenbaum) [#49745](https://github.com/nodejs/node/pull/49745) +* \[[`ee4fc7d78c`](https://github.com/nodejs/node/commit/ee4fc7d78c)] - **stream**: use Buffer.from when constructor is a Buffer (Matthew Aitken) [#49250](https://github.com/nodejs/node/pull/49250) +* \[[`651e4504ce`](https://github.com/nodejs/node/commit/651e4504ce)] - **stream**: add `highWaterMark` for the map operator (Raz Luvaton) [#49249](https://github.com/nodejs/node/pull/49249) +* \[[`d585d13127`](https://github.com/nodejs/node/commit/d585d13127)] - **stream**: improve WebStreams performance (Raz Luvaton) [#49089](https://github.com/nodejs/node/pull/49089) +* \[[`7f39f8e805`](https://github.com/nodejs/node/commit/7f39f8e805)] - **test**: replace forEach with for..of in test-http-perf\_hooks.js (Niya Shiyas) [#49818](https://github.com/nodejs/node/pull/49818) +* \[[`2f0ffde842`](https://github.com/nodejs/node/commit/2f0ffde842)] - **test**: replace forEach with for..of in test-net-isipv4.js (Niya Shiyas) [#49822](https://github.com/nodejs/node/pull/49822) +* \[[`bbd302b5ab`](https://github.com/nodejs/node/commit/bbd302b5ab)] - **test**: replace forEach with for..of in test-http2-server (Niya Shiyas) [#49819](https://github.com/nodejs/node/pull/49819) +* \[[`128ca3e213`](https://github.com/nodejs/node/commit/128ca3e213)] - **test**: replace forEach with for..of in test-http2-client-destroy.js (Niya Shiyas) [#49820](https://github.com/nodejs/node/pull/49820) +* \[[`a2ca1a605f`](https://github.com/nodejs/node/commit/a2ca1a605f)] - **test**: print instruction for creating missing snapshot in assertSnapshot (Raz Luvaton) [#48914](https://github.com/nodejs/node/pull/48914) +* \[[`a0bb30cdca`](https://github.com/nodejs/node/commit/a0bb30cdca)] - **test**: set `test-watch-mode-inspect` as flaky (Yagiz Nizipli) [#50259](https://github.com/nodejs/node/pull/50259) +* \[[`1047d95698`](https://github.com/nodejs/node/commit/1047d95698)] - **test**: set `test-emit-after-on-destroyed` as flaky (Yagiz Nizipli) [#50246](https://github.com/nodejs/node/pull/50246) +* \[[`91a3b57962`](https://github.com/nodejs/node/commit/91a3b57962)] - **test**: set inspector async stack test as flaky (Yagiz Nizipli) [#50244](https://github.com/nodejs/node/pull/50244) +* \[[`b41aa7b82a`](https://github.com/nodejs/node/commit/b41aa7b82a)] - **test**: set test-worker-nearheaplimit-deadlock flaky (StefanStojanovic) [#50277](https://github.com/nodejs/node/pull/50277) +* \[[`e81b066fb1`](https://github.com/nodejs/node/commit/e81b066fb1)] - **test**: set `test-cli-node-options` as flaky (Yagiz Nizipli) [#50296](https://github.com/nodejs/node/pull/50296) +* \[[`0c05c25c4e`](https://github.com/nodejs/node/commit/0c05c25c4e)] - **test**: set crypto-timing test as flaky (Yagiz Nizipli) [#50232](https://github.com/nodejs/node/pull/50232) +* \[[`83e339dbba`](https://github.com/nodejs/node/commit/83e339dbba)] - **test**: set `test-structuredclone-*` as flaky (Yagiz Nizipli) [#50261](https://github.com/nodejs/node/pull/50261) +* \[[`866a399488`](https://github.com/nodejs/node/commit/866a399488)] - **test**: set inspector async hook test as flaky (Yagiz Nizipli) [#50252](https://github.com/nodejs/node/pull/50252) +* \[[`cb0bd2116b`](https://github.com/nodejs/node/commit/cb0bd2116b)] - **test**: set parallel http server test as flaky (Yagiz Nizipli) [#50227](https://github.com/nodejs/node/pull/50227) +* \[[`54f3d877ae`](https://github.com/nodejs/node/commit/54f3d877ae)] - **test**: set test-worker-nearheaplimit-deadlock flaky (Stefan Stojanovic) [#50238](https://github.com/nodejs/node/pull/50238) +* \[[`5953a255b6`](https://github.com/nodejs/node/commit/5953a255b6)] - **test**: set `test-runner-watch-mode` as flaky (Yagiz Nizipli) [#50221](https://github.com/nodejs/node/pull/50221) +* \[[`5820d7e14d`](https://github.com/nodejs/node/commit/5820d7e14d)] - **test**: deflake test-runner-output (Moshe Atlow) [#49878](https://github.com/nodejs/node/pull/49878) +* \[[`1d75da43f2`](https://github.com/nodejs/node/commit/1d75da43f2)] - _**Revert**_ "**test**: mark test-http-regr-gh-2928 as flaky" (Luigi Pinca) [#49708](https://github.com/nodejs/node/pull/49708) +* \[[`5df23520e7`](https://github.com/nodejs/node/commit/5df23520e7)] - **test**: mark test-runner-watch-mode as flaky (Joyee Cheung) [#49627](https://github.com/nodejs/node/pull/49627) +* \[[`7e714e6497`](https://github.com/nodejs/node/commit/7e714e6497)] - **test**: remove --no-warnings flag in test\_runner fixtures (Raz Luvaton) [#48989](https://github.com/nodejs/node/pull/48989) +* \[[`0fea550641`](https://github.com/nodejs/node/commit/0fea550641)] - **test**: reorder test files fixtures for better understanding (Raz Luvaton) [#48787](https://github.com/nodejs/node/pull/48787) +* \[[`c5857bde42`](https://github.com/nodejs/node/commit/c5857bde42)] - **test**: avoid copying test source files (Chengzhong Wu) [#49515](https://github.com/nodejs/node/pull/49515) +* \[[`67cb6f9a34`](https://github.com/nodejs/node/commit/67cb6f9a34)] - **test**: reduce length in crypto keygen tests (Joyee Cheung) [#49221](https://github.com/nodejs/node/pull/49221) +* \[[`958e114655`](https://github.com/nodejs/node/commit/958e114655)] - **test**: split JWK async elliptic curve keygen tests (Joyee Cheung) [#49221](https://github.com/nodejs/node/pull/49221) +* \[[`344592dc00`](https://github.com/nodejs/node/commit/344592dc00)] - **test**: split test-crypto-keygen.js (Joyee Cheung) [#49221](https://github.com/nodejs/node/pull/49221) +* \[[`5f1a1aeeed`](https://github.com/nodejs/node/commit/5f1a1aeeed)] - **test**: rename test-crypto-modp1-error (Tobias Nießen) [#49348](https://github.com/nodejs/node/pull/49348) +* \[[`107015b45d`](https://github.com/nodejs/node/commit/107015b45d)] - **test**: migrate message source map tests from Python to JS (Yiyun Lei) [#49238](https://github.com/nodejs/node/pull/49238) +* \[[`ddebd29515`](https://github.com/nodejs/node/commit/ddebd29515)] - **test**: fix compiler warning in NodeCryptoEnv (Tobias Nießen) [#49206](https://github.com/nodejs/node/pull/49206) +* \[[`0261c5de56`](https://github.com/nodejs/node/commit/0261c5de56)] - **test**: make test-perf-hooks more robust and work with workers (Joyee Cheung) [#49197](https://github.com/nodejs/node/pull/49197) +* \[[`e18de802c8`](https://github.com/nodejs/node/commit/e18de802c8)] - **test**: use gcUntil() in test-v8-serialize-leak (Joyee Cheung) [#49168](https://github.com/nodejs/node/pull/49168) +* \[[`52d5dd8dba`](https://github.com/nodejs/node/commit/52d5dd8dba)] - **test**: add expectSyncExitWithoutError() and expectSyncExit() utils (Joyee Cheung) [#49020](https://github.com/nodejs/node/pull/49020) +* \[[`67925bb914`](https://github.com/nodejs/node/commit/67925bb914)] - **test**: add Symbol.dispose support to mock timers (Benjamin Gruenbaum) [#48549](https://github.com/nodejs/node/pull/48549) +* \[[`00c08539b6`](https://github.com/nodejs/node/commit/00c08539b6)] - **test**: fix edge snapshot stack traces (Geoffrey Booth) [#49659](https://github.com/nodejs/node/pull/49659) +* \[[`48f6d9a975`](https://github.com/nodejs/node/commit/48f6d9a975)] - **test**: refactor `test-node-output-errors` (Antoine du Hamel) [#48992](https://github.com/nodejs/node/pull/48992) +* \[[`c1a8ae38c0`](https://github.com/nodejs/node/commit/c1a8ae38c0)] - **test**: deflake `test-loaders-workers-spawned` (Antoine du Hamel) [#50251](https://github.com/nodejs/node/pull/50251) +* \[[`d5cc5d7956`](https://github.com/nodejs/node/commit/d5cc5d7956)] - **test**: deflake `test-esm-loader-resolve-type` (Antoine du Hamel) [#50273](https://github.com/nodejs/node/pull/50273) +* \[[`866d646b0e`](https://github.com/nodejs/node/commit/866d646b0e)] - **test**: increase coverage of `Module.register` and `initialize` hook (Antoine du Hamel) [#49532](https://github.com/nodejs/node/pull/49532) +* \[[`65201ab36b`](https://github.com/nodejs/node/commit/65201ab36b)] - **test**: isolate `globalPreload` tests (Geoffrey Booth) [#49545](https://github.com/nodejs/node/pull/49545) +* \[[`65058d9a35`](https://github.com/nodejs/node/commit/65058d9a35)] - **test**: add `tmpdir.fileURL()` (Livia Medeiros) [#49040](https://github.com/nodejs/node/pull/49040) +* \[[`e1c6f46926`](https://github.com/nodejs/node/commit/e1c6f46926)] - **test**: reduce flakiness of `test-esm-loader-hooks` (Antoine du Hamel) [#49248](https://github.com/nodejs/node/pull/49248) +* \[[`e8d475ffc4`](https://github.com/nodejs/node/commit/e8d475ffc4)] - **test**: refactor `test-esm-loader-hooks` for easier debugging (Antoine du Hamel) [#49131](https://github.com/nodejs/node/pull/49131) +* \[[`26f01669fc`](https://github.com/nodejs/node/commit/26f01669fc)] - **test**: reduce flakiness of `test-esm-loader-hooks` (Antoine du Hamel) [#49105](https://github.com/nodejs/node/pull/49105) +* \[[`d5a1153970`](https://github.com/nodejs/node/commit/d5a1153970)] - **test**: use `fixtures.fileURL` when appropriate (Antoine du Hamel) [#48990](https://github.com/nodejs/node/pull/48990) +* \[[`3424793013`](https://github.com/nodejs/node/commit/3424793013)] - **test**: fix snapshot tests when cwd contains spaces or backslashes (Antoine du Hamel) [#48959](https://github.com/nodejs/node/pull/48959) +* \[[`a9347a4635`](https://github.com/nodejs/node/commit/a9347a4635)] - **test**: order `common.mjs` in ASCII order (Antoine du Hamel) [#48960](https://github.com/nodejs/node/pull/48960) +* \[[`adb9280d8e`](https://github.com/nodejs/node/commit/adb9280d8e)] - **test**: fix some assumptions in tests (Antoine du Hamel) [#48958](https://github.com/nodejs/node/pull/48958) +* \[[`f02637e805`](https://github.com/nodejs/node/commit/f02637e805)] - **test**: fix `es-module/test-esm-initialization` (Antoine du Hamel) [#48880](https://github.com/nodejs/node/pull/48880) +* \[[`8c918e5e59`](https://github.com/nodejs/node/commit/8c918e5e59)] - **test**: relax version check with shared OpenSSL (Luigi Pinca) [#50505](https://github.com/nodejs/node/pull/50505) +* \[[`c6caf13ad5`](https://github.com/nodejs/node/commit/c6caf13ad5)] - **test**: fix crypto-dh error message for OpenSSL 3.x (Kerem Kat) [#50395](https://github.com/nodejs/node/pull/50395) +* \[[`65b41ebd1f`](https://github.com/nodejs/node/commit/65b41ebd1f)] - **test**: split test-crypto-dh to avoid timeout on slow machines in the CI (Joyee Cheung) [#49492](https://github.com/nodejs/node/pull/49492) +* \[[`7606921e1d`](https://github.com/nodejs/node/commit/7606921e1d)] - **test**: fix testsuite against zlib version 1.3 (Dominique Leuenberger) [#50364](https://github.com/nodejs/node/pull/50364) +* \[[`4f78233254`](https://github.com/nodejs/node/commit/4f78233254)] - **test**: verify tracePromise does not do runStores (Stephen Belanger) [#47349](https://github.com/nodejs/node/pull/47349) +* \[[`cb6ef74cf2`](https://github.com/nodejs/node/commit/cb6ef74cf2)] - **test**: fix IPv6 checks on IBM i (Abdirahim Musse) [#46546](https://github.com/nodejs/node/pull/46546) +* \[[`bcf97ab1b2`](https://github.com/nodejs/node/commit/bcf97ab1b2)] - **test**: fix flaky test-runner-exit-code.js (Colin Ihrig) [#46138](https://github.com/nodejs/node/pull/46138) +* \[[`f0e8ff90eb`](https://github.com/nodejs/node/commit/f0e8ff90eb)] - **test**: use an array for WPT gloablThis initialization scripts (Joyee Cheung) [#46425](https://github.com/nodejs/node/pull/46425) +* \[[`0e0dd1fe90`](https://github.com/nodejs/node/commit/0e0dd1fe90)] - **test**: adapt tests for OpenSSL 3.1 (OttoHollmann) [#47859](https://github.com/nodejs/node/pull/47859) +* \[[`e3ea906988`](https://github.com/nodejs/node/commit/e3ea906988)] - **test**: disambiguate AIX and IBM i (Richard Lau) [#48056](https://github.com/nodejs/node/pull/48056) +* \[[`088460d80c`](https://github.com/nodejs/node/commit/088460d80c)] - **test**: add os setPriority, getPriority test coverage (Wael) [#38771](https://github.com/nodejs/node/pull/38771) +* \[[`b011a498c5`](https://github.com/nodejs/node/commit/b011a498c5)] - **test,benchmark**: use `tmpdir.fileURL()` (Livia Medeiros) [#49138](https://github.com/nodejs/node/pull/49138) +* \[[`54168b7364`](https://github.com/nodejs/node/commit/54168b7364)] - **test\_runner**: add test location for FileTests (Colin Ihrig) [#49999](https://github.com/nodejs/node/pull/49999) +* \[[`1d9c37161d`](https://github.com/nodejs/node/commit/1d9c37161d)] - **test\_runner**: replace spurious if with else (Colin Ihrig) [#49943](https://github.com/nodejs/node/pull/49943) +* \[[`b283ae4238`](https://github.com/nodejs/node/commit/b283ae4238)] - **(SEMVER-MINOR)** **test\_runner**: accept `testOnly` in `run` (Moshe Atlow) [#49753](https://github.com/nodejs/node/pull/49753) +* \[[`103c4a088a`](https://github.com/nodejs/node/commit/103c4a088a)] - **test\_runner**: catch reporter errors (Moshe Atlow) [#49646](https://github.com/nodejs/node/pull/49646) +* \[[`e459598cf2`](https://github.com/nodejs/node/commit/e459598cf2)] - **test\_runner**: fix test runner watch mode when no positional arguments (Moshe Atlow) [#49578](https://github.com/nodejs/node/pull/49578) +* \[[`059b1945d8`](https://github.com/nodejs/node/commit/059b1945d8)] - **(SEMVER-MINOR)** **test\_runner**: add junit reporter (Moshe Atlow) [#49614](https://github.com/nodejs/node/pull/49614) +* \[[`76a35632d3`](https://github.com/nodejs/node/commit/76a35632d3)] - **test\_runner**: add jsdocs to mock.js (Caio Borghi) [#49555](https://github.com/nodejs/node/pull/49555) +* \[[`ba57c24fde`](https://github.com/nodejs/node/commit/ba57c24fde)] - **test\_runner**: fix invalid timer call (Erick Wendel) [#49477](https://github.com/nodejs/node/pull/49477) +* \[[`5949ae016f`](https://github.com/nodejs/node/commit/5949ae016f)] - **test\_runner**: add jsdocs to MockTimers (Erick Wendel) [#49476](https://github.com/nodejs/node/pull/49476) +* \[[`429846f258`](https://github.com/nodejs/node/commit/429846f258)] - **test\_runner**: fix typescript coverage (Moshe Atlow) [#49406](https://github.com/nodejs/node/pull/49406) +* \[[`760c98280e`](https://github.com/nodejs/node/commit/760c98280e)] - **test\_runner**: preserve original property descriptor (Erick Wendel) [#49433](https://github.com/nodejs/node/pull/49433) +* \[[`95cc98e14b`](https://github.com/nodejs/node/commit/95cc98e14b)] - **test\_runner**: expose spec reporter as newable function (Chemi Atlow) [#49184](https://github.com/nodejs/node/pull/49184) +* \[[`d83964031b`](https://github.com/nodejs/node/commit/d83964031b)] - **test\_runner**: reland run global after() hook earlier (Colin Ihrig) [#49116](https://github.com/nodejs/node/pull/49116) +* \[[`d61a505546`](https://github.com/nodejs/node/commit/d61a505546)] - **(SEMVER-MINOR)** **test\_runner**: expose location of tests (Colin Ihrig) [#48975](https://github.com/nodejs/node/pull/48975) +* \[[`00c70e12f7`](https://github.com/nodejs/node/commit/00c70e12f7)] - **test\_runner**: dont set exit code on todo tests (Moshe Atlow) [#48929](https://github.com/nodejs/node/pull/48929) +* \[[`71f7ed728d`](https://github.com/nodejs/node/commit/71f7ed728d)] - **test\_runner**: fix global after not failing the tests (Raz Luvaton) [#48913](https://github.com/nodejs/node/pull/48913) +* \[[`11fbd924ed`](https://github.com/nodejs/node/commit/11fbd924ed)] - **test\_runner**: add support for setImmediate (Erick Wendel) [#49397](https://github.com/nodejs/node/pull/49397) +* \[[`fb64d415be`](https://github.com/nodejs/node/commit/fb64d415be)] - **test\_runner**: fix timeout in \*Each hook failing further tests (Raz Luvaton) [#48925](https://github.com/nodejs/node/pull/48925) +* \[[`67d7faddb2`](https://github.com/nodejs/node/commit/67d7faddb2)] - **test\_runner**: cleanup test timeout abort listener (Raz Luvaton) [#48915](https://github.com/nodejs/node/pull/48915) +* \[[`d217435cd3`](https://github.com/nodejs/node/commit/d217435cd3)] - **test\_runner**: fix todo and only in spec reporter (Moshe Atlow) [#48929](https://github.com/nodejs/node/pull/48929) +* \[[`9f122be15a`](https://github.com/nodejs/node/commit/9f122be15a)] - **test\_runner**: unwrap error message in TAP reporter (Colin Ihrig) [#48942](https://github.com/nodejs/node/pull/48942) +* \[[`3a74316624`](https://github.com/nodejs/node/commit/3a74316624)] - **test\_runner**: add `__proto__` null (Raz Luvaton) [#48663](https://github.com/nodejs/node/pull/48663) +* \[[`66ea9bdb4d`](https://github.com/nodejs/node/commit/66ea9bdb4d)] - **test\_runner**: fix global before not called when no global test exists (Raz Luvaton) [#48877](https://github.com/nodejs/node/pull/48877) +* \[[`0bd9704018`](https://github.com/nodejs/node/commit/0bd9704018)] - **test\_runner**: use os.availableParallelism() (Colin Ihrig) [#45969](https://github.com/nodejs/node/pull/45969) +* \[[`b55eb2a8d1`](https://github.com/nodejs/node/commit/b55eb2a8d1)] - **(SEMVER-MINOR)** **test\_runner**: add shards support (Raz Luvaton) [#48639](https://github.com/nodejs/node/pull/48639) +* \[[`c2575c8db0`](https://github.com/nodejs/node/commit/c2575c8db0)] - **test\_runner**: fix test\_runner `test:fail` event type (Ethan Arrowood) [#48854](https://github.com/nodejs/node/pull/48854) +* \[[`6b186d41cd`](https://github.com/nodejs/node/commit/6b186d41cd)] - **test\_runner**: fix async callback in describe not awaited (Raz Luvaton) [#48856](https://github.com/nodejs/node/pull/48856) +* \[[`2d4511baab`](https://github.com/nodejs/node/commit/2d4511baab)] - **test\_runner**: call abort on test finish (Raz Luvaton) [#48827](https://github.com/nodejs/node/pull/48827) +* \[[`05e7f28b40`](https://github.com/nodejs/node/commit/05e7f28b40)] - **(SEMVER-MINOR)** **test\_runner**: add initial draft for fakeTimers (Erick Wendel) [#47775](https://github.com/nodejs/node/pull/47775) +* \[[`428301ad27`](https://github.com/nodejs/node/commit/428301ad27)] - **(SEMVER-MINOR)** **test\_runner, cli**: add --test-concurrency flag (Colin Ihrig) [#49996](https://github.com/nodejs/node/pull/49996) +* \[[`4b2e258c76`](https://github.com/nodejs/node/commit/4b2e258c76)] - **test\_runner,test**: fix flaky test-runner-cli-concurrency.js (Colin Ihrig) [#50108](https://github.com/nodejs/node/pull/50108) +* \[[`b5d16cd8f0`](https://github.com/nodejs/node/commit/b5d16cd8f0)] - **(SEMVER-MINOR)** **tls**: add ALPNCallback server option for dynamic ALPN negotiation (Tim Perry) [#45190](https://github.com/nodejs/node/pull/45190) +* \[[`a1c94037ab`](https://github.com/nodejs/node/commit/a1c94037ab)] - **tools**: fix --v8-non-optimized-debug for v18.x (Joyee Cheung) [#50612](https://github.com/nodejs/node/pull/50612) +* \[[`3b65c61f5c`](https://github.com/nodejs/node/commit/3b65c61f5c)] - **tools**: update lint-md-dependencies (Node.js GitHub Bot) [#50083](https://github.com/nodejs/node/pull/50083) +* \[[`07941a3609`](https://github.com/nodejs/node/commit/07941a3609)] - **tools**: update lint-md-dependencies (Node.js GitHub Bot) [#49983](https://github.com/nodejs/node/pull/49983) +* \[[`ad6e7a6270`](https://github.com/nodejs/node/commit/ad6e7a6270)] - **tools**: update lint-md-dependencies to rollup\@3.29.2 (Node.js GitHub Bot) [#49679](https://github.com/nodejs/node/pull/49679) +* \[[`3511b13c94`](https://github.com/nodejs/node/commit/3511b13c94)] - **tools**: update lint-md-dependencies to rollup\@3.29.0 unified\@11.0.3 (Node.js GitHub Bot) [#49584](https://github.com/nodejs/node/pull/49584) +* \[[`b6522a2b6b`](https://github.com/nodejs/node/commit/b6522a2b6b)] - **tools**: update lint-md-dependencies (Node.js GitHub Bot) [#49342](https://github.com/nodejs/node/pull/49342) +* \[[`01b2588acf`](https://github.com/nodejs/node/commit/01b2588acf)] - **tools**: update lint-md-dependencies (Node.js GitHub Bot) [#49253](https://github.com/nodejs/node/pull/49253) +* \[[`0cb42ccb5c`](https://github.com/nodejs/node/commit/0cb42ccb5c)] - **tools**: update lint-md-dependencies (Node.js GitHub Bot) [#49122](https://github.com/nodejs/node/pull/49122) +* \[[`caa7ecca30`](https://github.com/nodejs/node/commit/caa7ecca30)] - **tools**: update lint-md-dependencies to rollup\@3.27.2 (Node.js GitHub Bot) [#49035](https://github.com/nodejs/node/pull/49035) +* \[[`42846a02b3`](https://github.com/nodejs/node/commit/42846a02b3)] - **tools**: limit the number of auto start CIs (Antoine du Hamel) [#49067](https://github.com/nodejs/node/pull/49067) +* \[[`9cc3b2061f`](https://github.com/nodejs/node/commit/9cc3b2061f)] - **tools**: update lint-md-dependencies to rollup\@3.27.0 (Node.js GitHub Bot) [#48965](https://github.com/nodejs/node/pull/48965) +* \[[`1cbb186039`](https://github.com/nodejs/node/commit/1cbb186039)] - **tools**: update lint-md-dependencies to rollup\@3.26.3 (Node.js GitHub Bot) [#48888](https://github.com/nodejs/node/pull/48888) +* \[[`f7d6e9ba43`](https://github.com/nodejs/node/commit/f7d6e9ba43)] - **tools**: update lint-md-dependencies to @rollup/plugin-commonjs\@25.0.3 (Node.js GitHub Bot) [#48791](https://github.com/nodejs/node/pull/48791) +* \[[`a98addb626`](https://github.com/nodejs/node/commit/a98addb626)] - **tools**: skip ruff on tools/node\_modules (Moshe Atlow) [#49838](https://github.com/nodejs/node/pull/49838) +* \[[`6cf8dd95d1`](https://github.com/nodejs/node/commit/6cf8dd95d1)] - **tools**: update eslint to 8.51.0 (Node.js GitHub Bot) [#50084](https://github.com/nodejs/node/pull/50084) +* \[[`b8d2a29ff5`](https://github.com/nodejs/node/commit/b8d2a29ff5)] - **tools**: update eslint to 8.50.0 (Node.js GitHub Bot) [#49989](https://github.com/nodejs/node/pull/49989) +* \[[`1c1cbf06f0`](https://github.com/nodejs/node/commit/1c1cbf06f0)] - **tools**: update eslint to 8.49.0 (Node.js GitHub Bot) [#49586](https://github.com/nodejs/node/pull/49586) +* \[[`92d21864c5`](https://github.com/nodejs/node/commit/92d21864c5)] - **tools**: update eslint to 8.48.0 (Node.js GitHub Bot) [#49343](https://github.com/nodejs/node/pull/49343) +* \[[`0940de36ee`](https://github.com/nodejs/node/commit/0940de36ee)] - **tools**: update eslint to 8.47.0 (Node.js GitHub Bot) [#49124](https://github.com/nodejs/node/pull/49124) +* \[[`4880a05fa2`](https://github.com/nodejs/node/commit/4880a05fa2)] - **tools**: update eslint to 8.46.0 (Node.js GitHub Bot) [#48966](https://github.com/nodejs/node/pull/48966) +* \[[`e9632454cd`](https://github.com/nodejs/node/commit/e9632454cd)] - **tools**: update eslint to 8.45.0 (Node.js GitHub Bot) [#48793](https://github.com/nodejs/node/pull/48793) +* \[[`ae49f319c4`](https://github.com/nodejs/node/commit/ae49f319c4)] - **tools**: drop support for osx notarization with gon (Ulises Gascón) [#50291](https://github.com/nodejs/node/pull/50291) +* \[[`014b65e9b7`](https://github.com/nodejs/node/commit/014b65e9b7)] - **tools**: use osx notarytool for future releases (Ulises Gascon) [#48701](https://github.com/nodejs/node/pull/48701) +* \[[`71c386a25c`](https://github.com/nodejs/node/commit/71c386a25c)] - **typings**: update JSDoc for `cwd` in `child_process` (LiviaMedeiros) [#49029](https://github.com/nodejs/node/pull/49029) +* \[[`4d70a2c344`](https://github.com/nodejs/node/commit/4d70a2c344)] - **typings**: sync JSDoc with the actual implementation (Hyunjin Kim) [#48853](https://github.com/nodejs/node/pull/48853) +* \[[`945609487c`](https://github.com/nodejs/node/commit/945609487c)] - **typings**: fix missing property in `ExportedHooks` (Antoine du Hamel) [#49567](https://github.com/nodejs/node/pull/49567) +* \[[`2ef80f12b9`](https://github.com/nodejs/node/commit/2ef80f12b9)] - **typings**: fix JSDoc in ESM loader modules (Antoine du Hamel) [#48424](https://github.com/nodejs/node/pull/48424) +* \[[`7fc15b6d42`](https://github.com/nodejs/node/commit/7fc15b6d42)] - **url**: fix `isURL` detection by checking `path` (Zhuo Zhang) [#48928](https://github.com/nodejs/node/pull/48928) +* \[[`916a63b124`](https://github.com/nodejs/node/commit/916a63b124)] - **url**: improve `isURL` detection (Yagiz Nizipli) [#47886](https://github.com/nodejs/node/pull/47886) +* \[[`ac27431372`](https://github.com/nodejs/node/commit/ac27431372)] - **url**: validate `pathToFileURL(path)` argument as string (LiviaMedeiros) [#49161](https://github.com/nodejs/node/pull/49161) +* \[[`f256b160bf`](https://github.com/nodejs/node/commit/f256b160bf)] - **url**: handle unicode hostname if empty (Yagiz Nizipli) [#49396](https://github.com/nodejs/node/pull/49396) +* \[[`2441415c68`](https://github.com/nodejs/node/commit/2441415c68)] - **url**: reduce `pathToFileURL` cpp calls (Yagiz Nizipli) [#48709](https://github.com/nodejs/node/pull/48709) +* \[[`227e749888`](https://github.com/nodejs/node/commit/227e749888)] - **url**: validate URL constructor arg length (Matthew Aitken) [#47513](https://github.com/nodejs/node/pull/47513) +* \[[`bf4ee17d18`](https://github.com/nodejs/node/commit/bf4ee17d18)] - **url**: validate argument length in canParse (Matthew Aitken) [#47513](https://github.com/nodejs/node/pull/47513) +* \[[`a67fa2a107`](https://github.com/nodejs/node/commit/a67fa2a107)] - **util**: add `getCwdSafe` internal util fn (João Lenon) [#48434](https://github.com/nodejs/node/pull/48434) +* \[[`e96f7ef881`](https://github.com/nodejs/node/commit/e96f7ef881)] - **(SEMVER-MINOR)** **vm**: use import attributes instead of import assertions (Antoine du Hamel) [#50141](https://github.com/nodejs/node/pull/50141) +* \[[`525de686a7`](https://github.com/nodejs/node/commit/525de686a7)] - **(SEMVER-MINOR)** **wasi**: updates required for latest uvwasi version (Michael Dawson) [#49908](https://github.com/nodejs/node/pull/49908) +* \[[`f27d505805`](https://github.com/nodejs/node/commit/f27d505805)] - **watch**: decrease debounce rate (Moshe Atlow) [#48926](https://github.com/nodejs/node/pull/48926) +* \[[`83a6d20d70`](https://github.com/nodejs/node/commit/83a6d20d70)] - **watch**: use debounce instead of throttle (Moshe Atlow) [#48926](https://github.com/nodejs/node/pull/48926) +* \[[`879b958184`](https://github.com/nodejs/node/commit/879b958184)] - **worker**: protect against user mutating well-known prototypes (Antoine du Hamel) [#49270](https://github.com/nodejs/node/pull/49270) + ## 2023-10-13, Version 18.18.2 'Hydrogen' (LTS), @RafaelGSS diff --git a/doc/contributing/maintaining/maintaining-dependencies.md b/doc/contributing/maintaining/maintaining-dependencies.md index 245817099e348b..eb0e5960a7c5b8 100644 --- a/doc/contributing/maintaining/maintaining-dependencies.md +++ b/doc/contributing/maintaining/maintaining-dependencies.md @@ -9,13 +9,13 @@ All dependencies are located within the `deps` directory. This a list of all the dependencies: * [acorn][] -* [ada][] +* [ada 2.7.2][] * [base64][] * [brotli][] -* [c-ares][] +* [c-ares 1.20.1][] * [cjs-module-lexer][] * [corepack][] -* [googletest][] +* [googletest 2dd1c13][] * [histogram][] * [icu-small][] * [llhttp][] @@ -25,12 +25,12 @@ This a list of all the dependencies: * [npm][] * [openssl][] * [postject][] -* [simdutf][] -* [undici 5.26.3][] +* [simdutf 3.2.18][] +* [undici 5.26.4][] * [uv][] -* [uvwasi][] +* [uvwasi 0.0.19][] * [V8][] -* [zlib][] +* [zlib 1.2.13.1-motley-fef5869][] Any code which meets one or more of these conditions should be managed as a dependency: @@ -148,7 +148,7 @@ The [acorn](https://github.com/acornjs/acorn) dependency is a JavaScript parser. [acorn-walk](https://github.com/acornjs/acorn/tree/master/acorn-walk) is an abstract syntax tree walker for the ESTree format. -### ada +### ada 2.7.2 The [ada](https://github.com/ada-url/ada) dependency is a fast and spec-compliant URL parser written in C++. @@ -165,7 +165,7 @@ length-delimited strings. The [brotli](https://github.com/google/brotli) dependency is used for the homonym generic-purpose lossless compression algorithm. -### c-ares +### c-ares 1.20.1 The [c-ares](https://github.com/c-ares/c-ares) is a C library for asynchronous DNS requests. @@ -187,7 +187,7 @@ In practical terms, Corepack will let you use Yarn and pnpm without having to install them - just like what currently happens with npm, which is shipped by Node.js by default. -### googletest +### googletest 2dd1c13 The [googletest](https://github.com/google/googletest) dependency is Google’s C++ testing and mocking framework. @@ -273,12 +273,12 @@ See [maintaining-openssl][] for more informations. The [postject](https://github.com/nodejs/postject) dependency is used for the [Single Executable strategic initiative](https://github.com/nodejs/single-executable). -### simdutf +### simdutf 3.2.18 The [simdutf](https://github.com/simdutf/simdutf) dependency is a C++ library for fast UTF-8 decoding and encoding. -### undici 5.26.3 +### undici 5.26.4 The [undici](https://github.com/nodejs/undici) dependency is an HTTP/1.1 client, written from scratch for Node.js.. @@ -290,7 +290,7 @@ The [libuv](https://github.com/libuv/libuv) dependency is a multi-platform support library with a focus on asynchronous I/O. It was primarily developed for use by Node.js. -### uvwasi +### uvwasi 0.0.19 The [uvwasi](https://github.com/nodejs/uvwasi) dependency implements the WASI system call API, so that WebAssembly runtimes can easily @@ -304,7 +304,7 @@ See [maintaining-web-assembly][] for more informations. high-performance JavaScript and WebAssembly engine, written in C++. See [maintaining-V8][] for more informations. -### zlib +### zlib 1.2.13.1-motley-fef5869 The [zlib](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/third_party/zlib) dependency lossless data-compression library, @@ -312,14 +312,14 @@ it comes from the Chromium team's zlib fork which incorporated performance improvements not currently available in standard zlib. [acorn]: #acorn -[ada]: #ada +[ada 2.7.2]: #ada-272 [base64]: #base64 [brotli]: #brotli -[c-ares]: #c-ares +[c-ares 1.20.1]: #c-ares-1200 [cjs-module-lexer]: #cjs-module-lexer [corepack]: #corepack [dependency-update-action]: ../../../.github/workflows/tools.yml -[googletest]: #googletest +[googletest 2dd1c13]: #googletest-2dd1c13 [histogram]: #histogram [icu-small]: #icu-small [llhttp]: #llhttp @@ -335,10 +335,10 @@ performance improvements not currently available in standard zlib. [npm]: #npm [openssl]: #openssl [postject]: #postject -[simdutf]: #simdutf -[undici 5.26.3]: #undici-5263 +[simdutf 3.2.18]: #simdutf-3218 +[undici 5.26.4]: #undici-5264 [update-openssl-action]: ../../../.github/workflows/update-openssl.yml [uv]: #uv -[uvwasi]: #uvwasi +[uvwasi 0.0.19]: #uvwasi-0019 [v8]: #v8 -[zlib]: #zlib +[zlib 1.2.13.1-motley-fef5869]: #zlib-12131-motley-fef5869 diff --git a/doc/contributing/maintaining/maintaining-openssl.md b/doc/contributing/maintaining/maintaining-openssl.md index 8d640c90f38c2d..afa22ac7dfb65e 100644 --- a/doc/contributing/maintaining/maintaining-openssl.md +++ b/doc/contributing/maintaining/maintaining-openssl.md @@ -13,8 +13,6 @@ currently need to generate four PRs as follows: of this guide. * a PR for 16.x following the instructions in the v16.x-staging version of this guide. -* a PR for 14.x following the instructions in the [v14.x-staging version][] - of this guide. ## Use of the quictls/openssl fork @@ -158,4 +156,3 @@ regenerated and committed by: Finally, build Node.js and run the tests. [update-openssl-action]: ../../../.github/workflows/update-openssl.yml -[v14.x-staging version]: https://github.com/nodejs/node/blob/v14.x-staging/doc/guides/maintaining-openssl.md diff --git a/doc/contributing/maintaining/maintaining-single-executable-application-support.md b/doc/contributing/maintaining/maintaining-single-executable-application-support.md index e3957230f3001e..51cafb5ae6fb4b 100644 --- a/doc/contributing/maintaining/maintaining-single-executable-application-support.md +++ b/doc/contributing/maintaining/maintaining-single-executable-application-support.md @@ -54,7 +54,9 @@ for the following features are in the list of work we'd like to get to: * Running an archive of multiple files. * Embedding [Node.js CLI options][] into the binary. * [XCOFF][] executable format. -* Run tests on Linux architectures/distributions other than AMD64 Ubuntu. +* Run tests on Alpine Linux. +* Run tests on s390x Linux. +* Run tests on ppc64 Linux. ## Disabling single executable application support diff --git a/doc/contributing/releases-node-api.md b/doc/contributing/releases-node-api.md index b5cbb321cc4b74..50f8c3893f4a5c 100644 --- a/doc/contributing/releases-node-api.md +++ b/doc/contributing/releases-node-api.md @@ -9,7 +9,7 @@ release process. * [0. Pre-release steps](#0-pre-release-steps) * [1. Update the main branch](#1-update-the-main-branch) * [2. Create a new branch for the release](#2-create-a-new-branch-for-the-release) - * [3. Update `NAPI_VERSION`](#3-update-napi_version) + * [3. Update `NODE_API_SUPPORTED_VERSION_MAX`](#3-update-node_api_supported_version_max) * [4. Define `addon_context_register_func`](#4-define-addon_context_register_func) * [5. Update version guards](#5-update-version-guards) * [6. Create release commit](#6-create-release-commit) @@ -55,13 +55,13 @@ Create a new branch named `node-api-x-proposal`, off the main branch. $ git checkout -b node-api-10-proposal upstream/main ``` -### 3. Update `NAPI_VERSION` +### 3. Update `NODE_API_SUPPORTED_VERSION_MAX` Set the version for the proposed release using the following macros, which are already defined in `src/node_version.h`: ```c -#define NAPI_VERSION x +#define NODE_API_SUPPORTED_VERSION_MAX x ``` > Note: Do not update the `NAPI_VERSION` defined in `src/js_native_api.h`. It diff --git a/doc/contributing/releases.md b/doc/contributing/releases.md index 368a2bda3d594c..accbad73368483 100644 --- a/doc/contributing/releases.md +++ b/doc/contributing/releases.md @@ -813,7 +813,9 @@ $ git commit --amend Even if there are no conflicts, ensure that you revert all the changes that were -made to `src/node_version.h`. +made to `src/node_version.h`. `NODE_VERSION_IS_RELEASE` must be `0`. + +Edit `src/node_version.h`, revert `NODE_VERSION_IS_RELEASE` back to `0`, and `git commit --amend` If there are conflicts in `doc` due to updated `REPLACEME` placeholders (that happens when a change previously landed on another release diff --git a/doc/contributing/security-release-process.md b/doc/contributing/security-release-process.md index 1f54aae33f6cd6..fd33f3ccbb5afd 100644 --- a/doc/contributing/security-release-process.md +++ b/doc/contributing/security-release-process.md @@ -29,7 +29,7 @@ The current security stewards are documented in the main Node.js | NodeSource | Juan | 2022-Nov-04 | | RH and IBM | Michael | 2023-Feb-16 | | NearForm | Rafael | 2023-Jun-20 | -| NearForm | Rafael | | +| NearForm | Rafael | 2023-Aug-09 | | Datadog | Bryan | | | IBM | Joe | | | Platformatic | Matteo | | @@ -56,6 +56,8 @@ The current security stewards are documented in the main Node.js * [ ] pre-release: _**LINK TO PR**_ * [ ] post-release: _**LINK TO PR**_ * List vulnerabilities in order of descending severity + * Use the "summary" feature in HackerOne to sync post-release content + and CVE requests. Example [2038134](https://hackerone.com/bugs?subject=nodejs\&report_id=2038134) * Ask the HackerOne reporter if they would like to be credited on the security release blog page: ```text @@ -70,8 +72,6 @@ The current security stewards are documented in the main Node.js ## Announcement (one week in advance of the planned release) -* [ ] Verify that GitHub Actions are working as normal: . - * [ ] Check that all vulnerabilities are ready for release integration: * PRs against all affected release lines or cherry-pick clean * Approved @@ -81,6 +81,9 @@ The current security stewards are documented in the main Node.js between Security Releases. * Pass `make test` * Have CVEs + * Use the "summary" feature in HackerOne to create a description for the + CVE and the post release announcement. + Example [2038134](https://hackerone.com/bugs?subject=nodejs\&report_id=2038134) * Make sure that dependent libraries have CVEs for their issues. We should only create CVEs for vulnerabilities in Node.js itself. This is to avoid having duplicate CVEs for the same vulnerability. @@ -117,7 +120,7 @@ The google groups UI does not support adding a CC, until we figure out a better way, forward the email you receive to `oss-security@lists.openwall.com` as a CC. -* [ ] Create a new issue in [nodejs/tweet][] +* [ ] Send a message to `#nodejs-social` in OpenJS Foundation slack ```text Security release pre-alert: diff --git a/doc/contributing/sharing-project-news.md b/doc/contributing/sharing-project-news.md index 4630ccdfa18620..270f290e5584f3 100644 --- a/doc/contributing/sharing-project-news.md +++ b/doc/contributing/sharing-project-news.md @@ -31,3 +31,4 @@ that promotes a specific company or commercial interest. * [node-api/node-addon-api](https://github.com/nodejs/abi-stable-node/issues/446). * [uvwasi](https://github.com/nodejs/uvwasi/issues/201). * [security-team](https://github.com/nodejs/security-wg/issues/1006). +* [diagnostics team](https://github.com/nodejs/diagnostics/issues/619). diff --git a/doc/contributing/strategic-initiatives.md b/doc/contributing/strategic-initiatives.md index b005040d54b479..ca4308daa3ebb8 100644 --- a/doc/contributing/strategic-initiatives.md +++ b/doc/contributing/strategic-initiatives.md @@ -6,16 +6,17 @@ agenda to ensure they are active and have the support they need. ## Current initiatives -| Initiative | Champion | Links | -| ---------------------- | --------------------------- | --------------------------------------------- | -| Core Promise APIs | [Antoine du Hamel][aduh95] | | -| QUIC / HTTP3 | [James M Snell][jasnell] | | -| Shadow Realm | [Chengzhong Wu][legendecas] | | -| Startup Snapshot | [Joyee Cheung][joyeecheung] | | -| V8 Currency | [Michaël Zasso][targos] | | -| Next-10 | [Michael Dawson][mhdawson] | | -| Single executable apps | [Darshan Sen][RaisinTen] | | -| Performance | [Yagiz Nizipli][anonrig] | | +| Initiative | Champion | Links | +| ---------------------- | -------------------------------- | ------------------------------------------------- | +| Core Promise APIs | [Antoine du Hamel][aduh95] | | +| QUIC / HTTP3 | [James M Snell][jasnell] | | +| Shadow Realm | [Chengzhong Wu][legendecas] | | +| Startup Snapshot | [Joyee Cheung][joyeecheung] | | +| V8 Currency | [Michaël Zasso][targos] | | +| Next-10 | [Michael Dawson][mhdawson] | | +| Single executable apps | [Darshan Sen][RaisinTen] | | +| Performance | | | +| Primordials | [Benjamin Gruenbaum][benjamingr] | |
List of completed initiatives @@ -40,7 +41,7 @@ agenda to ensure they are active and have the support they need. [RaisinTen]: https://github.com/RaisinTen [aduh95]: https://github.com/aduh95 -[anonrig]: https://github.com/anonrig +[benjamingr]: https://github.com/benjamingr [jasnell]: https://github.com/jasnell [joyeecheung]: https://github.com/joyeecheung [legendecas]: https://github.com/legendecas diff --git a/doc/node.1 b/doc/node.1 index 3f71dde89b55cd..ea2a9dab11ef17 100644 --- a/doc/node.1 +++ b/doc/node.1 @@ -140,6 +140,11 @@ Requires Node.js to be built with .It Fl -enable-source-maps Enable Source Map V3 support for stack traces. . +.It Fl -experimental-default-type Ns = Ns Ar type +Interpret as either ES modules or CommonJS modules input via --eval or STDIN, when --input-type is unspecified; +.js or extensionless files with no sibling or parent package.json; +.js or extensionless files whose nearest parent package.json lacks a "type" field, unless under node_modules. +. .It Fl -experimental-global-customevent Expose the CustomEvent on the global scope. . @@ -395,6 +400,10 @@ Specify the minimum allocation from the OpenSSL secure heap. The default is 2. T .It Fl -test Starts the Node.js command line test runner. . +.It Fl -test-concurrency +The maximum number of test files that the test runner CLI will execute +concurrently. +. .It Fl -test-name-pattern A regular expression that configures the test runner to only execute tests whose name matches the provided pattern. @@ -409,6 +418,9 @@ The destination for the corresponding test reporter. Configures the test runner to only execute top level tests that have the `only` option set. . +.It Fl -test-shard +Test suite shard to execute in a format of /. +. .It Fl -throw-deprecation Throw errors for deprecations. . diff --git a/lib/_http_server.js b/lib/_http_server.js index c010d8fa96a1c2..b16c341b4434c7 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -493,14 +493,21 @@ function storeHTTPOptions(options) { } } -function setupConnectionsTracking(server) { +function setupConnectionsTracking() { // Start connection handling - server[kConnections] = new ConnectionsList(); + if (!this[kConnections]) { + this[kConnections] = new ConnectionsList(); + } // This checker is started without checking whether any headersTimeout or requestTimeout is non zero // otherwise it would not be started if such timeouts are modified after createServer. - server[kConnectionsCheckingInterval] = - setInterval(checkConnections.bind(server), server.connectionsCheckingInterval).unref(); + this[kConnectionsCheckingInterval] = + setInterval(checkConnections.bind(this), this.connectionsCheckingInterval).unref(); +} + +function httpServerPreClose(server) { + server.closeIdleConnections(); + clearInterval(server[kConnectionsCheckingInterval]); } function Server(options, requestListener) { @@ -533,22 +540,27 @@ function Server(options, requestListener) { this.httpAllowHalfOpen = false; this.on('connection', connectionListener); + this.on('listening', setupConnectionsTracking); this.timeout = 0; this.maxHeadersCount = null; this.maxRequestsPerSocket = 0; - setupConnectionsTracking(this); + this[kUniqueHeaders] = parseUniqueHeadersOption(options.uniqueHeaders); } ObjectSetPrototypeOf(Server.prototype, net.Server.prototype); ObjectSetPrototypeOf(Server, net.Server); Server.prototype.close = function() { - clearInterval(this[kConnectionsCheckingInterval]); + httpServerPreClose(this); ReflectApply(net.Server.prototype.close, this, arguments); }; Server.prototype.closeAllConnections = function() { + if (!this[kConnections]) { + return; + } + const connections = this[kConnections].all(); for (let i = 0, l = connections.length; i < l; i++) { @@ -557,6 +569,10 @@ Server.prototype.closeAllConnections = function() { }; Server.prototype.closeIdleConnections = function() { + if (!this[kConnections]) { + return; + } + const connections = this[kConnections].idle(); for (let i = 0, l = connections.length; i < l; i++) { @@ -1179,4 +1195,6 @@ module.exports = { storeHTTPOptions, _connectionListener: connectionListener, kServerResponse, + httpServerPreClose, + kConnectionsCheckingInterval, }; diff --git a/lib/_tls_wrap.js b/lib/_tls_wrap.js index 84599102be4b74..909f36dd00fe15 100644 --- a/lib/_tls_wrap.js +++ b/lib/_tls_wrap.js @@ -72,6 +72,8 @@ const { ERR_INVALID_ARG_VALUE, ERR_MULTIPLE_CALLBACK, ERR_SOCKET_CLOSED, + ERR_TLS_ALPN_CALLBACK_INVALID_RESULT, + ERR_TLS_ALPN_CALLBACK_WITH_PROTOCOLS, ERR_TLS_DH_PARAM_SIZE, ERR_TLS_HANDSHAKE_TIMEOUT, ERR_TLS_INVALID_CONTEXT, @@ -108,6 +110,7 @@ const kErrorEmitted = Symbol('error-emitted'); const kHandshakeTimeout = Symbol('handshake-timeout'); const kRes = Symbol('res'); const kSNICallback = Symbol('snicallback'); +const kALPNCallback = Symbol('alpncallback'); const kEnableTrace = Symbol('enableTrace'); const kPskCallback = Symbol('pskcallback'); const kPskIdentityHint = Symbol('pskidentityhint'); @@ -234,6 +237,45 @@ function loadSNI(info) { } +function callALPNCallback(protocolsBuffer) { + const handle = this; + const socket = handle[owner_symbol]; + + const servername = handle.getServername(); + + // Collect all the protocols from the given buffer: + const protocols = []; + let offset = 0; + while (offset < protocolsBuffer.length) { + const protocolLen = protocolsBuffer[offset]; + offset += 1; + + const protocol = protocolsBuffer.slice(offset, offset + protocolLen); + offset += protocolLen; + + protocols.push(protocol.toString('ascii')); + } + + const selectedProtocol = socket[kALPNCallback]({ + servername, + protocols, + }); + + // Undefined -> all proposed protocols rejected + if (selectedProtocol === undefined) return undefined; + + const protocolIndex = protocols.indexOf(selectedProtocol); + if (protocolIndex === -1) { + throw new ERR_TLS_ALPN_CALLBACK_INVALID_RESULT(selectedProtocol, protocols); + } + let protocolOffset = 0; + for (let i = 0; i < protocolIndex; i++) { + protocolOffset += 1 + protocols[i].length; + } + + return protocolOffset; +} + function requestOCSP(socket, info) { if (!info.OCSPRequest || !socket.server) return requestOCSPDone(socket); @@ -493,6 +535,7 @@ function TLSSocket(socket, opts) { this._controlReleased = false; this.secureConnecting = true; this._SNICallback = null; + this[kALPNCallback] = null; this.servername = null; this.alpnProtocol = null; this.authorized = false; @@ -787,6 +830,16 @@ TLSSocket.prototype._init = function(socket, wrap) { ssl.lastHandshakeTime = 0; ssl.handshakes = 0; + if (options.ALPNCallback) { + if (typeof options.ALPNCallback !== 'function') { + throw new ERR_INVALID_ARG_TYPE('options.ALPNCallback', 'Function', options.ALPNCallback); + } + assert(typeof options.ALPNCallback === 'function'); + this[kALPNCallback] = options.ALPNCallback; + ssl.ALPNCallback = callALPNCallback; + ssl.enableALPNCb(); + } + if (this.server) { if (this.server.listenerCount('resumeSession') > 0 || this.server.listenerCount('newSession') > 0) { @@ -1165,6 +1218,7 @@ function tlsConnectionListener(rawSocket) { rejectUnauthorized: this.rejectUnauthorized, handshakeTimeout: this[kHandshakeTimeout], ALPNProtocols: this.ALPNProtocols, + ALPNCallback: this.ALPNCallback, SNICallback: this[kSNICallback] || SNICallback, enableTrace: this[kEnableTrace], pauseOnConnect: this.pauseOnConnect, @@ -1264,6 +1318,11 @@ function Server(options, listener) { this.requestCert = options.requestCert === true; this.rejectUnauthorized = options.rejectUnauthorized !== false; + this.ALPNCallback = options.ALPNCallback; + if (this.ALPNCallback && options.ALPNProtocols) { + throw new ERR_TLS_ALPN_CALLBACK_WITH_PROTOCOLS(); + } + if (options.sessionTimeout) this.sessionTimeout = options.sessionTimeout; diff --git a/lib/assert.js b/lib/assert.js index 04c2dd3bfcfdfb..c73e750e337fcb 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -65,7 +65,7 @@ const { openSync, closeSync, readSync } = require('fs'); const { inspect } = require('internal/util/inspect'); const { isPromise, isRegExp } = require('internal/util/types'); const { EOL } = require('internal/constants'); -const { BuiltinModule } = require('internal/bootstrap/loaders'); +const { BuiltinModule } = require('internal/bootstrap/realm'); const { isError } = require('internal/util'); const errorCache = new SafeMap(); diff --git a/lib/buffer.js b/lib/buffer.js index 704b0369a53ffd..0c8c185cfbac7c 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -85,6 +85,7 @@ const { lazyDOMException, normalizeEncoding, kIsEncodingSymbol, + defineLazyProperties, } = require('internal/util'); const { isAnyArrayBuffer, @@ -128,15 +129,6 @@ const { createUnsafeBuffer, } = require('internal/buffer'); -const { - Blob, - resolveObjectURL, -} = require('internal/blob'); - -const { - File, -} = require('internal/file'); - FastBuffer.prototype.constructor = Buffer; Buffer.prototype = FastBuffer.prototype; addBufferPrototypeMethods(Buffer.prototype); @@ -1382,9 +1374,6 @@ function isAscii(input) { } module.exports = { - Blob, - File, - resolveObjectURL, Buffer, SlowBuffer, transcode, @@ -1413,3 +1402,14 @@ ObjectDefineProperties(module.exports, { set(val) { INSPECT_MAX_BYTES = val; }, }, }); + +defineLazyProperties( + module.exports, + 'internal/blob', + ['Blob', 'resolveObjectURL'], +); +defineLazyProperties( + module.exports, + 'internal/file', + ['File'], +); diff --git a/lib/child_process.js b/lib/child_process.js index 5bdc474c80169c..449013906e93e5 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -103,7 +103,7 @@ let addAbortListener; * @param {string|URL} modulePath * @param {string[]} [args] * @param {{ - * cwd?: string; + * cwd?: string | URL; * detached?: boolean; * env?: Record; * execPath?: string; @@ -305,7 +305,7 @@ function normalizeExecFileArgs(file, args, options, callback) { * @param {string} file * @param {string[]} [args] * @param {{ - * cwd?: string; + * cwd?: string | URL; * env?: Record; * encoding?: string; * timeout?: number; @@ -733,7 +733,7 @@ function abortChildProcess(child, killSignal, reason) { * @param {string} file * @param {string[]} [args] * @param {{ - * cwd?: string; + * cwd?: string | URL; * env?: Record; * argv0?: string; * stdio?: Array | string; @@ -803,7 +803,7 @@ function spawn(file, args, options) { * @param {string} file * @param {string[]} [args] * @param {{ - * cwd?: string; + * cwd?: string | URL; * input?: string | Buffer | TypedArray | DataView; * argv0?: string; * stdio?: string | Array; @@ -897,7 +897,7 @@ function checkExecSyncError(ret, args, cmd) { * @param {string} file * @param {string[]} [args] * @param {{ - * cwd?: string; + * cwd?: string | URL; * input?: string | Buffer | TypedArray | DataView; * stdio?: string | Array; * env?: Record; @@ -935,7 +935,7 @@ function execFileSync(file, args, options) { * Spawns a shell executing the given `command` synchronously. * @param {string} command * @param {{ - * cwd?: string; + * cwd?: string | URL; * input?: string | Buffer | TypedArray | DataView; * stdio?: string | Array; * env?: Record; diff --git a/lib/diagnostics_channel.js b/lib/diagnostics_channel.js index c20a9bffc8610b..d7558a88cc7e3f 100644 --- a/lib/diagnostics_channel.js +++ b/lib/diagnostics_channel.js @@ -4,9 +4,15 @@ const { ArrayPrototypeIndexOf, ArrayPrototypePush, ArrayPrototypeSplice, - ObjectCreate, + SafeFinalizationRegistry, ObjectGetPrototypeOf, ObjectSetPrototypeOf, + Promise, + PromisePrototypeThen, + PromiseResolve, + PromiseReject, + ReflectApply, + SafeMap, SymbolHasInstance, } = primordials; @@ -23,11 +29,74 @@ const { triggerUncaughtException } = internalBinding('errors'); const { WeakReference } = internalBinding('util'); +// Can't delete when weakref count reaches 0 as it could increment again. +// Only GC can be used as a valid time to clean up the channels map. +class WeakRefMap extends SafeMap { + #finalizers = new SafeFinalizationRegistry((key) => { + this.delete(key); + }); + + set(key, value) { + this.#finalizers.register(value, key); + return super.set(key, new WeakReference(value)); + } + + get(key) { + return super.get(key)?.get(); + } + + incRef(key) { + return super.get(key)?.incRef(); + } + + decRef(key) { + return super.get(key)?.decRef(); + } +} + +function markActive(channel) { + // eslint-disable-next-line no-use-before-define + ObjectSetPrototypeOf(channel, ActiveChannel.prototype); + channel._subscribers = []; + channel._stores = new SafeMap(); +} + +function maybeMarkInactive(channel) { + // When there are no more active subscribers or bound, restore to fast prototype. + if (!channel._subscribers.length && !channel._stores.size) { + // eslint-disable-next-line no-use-before-define + ObjectSetPrototypeOf(channel, Channel.prototype); + channel._subscribers = undefined; + channel._stores = undefined; + } +} + +function defaultTransform(data) { + return data; +} + +function wrapStoreRun(store, data, next, transform = defaultTransform) { + return () => { + let context; + try { + context = transform(data); + } catch (err) { + process.nextTick(() => { + triggerUncaughtException(err, false); + }); + return next(); + } + + return store.run(context, next); + }; +} + // TODO(qard): should there be a C++ channel interface? class ActiveChannel { subscribe(subscription) { validateFunction(subscription, 'subscription'); ArrayPrototypePush(this._subscribers, subscription); + channels.incRef(this.name); } unsubscribe(subscription) { @@ -36,12 +105,28 @@ class ActiveChannel { ArrayPrototypeSplice(this._subscribers, index, 1); - // When there are no more active subscribers, restore to fast prototype. - if (!this._subscribers.length) { - // eslint-disable-next-line no-use-before-define - ObjectSetPrototypeOf(this, Channel.prototype); + channels.decRef(this.name); + maybeMarkInactive(this); + + return true; + } + + bindStore(store, transform) { + const replacing = this._stores.has(store); + if (!replacing) channels.incRef(this.name); + this._stores.set(store, transform); + } + + unbindStore(store) { + if (!this._stores.has(store)) { + return false; } + this._stores.delete(store); + + channels.decRef(this.name); + maybeMarkInactive(this); + return true; } @@ -61,12 +146,30 @@ class ActiveChannel { } } } + + runStores(data, fn, thisArg, ...args) { + let run = () => { + this.publish(data); + return ReflectApply(fn, thisArg, args); + }; + + for (const entry of this._stores.entries()) { + const store = entry[0]; + const transform = entry[1]; + run = wrapStoreRun(store, data, run, transform); + } + + return run(); + } } class Channel { constructor(name) { this._subscribers = undefined; + this._stores = undefined; this.name = name; + + channels.set(name, this); } static [SymbolHasInstance](instance) { @@ -76,8 +179,7 @@ class Channel { } subscribe(subscription) { - ObjectSetPrototypeOf(this, ActiveChannel.prototype); - this._subscribers = []; + markActive(this); this.subscribe(subscription); } @@ -85,64 +187,227 @@ class Channel { return false; } + bindStore(store, transform) { + markActive(this); + this.bindStore(store, transform); + } + + unbindStore() { + return false; + } + get hasSubscribers() { return false; } publish() {} + + runStores(data, fn, thisArg, ...args) { + return ReflectApply(fn, thisArg, args); + } } -const channels = ObjectCreate(null); +const channels = new WeakRefMap(); function channel(name) { - let channel; - const ref = channels[name]; - if (ref) channel = ref.get(); + const channel = channels.get(name); if (channel) return channel; if (typeof name !== 'string' && typeof name !== 'symbol') { throw new ERR_INVALID_ARG_TYPE('channel', ['string', 'symbol'], name); } - channel = new Channel(name); - channels[name] = new WeakReference(channel); - return channel; + return new Channel(name); } function subscribe(name, subscription) { - const chan = channel(name); - channels[name].incRef(); - chan.subscribe(subscription); + return channel(name).subscribe(subscription); } function unsubscribe(name, subscription) { - const chan = channel(name); - if (!chan.unsubscribe(subscription)) { - return false; - } + return channel(name).unsubscribe(subscription); +} + +function hasSubscribers(name) { + const channel = channels.get(name); + if (!channel) return false; - channels[name].decRef(); - if (channels[name].getRef() === 0) { - delete channels[name]; + return channel.hasSubscribers; +} + +const traceEvents = [ + 'start', + 'end', + 'asyncStart', + 'asyncEnd', + 'error', +]; + +function assertChannel(value, name) { + if (!(value instanceof Channel)) { + throw new ERR_INVALID_ARG_TYPE(name, ['Channel'], value); } - return true; } -function hasSubscribers(name) { - let channel; - const ref = channels[name]; - if (ref) channel = ref.get(); - if (!channel) { - return false; +class TracingChannel { + constructor(nameOrChannels) { + if (typeof nameOrChannels === 'string') { + this.start = channel(`tracing:${nameOrChannels}:start`); + this.end = channel(`tracing:${nameOrChannels}:end`); + this.asyncStart = channel(`tracing:${nameOrChannels}:asyncStart`); + this.asyncEnd = channel(`tracing:${nameOrChannels}:asyncEnd`); + this.error = channel(`tracing:${nameOrChannels}:error`); + } else if (typeof nameOrChannels === 'object') { + const { start, end, asyncStart, asyncEnd, error } = nameOrChannels; + + assertChannel(start, 'nameOrChannels.start'); + assertChannel(end, 'nameOrChannels.end'); + assertChannel(asyncStart, 'nameOrChannels.asyncStart'); + assertChannel(asyncEnd, 'nameOrChannels.asyncEnd'); + assertChannel(error, 'nameOrChannels.error'); + + this.start = start; + this.end = end; + this.asyncStart = asyncStart; + this.asyncEnd = asyncEnd; + this.error = error; + } else { + throw new ERR_INVALID_ARG_TYPE('nameOrChannels', + ['string', 'object', 'Channel'], + nameOrChannels); + } } - return channel.hasSubscribers; + subscribe(handlers) { + for (const name of traceEvents) { + if (!handlers[name]) continue; + + this[name]?.subscribe(handlers[name]); + } + } + + unsubscribe(handlers) { + let done = true; + + for (const name of traceEvents) { + if (!handlers[name]) continue; + + if (!this[name]?.unsubscribe(handlers[name])) { + done = false; + } + } + + return done; + } + + traceSync(fn, context = {}, thisArg, ...args) { + const { start, end, error } = this; + + return start.runStores(context, () => { + try { + const result = ReflectApply(fn, thisArg, args); + context.result = result; + return result; + } catch (err) { + context.error = err; + error.publish(context); + throw err; + } finally { + end.publish(context); + } + }); + } + + tracePromise(fn, context = {}, thisArg, ...args) { + const { start, end, asyncStart, asyncEnd, error } = this; + + function reject(err) { + context.error = err; + error.publish(context); + asyncStart.publish(context); + // TODO: Is there a way to have asyncEnd _after_ the continuation? + asyncEnd.publish(context); + return PromiseReject(err); + } + + function resolve(result) { + context.result = result; + asyncStart.publish(context); + // TODO: Is there a way to have asyncEnd _after_ the continuation? + asyncEnd.publish(context); + return result; + } + + return start.runStores(context, () => { + try { + let promise = ReflectApply(fn, thisArg, args); + // Convert thenables to native promises + if (!(promise instanceof Promise)) { + promise = PromiseResolve(promise); + } + return PromisePrototypeThen(promise, resolve, reject); + } catch (err) { + context.error = err; + error.publish(context); + throw err; + } finally { + end.publish(context); + } + }); + } + + traceCallback(fn, position = -1, context = {}, thisArg, ...args) { + const { start, end, asyncStart, asyncEnd, error } = this; + + function wrappedCallback(err, res) { + if (err) { + context.error = err; + error.publish(context); + } else { + context.result = res; + } + + // Using runStores here enables manual context failure recovery + asyncStart.runStores(context, () => { + try { + if (callback) { + return ReflectApply(callback, this, arguments); + } + } finally { + asyncEnd.publish(context); + } + }); + } + + const callback = args.at(position); + if (typeof callback !== 'function') { + throw new ERR_INVALID_ARG_TYPE('callback', ['function'], callback); + } + ArrayPrototypeSplice(args, position, 1, wrappedCallback); + + return start.runStores(context, () => { + try { + return ReflectApply(fn, thisArg, args); + } catch (err) { + context.error = err; + error.publish(context); + throw err; + } finally { + end.publish(context); + } + }); + } +} + +function tracingChannel(nameOrChannels) { + return new TracingChannel(nameOrChannels); } module.exports = { channel, hasSubscribers, subscribe, + tracingChannel, unsubscribe, Channel, }; diff --git a/lib/dns.js b/lib/dns.js index ae0e14bab3097d..ca932ad05f4da7 100644 --- a/lib/dns.js +++ b/lib/dns.js @@ -28,7 +28,6 @@ const { } = primordials; const cares = internalBinding('cares_wrap'); -const { toASCII } = require('internal/idna'); const { isIP } = require('internal/net'); const { customPromisifyArgs } = require('internal/util'); const errors = require('internal/errors'); @@ -220,7 +219,7 @@ function lookup(hostname, options, callback) { req.oncomplete = all ? onlookupall : onlookup; const err = cares.getaddrinfo( - req, toASCII(hostname), family, hints, verbatim, + req, hostname, family, hints, verbatim, ); if (err) { process.nextTick(callback, dnsException(err, 'getaddrinfo', hostname)); diff --git a/lib/fs.js b/lib/fs.js index 1f695f6b08540a..55e6373327c846 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -87,6 +87,7 @@ const { custom: kCustomPromisifiedSymbol, }, SideEffectFreeRegExpPrototypeExec, + defineLazyProperties, } = require('internal/util'); const { constants: { @@ -103,7 +104,6 @@ const { getValidatedPath, getValidMode, handleErrorFromBinding, - nullCheck, preprocessSymlinkDestination, Stats, getStatFsFromBinding, @@ -125,11 +125,6 @@ const { validatePrimitiveStringAfterArrayBufferView, warnOnNonPortableTemplate, } = require('internal/fs/utils'); -const { - Dir, - opendir, - opendirSync, -} = require('internal/fs/dir'); const { CHAR_FORWARD_SLASH, CHAR_BACKWARD_SLASH, @@ -143,12 +138,8 @@ const { validateFunction, validateInteger, validateObject, - validateString, } = require('internal/validators'); -const watchers = require('internal/fs/watchers'); -const ReadFileContext = require('internal/fs/read_file_context'); - let truncateWarn = true; let fs; @@ -160,6 +151,7 @@ let ReadStream; let WriteStream; let rimraf; let rimrafSync; +let kResistStopPropagation; // These have to be separate because of how graceful-fs happens to do it's // monkeypatching. @@ -391,6 +383,7 @@ function checkAborted(signal, callback) { function readFile(path, options, callback) { callback = maybeCallback(callback || options); options = getOptions(options, { flag: 'r' }); + const ReadFileContext = require('internal/fs/read_file_context'); const context = new ReadFileContext(callback, options.encoding); context.isUserFd = isFd(path); // File descriptor ownership @@ -1404,14 +1397,12 @@ function mkdirSync(path, options) { /** * An iterative algorithm for reading the entire contents of the `basePath` directory. * This function does not validate `basePath` as a directory. It is passed directly to - * `binding.readdir` after a `nullCheck`. + * `binding.readdir`. * @param {string} basePath * @param {{ encoding: string, withFileTypes: boolean }} options * @returns {string[] | Dirent[]} */ function readdirSyncRecursive(basePath, options) { - nullCheck(basePath, 'path', true); - const withFileTypes = Boolean(options.withFileTypes); const encoding = options.encoding; @@ -1430,14 +1421,21 @@ function readdirSyncRecursive(basePath, options) { ); handleErrorFromBinding(ctx); - for (let i = 0; i < readdirResult.length; i++) { - if (withFileTypes) { + if (withFileTypes) { + // Calling `readdir` with `withFileTypes=true`, the result is an array of arrays. + // The first array is the names, and the second array is the types. + // They are guaranteed to be the same length; hence, setting `length` to the length + // of the first array within the result. + const length = readdirResult[0].length; + for (let i = 0; i < length; i++) { const dirent = getDirent(path, readdirResult[0][i], readdirResult[1][i]); ArrayPrototypePush(readdirResults, dirent); if (dirent.isDirectory()) { ArrayPrototypePush(pathsQueue, pathModule.join(dirent.path, dirent.name)); } - } else { + } + } else { + for (let i = 0; i < readdirResult.length; i++) { const resultPath = pathModule.join(path, readdirResult[i]); const relativeResultPath = pathModule.relative(basePath, resultPath); const stat = binding.internalModuleStat(resultPath); @@ -2414,12 +2412,13 @@ function watch(filename, options, listener) { if (options.recursive === undefined) options.recursive = false; if (options.recursive && !(isOSX || isWindows)) throw new ERR_FEATURE_UNAVAILABLE_ON_PLATFORM('watch recursively'); + + const watchers = require('internal/fs/watchers'); const watcher = new watchers.FSWatcher(); watcher[watchers.kFSWatchStart](filename, options.persistent, options.recursive, options.encoding); - if (listener) { watcher.addListener('change', listener); } @@ -2428,7 +2427,8 @@ function watch(filename, options, listener) { process.nextTick(() => watcher.close()); } else { const listener = () => watcher.close(); - options.signal.addEventListener('abort', listener); + kResistStopPropagation ??= require('internal/event_target').kResistStopPropagation; + options.signal.addEventListener('abort', listener, { __proto__: null, [kResistStopPropagation]: true }); watcher.once('close', () => { options.signal.removeEventListener('abort', listener); }); @@ -2477,7 +2477,7 @@ function watchFile(filename, options, listener) { validateFunction(listener, 'listener'); stat = statWatchers.get(filename); - + const watchers = require('internal/fs/watchers'); if (stat === undefined) { stat = new watchers.StatWatcher(options.bigint); stat[watchers.kFSStatWatcherStart](filename, @@ -2503,7 +2503,7 @@ function unwatchFile(filename, listener) { const stat = statWatchers.get(filename); if (stat === undefined) return; - + const watchers = require('internal/fs/watchers'); if (typeof listener === 'function') { const beforeListenerCount = stat.listenerCount('change'); stat.removeListener('change', listener); @@ -2880,7 +2880,7 @@ realpath.native = (path, options, callback) => { /** * Creates a unique temporary directory. - * @param {string} prefix + * @param {string | Buffer | URL} prefix * @param {string | { encoding?: string; }} [options] * @param {( * err?: Error, @@ -2892,27 +2892,40 @@ function mkdtemp(prefix, options, callback) { callback = makeCallback(typeof options === 'function' ? options : callback); options = getOptions(options); - validateString(prefix, 'prefix'); - nullCheck(prefix, 'prefix'); + prefix = getValidatedPath(prefix, 'prefix'); warnOnNonPortableTemplate(prefix); + + let path; + if (typeof prefix === 'string') { + path = `${prefix}XXXXXX`; + } else { + path = Buffer.concat([prefix, Buffer.from('XXXXXX')]); + } + const req = new FSReqCallback(); req.oncomplete = callback; - binding.mkdtemp(`${prefix}XXXXXX`, options.encoding, req); + binding.mkdtemp(path, options.encoding, req); } /** * Synchronously creates a unique temporary directory. - * @param {string} prefix + * @param {string | Buffer | URL} prefix * @param {string | { encoding?: string; }} [options] * @returns {string} */ function mkdtempSync(prefix, options) { options = getOptions(options); - validateString(prefix, 'prefix'); - nullCheck(prefix, 'prefix'); + prefix = getValidatedPath(prefix, 'prefix'); warnOnNonPortableTemplate(prefix); - const path = `${prefix}XXXXXX`; + + let path; + if (typeof prefix === 'string') { + path = `${prefix}XXXXXX`; + } else { + path = Buffer.concat([prefix, Buffer.from('XXXXXX')]); + } + const ctx = { path }; const result = binding.mkdtemp(path, options.encoding, undefined, ctx); @@ -3107,8 +3120,6 @@ module.exports = fs = { mkdtempSync, open, openSync, - opendir, - opendirSync, readdir, readdirSync, read, @@ -3148,7 +3159,6 @@ module.exports = fs = { writeSync, writev, writevSync, - Dir, Dirent, Stats, @@ -3194,6 +3204,12 @@ module.exports = fs = { _toUnixTimestamp: toUnixTimestamp, }; +defineLazyProperties( + fs, + 'internal/fs/dir', + ['Dir', 'opendir', 'opendirSync'], +); + ObjectDefineProperties(fs, { F_OK: { __proto__: null, enumerable: true, value: F_OK || 0 }, R_OK: { __proto__: null, enumerable: true, value: R_OK || 0 }, diff --git a/lib/https.js b/lib/https.js index 12453609f2c452..e74dbcf43eb8f9 100644 --- a/lib/https.js +++ b/lib/https.js @@ -31,6 +31,7 @@ const { JSONStringify, ObjectAssign, ObjectSetPrototypeOf, + ReflectApply, ReflectConstruct, } = primordials; @@ -43,6 +44,7 @@ assertCrypto(); const tls = require('tls'); const { Agent: HttpAgent } = require('_http_agent'); const { + httpServerPreClose, Server: HttpServer, setupConnectionsTracking, storeHTTPOptions, @@ -86,8 +88,9 @@ function Server(opts, requestListener) { this.timeout = 0; this.maxHeadersCount = null; - setupConnectionsTracking(this); + this.on('listening', setupConnectionsTracking); } + ObjectSetPrototypeOf(Server.prototype, tls.Server.prototype); ObjectSetPrototypeOf(Server, tls.Server); @@ -97,6 +100,11 @@ Server.prototype.closeIdleConnections = HttpServer.prototype.closeIdleConnection Server.prototype.setTimeout = HttpServer.prototype.setTimeout; +Server.prototype.close = function() { + httpServerPreClose(this); + ReflectApply(tls.Server.prototype.close, this, arguments); +}; + /** * Creates a new `https.Server` instance. * @param {{ diff --git a/lib/internal/async_hooks.js b/lib/internal/async_hooks.js index 9294773fe4126a..ee9094b184f039 100644 --- a/lib/internal/async_hooks.js +++ b/lib/internal/async_hooks.js @@ -8,8 +8,6 @@ const { Symbol, } = primordials; -const promiseHooks = require('internal/promise_hooks'); - const async_wrap = internalBinding('async_wrap'); const { setCallbackTrampoline } = async_wrap; /* async_hook_fields is a Uint32Array wrapping the uint32_t array of @@ -382,6 +380,7 @@ function updatePromiseHookMode() { initHook = destroyTracking; } if (stopPromiseHook) stopPromiseHook(); + const promiseHooks = require('internal/promise_hooks'); stopPromiseHook = promiseHooks.createHook({ init: initHook, before: promiseBeforeHook, diff --git a/lib/internal/bootstrap/browser.js b/lib/internal/bootstrap/browser.js index 5be4dd6176482c..29932e9b5d8ef0 100644 --- a/lib/internal/bootstrap/browser.js +++ b/lib/internal/bootstrap/browser.js @@ -9,6 +9,9 @@ const { defineOperation, exposeInterface, lazyDOMExceptionClass, + defineLazyProperties, + defineReplaceableLazyAttribute, + exposeLazyInterfaces, } = require('internal/util'); const config = internalBinding('config'); @@ -23,42 +26,15 @@ exposeInterface(globalThis, 'URL', URL); exposeInterface(globalThis, 'URLSearchParams', URLSearchParams); exposeGetterAndSetter(globalThis, 'DOMException', - lazyDOMExceptionClass, + () => { + const DOMException = lazyDOMExceptionClass(); + exposeInterface(globalThis, 'DOMException', DOMException); + return DOMException; + }, (value) => { exposeInterface(globalThis, 'DOMException', value); }); -const { - TextEncoder, - TextDecoder, -} = require('internal/encoding'); -// https://encoding.spec.whatwg.org/#textencoder -exposeInterface(globalThis, 'TextEncoder', TextEncoder); -// https://encoding.spec.whatwg.org/#textdecoder -exposeInterface(globalThis, 'TextDecoder', TextDecoder); - -const { - AbortController, - AbortSignal, -} = require('internal/abort_controller'); -exposeInterface(globalThis, 'AbortController', AbortController); -exposeInterface(globalThis, 'AbortSignal', AbortSignal); - -const { - EventTarget, - Event, -} = require('internal/event_target'); -exposeInterface(globalThis, 'EventTarget', EventTarget); -exposeInterface(globalThis, 'Event', Event); -const { - MessageChannel, - MessagePort, - MessageEvent, -} = require('internal/worker/io'); -exposeInterface(globalThis, 'MessageChannel', MessageChannel); -exposeInterface(globalThis, 'MessagePort', MessagePort); -exposeInterface(globalThis, 'MessageEvent', MessageEvent); - // https://html.spec.whatwg.org/multipage/webappapis.html#windoworworkerglobalscope const timers = require('timers'); defineOperation(globalThis, 'clearInterval', timers.clearInterval); @@ -66,18 +42,35 @@ defineOperation(globalThis, 'clearTimeout', timers.clearTimeout); defineOperation(globalThis, 'setInterval', timers.setInterval); defineOperation(globalThis, 'setTimeout', timers.setTimeout); -const buffer = require('buffer'); -defineOperation(globalThis, 'atob', buffer.atob); -defineOperation(globalThis, 'btoa', buffer.btoa); - +// Lazy ones. +exposeLazyInterfaces(globalThis, 'internal/worker/io', ['BroadcastChannel']); +exposeLazyInterfaces(globalThis, 'internal/abort_controller', [ + 'AbortController', 'AbortSignal', +]); +const { + EventTarget, Event, +} = require('internal/event_target'); +exposeInterface(globalThis, 'Event', Event); +exposeInterface(globalThis, 'EventTarget', EventTarget); +exposeLazyInterfaces(globalThis, 'internal/worker/io', [ + 'MessageChannel', 'MessagePort', 'MessageEvent', +]); +defineLazyProperties(globalThis, 'buffer', ['atob', 'btoa']); // https://www.w3.org/TR/FileAPI/#dfn-Blob -exposeInterface(globalThis, 'Blob', buffer.Blob); - +exposeLazyInterfaces(globalThis, 'internal/blob', ['Blob']); // https://www.w3.org/TR/hr-time-2/#the-performance-attribute -const perf_hooks = require('perf_hooks'); -exposeInterface(globalThis, 'Performance', perf_hooks.Performance); -defineReplacableAttribute(globalThis, 'performance', - perf_hooks.performance); + +exposeLazyInterfaces(globalThis, 'perf_hooks', [ + 'Performance', +]); + +defineReplaceableLazyAttribute(globalThis, 'perf_hooks', ['performance']); + +// https://encoding.spec.whatwg.org/#textencoder +// https://encoding.spec.whatwg.org/#textdecoder +exposeLazyInterfaces(globalThis, + 'internal/encoding', + ['TextEncoder', 'TextDecoder']); function createGlobalConsole() { const consoleFromNode = @@ -115,67 +108,43 @@ function exposeGetterAndSetter(target, name, getter, setter = undefined) { }); } -// https://heycam.github.io/webidl/#Replaceable -function defineReplacableAttribute(target, name, value) { - ObjectDefineProperty(target, name, { - __proto__: null, - writable: true, - enumerable: true, - configurable: true, - value, - }); -} - // Web Streams API -const { - TransformStream, - TransformStreamDefaultController, -} = require('internal/webstreams/transformstream'); - -const { - WritableStream, - WritableStreamDefaultController, - WritableStreamDefaultWriter, -} = require('internal/webstreams/writablestream'); +exposeLazyInterfaces( + globalThis, + 'internal/webstreams/transformstream', + ['TransformStream', 'TransformStreamDefaultController']); -const { - ReadableStream, - ReadableStreamDefaultReader, - ReadableStreamBYOBReader, - ReadableStreamBYOBRequest, - ReadableByteStreamController, - ReadableStreamDefaultController, -} = require('internal/webstreams/readablestream'); +exposeLazyInterfaces( + globalThis, + 'internal/webstreams/writablestream', + ['WritableStream', 'WritableStreamDefaultController', 'WritableStreamDefaultWriter']); -const { - ByteLengthQueuingStrategy, - CountQueuingStrategy, -} = require('internal/webstreams/queuingstrategies'); +exposeLazyInterfaces( + globalThis, + 'internal/webstreams/readablestream', + [ + 'ReadableStream', 'ReadableStreamDefaultReader', + 'ReadableStreamBYOBReader', 'ReadableStreamBYOBRequest', + 'ReadableByteStreamController', 'ReadableStreamDefaultController', + ]); + +exposeLazyInterfaces( + globalThis, + 'internal/webstreams/queuingstrategies', + [ + 'ByteLengthQueuingStrategy', 'CountQueuingStrategy', + ]); -const { - TextEncoderStream, - TextDecoderStream, -} = require('internal/webstreams/encoding'); +exposeLazyInterfaces( + globalThis, + 'internal/webstreams/encoding', + [ + 'TextEncoderStream', 'TextDecoderStream', + ]); -const { - CompressionStream, - DecompressionStream, -} = require('internal/webstreams/compression'); - -exposeInterface(globalThis, 'ReadableStream', ReadableStream); -exposeInterface(globalThis, 'ReadableStreamDefaultReader', ReadableStreamDefaultReader); -exposeInterface(globalThis, 'ReadableStreamBYOBReader', ReadableStreamBYOBReader); -exposeInterface(globalThis, 'ReadableStreamBYOBRequest', ReadableStreamBYOBRequest); -exposeInterface(globalThis, 'ReadableByteStreamController', ReadableByteStreamController); -exposeInterface(globalThis, 'ReadableStreamDefaultController', ReadableStreamDefaultController); -exposeInterface(globalThis, 'TransformStream', TransformStream); -exposeInterface(globalThis, 'TransformStreamDefaultController', TransformStreamDefaultController); -exposeInterface(globalThis, 'WritableStream', WritableStream); -exposeInterface(globalThis, 'WritableStreamDefaultWriter', WritableStreamDefaultWriter); -exposeInterface(globalThis, 'WritableStreamDefaultController', WritableStreamDefaultController); -exposeInterface(globalThis, 'ByteLengthQueuingStrategy', ByteLengthQueuingStrategy); -exposeInterface(globalThis, 'CountQueuingStrategy', CountQueuingStrategy); -exposeInterface(globalThis, 'TextEncoderStream', TextEncoderStream); -exposeInterface(globalThis, 'TextDecoderStream', TextDecoderStream); -exposeInterface(globalThis, 'CompressionStream', CompressionStream); -exposeInterface(globalThis, 'DecompressionStream', DecompressionStream); +exposeLazyInterfaces( + globalThis, + 'internal/webstreams/compression', + [ + 'CompressionStream', 'DecompressionStream', + ]); diff --git a/lib/internal/bootstrap/loaders.js b/lib/internal/bootstrap/loaders.js deleted file mode 100644 index 064a735f9a637e..00000000000000 --- a/lib/internal/bootstrap/loaders.js +++ /dev/null @@ -1,382 +0,0 @@ -// This file creates the internal module & binding loaders used by built-in -// modules. In contrast, user land modules are loaded using -// lib/internal/modules/cjs/loader.js (CommonJS Modules) or -// lib/internal/modules/esm/* (ES Modules). -// -// This file is compiled and run by node.cc before bootstrap/node.js -// was called, therefore the loaders are bootstrapped before we start to -// actually bootstrap Node.js. It creates the following objects: -// -// C++ binding loaders: -// - process.binding(): the legacy C++ binding loader, accessible from user land -// because it is an object attached to the global process object. -// These C++ bindings are created using NODE_BUILTIN_MODULE_CONTEXT_AWARE() -// and have their nm_flags set to NM_F_BUILTIN. We do not make any guarantees -// about the stability of these bindings, but still have to take care of -// compatibility issues caused by them from time to time. -// - process._linkedBinding(): intended to be used by embedders to add -// additional C++ bindings in their applications. These C++ bindings -// can be created using NODE_BINDING_CONTEXT_AWARE_CPP() with the flag -// NM_F_LINKED. -// - internalBinding(): the private internal C++ binding loader, inaccessible -// from user land unless through `require('internal/test/binding')`. -// These C++ bindings are created using NODE_BINDING_CONTEXT_AWARE_INTERNAL() -// and have their nm_flags set to NM_F_INTERNAL. -// -// Internal JavaScript module loader: -// - BuiltinModule: a minimal module system used to load the JavaScript core -// modules found in lib/**/*.js and deps/**/*.js. All core modules are -// compiled into the node binary via node_javascript.cc generated by js2c.py, -// so they can be loaded faster without the cost of I/O. This class makes the -// lib/internal/*, deps/internal/* modules and internalBinding() available by -// default to core modules, and lets the core modules require itself via -// require('internal/bootstrap/loaders') even when this file is not written in -// CommonJS style. -// -// Other objects: -// - process.moduleLoadList: an array recording the bindings and the modules -// loaded in the process and the order in which they are loaded. - -'use strict'; - -// This file is compiled as if it's wrapped in a function with arguments -// passed by node::RunBootstrapping() -/* global process, getLinkedBinding, getInternalBinding, primordials */ - -const { - ArrayFrom, - ArrayPrototypeMap, - ArrayPrototypePush, - ArrayPrototypeSlice, - Error, - ObjectCreate, - ObjectDefineProperty, - ObjectKeys, - ObjectPrototypeHasOwnProperty, - ObjectSetPrototypeOf, - ReflectGet, - SafeMap, - SafeSet, - String, - StringPrototypeStartsWith, - StringPrototypeSlice, - TypeError, -} = primordials; - -// Set up process.moduleLoadList. -const moduleLoadList = []; -ObjectDefineProperty(process, 'moduleLoadList', { - __proto__: null, - value: moduleLoadList, - configurable: true, - enumerable: true, - writable: false, -}); - - -// internalBindingAllowlist contains the name of internalBinding modules -// that are allowed for access via process.binding()... This is used -// to provide a transition path for modules that are being moved over to -// internalBinding. -const internalBindingAllowlist = new SafeSet([ - 'async_wrap', - 'buffer', - 'cares_wrap', - 'config', - 'constants', - 'contextify', - 'crypto', - 'fs', - 'fs_event_wrap', - 'http_parser', - 'icu', - 'inspector', - 'js_stream', - 'natives', - 'os', - 'pipe_wrap', - 'process_wrap', - 'signal_wrap', - 'spawn_sync', - 'stream_wrap', - 'tcp_wrap', - 'tls_wrap', - 'tty_wrap', - 'udp_wrap', - 'url', - 'util', - 'uv', - 'v8', - 'zlib', -]); - -const runtimeDeprecatedList = new SafeSet([ - 'async_wrap', - 'crypto', - 'http_parser', - 'signal_wrap', - 'url', - 'v8', -]); - -const legacyWrapperList = new SafeSet([ - 'util', -]); - -// Modules that can only be imported via the node: scheme. -const schemelessBlockList = new SafeSet([ - 'test', - 'test/reporters', -]); - -// Set up process.binding() and process._linkedBinding(). -{ - const bindingObj = ObjectCreate(null); - - process.binding = function binding(module) { - module = String(module); - // Deprecated specific process.binding() modules, but not all, allow - // selective fallback to internalBinding for the deprecated ones. - if (internalBindingAllowlist.has(module)) { - if (runtimeDeprecatedList.has(module)) { - runtimeDeprecatedList.delete(module); - process.emitWarning( - `Access to process.binding('${module}') is deprecated.`, - 'DeprecationWarning', - 'DEP0111'); - } - if (legacyWrapperList.has(module)) { - return requireBuiltin('internal/legacy/processbinding')[module](); - } - return internalBinding(module); - } - // eslint-disable-next-line no-restricted-syntax - throw new Error(`No such module: ${module}`); - }; - - process._linkedBinding = function _linkedBinding(module) { - module = String(module); - let mod = bindingObj[module]; - if (typeof mod !== 'object') - mod = bindingObj[module] = getLinkedBinding(module); - return mod; - }; -} - -// Set up internalBinding() in the closure. -/** - * @type {InternalBinding} - */ -let internalBinding; -{ - const bindingObj = ObjectCreate(null); - // eslint-disable-next-line no-global-assign - internalBinding = function internalBinding(module) { - let mod = bindingObj[module]; - if (typeof mod !== 'object') { - mod = bindingObj[module] = getInternalBinding(module); - ArrayPrototypePush(moduleLoadList, `Internal Binding ${module}`); - } - return mod; - }; -} - -const loaderId = 'internal/bootstrap/loaders'; -const { - builtinIds, - compileFunction, -} = internalBinding('builtins'); - -const getOwn = (target, property, receiver) => { - return ObjectPrototypeHasOwnProperty(target, property) ? - ReflectGet(target, property, receiver) : - undefined; -}; - -/** - * An internal abstraction for the built-in JavaScript modules of Node.js. - * Be careful not to expose this to user land unless --expose-internals is - * used, in which case there is no compatibility guarantee about this class. - */ -class BuiltinModule { - /** - * A map from the module IDs to the module instances. - * @type {Map} - */ - static map = new SafeMap( - ArrayPrototypeMap(builtinIds, (id) => [id, new BuiltinModule(id)]), - ); - - constructor(id) { - this.filename = `${id}.js`; - this.id = id; - this.canBeRequiredByUsers = !StringPrototypeStartsWith(id, 'internal/'); - - // The CJS exports object of the module. - this.exports = {}; - // States used to work around circular dependencies. - this.loaded = false; - this.loading = false; - - // The following properties are used by the ESM implementation and only - // initialized when the built-in module is loaded by users. - /** - * The C++ ModuleWrap binding used to interface with the ESM implementation. - * @type {ModuleWrap|undefined} - */ - this.module = undefined; - /** - * Exported names for the ESM imports. - * @type {string[]|undefined} - */ - this.exportKeys = undefined; - } - - // To be called during pre-execution when --expose-internals is on. - // Enables the user-land module loader to access internal modules. - static exposeInternals() { - for (const { 0: id, 1: mod } of BuiltinModule.map) { - // Do not expose this to user land even with --expose-internals. - if (id !== loaderId) { - mod.canBeRequiredByUsers = true; - } - } - } - - static exists(id) { - return BuiltinModule.map.has(id); - } - - static canBeRequiredByUsers(id) { - const mod = BuiltinModule.map.get(id); - return mod && mod.canBeRequiredByUsers; - } - - // Determine if a core module can be loaded without the node: prefix. This - // function does not validate if the module actually exists. - static canBeRequiredWithoutScheme(id) { - return !schemelessBlockList.has(id); - } - - static getSchemeOnlyModuleNames() { - return ArrayFrom(schemelessBlockList); - } - - // Used by user-land module loaders to compile and load builtins. - compileForPublicLoader() { - if (!this.canBeRequiredByUsers) { - // No code because this is an assertion against bugs - // eslint-disable-next-line no-restricted-syntax - throw new Error(`Should not compile ${this.id} for public use`); - } - this.compileForInternalLoader(); - if (!this.exportKeys) { - // When using --expose-internals, we do not want to reflect the named - // exports from core modules as this can trigger unnecessary getters. - const internal = StringPrototypeStartsWith(this.id, 'internal/'); - this.exportKeys = internal ? [] : ObjectKeys(this.exports); - } - this.getESMFacade(); - this.syncExports(); - return this.exports; - } - - getESMFacade() { - if (this.module) return this.module; - const { ModuleWrap } = internalBinding('module_wrap'); - // TODO(aduh95): move this to C++, alongside the initialization of the class. - ObjectSetPrototypeOf(ModuleWrap.prototype, null); - const url = `node:${this.id}`; - const builtin = this; - const exportsKeys = ArrayPrototypeSlice(this.exportKeys); - ArrayPrototypePush(exportsKeys, 'default'); - this.module = new ModuleWrap( - url, undefined, exportsKeys, - function() { - builtin.syncExports(); - this.setExport('default', builtin.exports); - }); - // Ensure immediate sync execution to capture exports now - this.module.instantiate(); - this.module.evaluate(-1, false); - return this.module; - } - - // Provide named exports for all builtin libraries so that the libraries - // may be imported in a nicer way for ESM users. The default export is left - // as the entire namespace (module.exports) and updates when this function is - // called so that APMs and other behavior are supported. - syncExports() { - const names = this.exportKeys; - if (this.module) { - for (let i = 0; i < names.length; i++) { - const exportName = names[i]; - if (exportName === 'default') continue; - this.module.setExport(exportName, - getOwn(this.exports, exportName, this.exports)); - } - } - } - - compileForInternalLoader() { - if (this.loaded || this.loading) { - return this.exports; - } - - const id = this.id; - this.loading = true; - - try { - const requireFn = StringPrototypeStartsWith(this.id, 'internal/deps/') ? - requireWithFallbackInDeps : requireBuiltin; - - const fn = compileFunction(id); - // Arguments must match the parameters specified in - // BuiltinLoader::LookupAndCompile(). - fn(this.exports, requireFn, this, process, internalBinding, primordials); - - this.loaded = true; - } finally { - this.loading = false; - } - - // "NativeModule" is a legacy name of "BuiltinModule". We keep it - // here to avoid breaking users who parse process.moduleLoadList. - ArrayPrototypePush(moduleLoadList, `NativeModule ${id}`); - return this.exports; - } -} - -// Think of this as module.exports in this file even though it is not -// written in CommonJS style. -const loaderExports = { - internalBinding, - BuiltinModule, - require: requireBuiltin, -}; - -function requireBuiltin(id) { - if (id === loaderId) { - return loaderExports; - } - - const mod = BuiltinModule.map.get(id); - // Can't load the internal errors module from here, have to use a raw error. - // eslint-disable-next-line no-restricted-syntax - if (!mod) throw new TypeError(`Missing internal module '${id}'`); - return mod.compileForInternalLoader(); -} - -// Allow internal modules from dependencies to require -// other modules from dependencies by providing fallbacks. -function requireWithFallbackInDeps(request) { - if (StringPrototypeStartsWith(request, 'node:')) { - request = StringPrototypeSlice(request, 5); - } else if (!BuiltinModule.map.has(request)) { - request = `internal/deps/${request}`; - } - return requireBuiltin(request); -} - -// Pass the exports back to C++ land for C++ internals to use. -return loaderExports; diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js index 07c6d5e9351a96..6200091a59cecc 100644 --- a/lib/internal/bootstrap/node.js +++ b/lib/internal/bootstrap/node.js @@ -1,6 +1,6 @@ // Hello, and welcome to hacking node.js! // -// This file is invoked by `Realm::BootstrapNode()` in `src/node_realm.cc`, +// This file is invoked by `Realm::BootstrapRealm()` in `src/node_realm.cc`, // and is responsible for setting up Node.js core before main scripts // under `lib/internal/main/` are executed. // @@ -32,9 +32,10 @@ // `DOMException` class. // - `lib/internal/per_context/messageport.js`: JS-side components of the // `MessagePort` implementation. -// - `lib/internal/bootstrap/loaders.js`: this sets up internal binding and +// - `lib/internal/bootstrap/realm.js`: this sets up internal binding and // module loaders, including `process.binding()`, `process._linkedBinding()`, -// `internalBinding()` and `BuiltinModule`. +// `internalBinding()` and `BuiltinModule`, and per-realm internal states +// and bindings, including `prepare_stack_trace_callback`. // // The initialization done in this script is included in both the main thread // and the worker threads. After this, further initialization is done based @@ -52,8 +53,6 @@ // passed by `BuiltinLoader::CompileAndCall()`. /* global process, require, internalBinding, primordials */ -setupPrepareStackTrace(); - const { FunctionPrototypeCall, JSONParse, @@ -71,7 +70,7 @@ const internalTimers = require('internal/timers'); const { defineOperation, deprecate, - exposeInterface, + defineLazyProperties, } = require('internal/util'); const { privateSymbols: { @@ -235,19 +234,17 @@ const { } = require('internal/process/task_queues'); // Non-standard extensions: -const { BroadcastChannel } = require('internal/worker/io'); -exposeInterface(globalThis, 'BroadcastChannel', BroadcastChannel); - defineOperation(globalThis, 'queueMicrotask', queueMicrotask); const timers = require('timers'); defineOperation(globalThis, 'clearImmediate', timers.clearImmediate); defineOperation(globalThis, 'setImmediate', timers.setImmediate); -const { - structuredClone, -} = require('internal/structured_clone'); -defineOperation(globalThis, 'structuredClone', structuredClone); +defineLazyProperties( + globalThis, + 'internal/structured_clone', + ['structuredClone'], +); // Set the per-Environment callback that will be called // when the TrackingTraceStateObserver updates trace state. @@ -360,33 +357,29 @@ process.emitWarning = emitWarning; // Note: only after this point are the timers effective } -// Preload modules so that they are included in the builtin snapshot. -require('fs'); -require('v8'); -require('vm'); -require('url'); -require('internal/options'); -if (config.hasOpenSSL) { - require('crypto'); -} - -function setupPrepareStackTrace() { +{ const { - setEnhanceStackForFatalException, - setPrepareStackTraceCallback, - } = internalBinding('errors'); + getSourceMapsEnabled, + setSourceMapsEnabled, + maybeCacheGeneratedSourceMap, + } = require('internal/source_map/source_map_cache'); const { - prepareStackTrace, - fatalExceptionStackEnhancers: { - beforeInspector, - afterInspector, + setMaybeCacheGeneratedSourceMap, + } = internalBinding('errors'); + + ObjectDefineProperty(process, 'sourceMapsEnabled', { + __proto__: null, + enumerable: true, + configurable: true, + get() { + return getSourceMapsEnabled(); }, - } = require('internal/errors'); - // Tell our PrepareStackTraceCallback passed to the V8 API - // to call prepareStackTrace(). - setPrepareStackTraceCallback(prepareStackTrace); - // Set the function used to enhance the error stack for printing - setEnhanceStackForFatalException(beforeInspector, afterInspector); + }); + process.setSourceMapsEnabled = setSourceMapsEnabled; + // The C++ land calls back to maybeCacheGeneratedSourceMap() + // when code is generated by user with eval() or new Function() + // to cache the source maps from the evaluated code, if any. + setMaybeCacheGeneratedSourceMap(maybeCacheGeneratedSourceMap); } function setupProcessObject() { diff --git a/lib/internal/bootstrap/realm.js b/lib/internal/bootstrap/realm.js new file mode 100644 index 00000000000000..81144c280a1f41 --- /dev/null +++ b/lib/internal/bootstrap/realm.js @@ -0,0 +1,458 @@ +// This file is executed in every realm that is created by Node.js, including +// the context of main thread, worker threads, and ShadowRealms. +// Only per-realm internal states and bindings should be bootstrapped in this +// file and no globals should be exposed to the user code. +// +// This file creates the internal module & binding loaders used by built-in +// modules. In contrast, user land modules are loaded using +// lib/internal/modules/cjs/loader.js (CommonJS Modules) or +// lib/internal/modules/esm/* (ES Modules). +// +// This file is compiled and run by node.cc before bootstrap/node.js +// was called, therefore the loaders are bootstrapped before we start to +// actually bootstrap Node.js. It creates the following objects: +// +// C++ binding loaders: +// - process.binding(): the legacy C++ binding loader, accessible from user land +// because it is an object attached to the global process object. +// These C++ bindings are created using NODE_BUILTIN_MODULE_CONTEXT_AWARE() +// and have their nm_flags set to NM_F_BUILTIN. We do not make any guarantees +// about the stability of these bindings, but still have to take care of +// compatibility issues caused by them from time to time. +// - process._linkedBinding(): intended to be used by embedders to add +// additional C++ bindings in their applications. These C++ bindings +// can be created using NODE_BINDING_CONTEXT_AWARE_CPP() with the flag +// NM_F_LINKED. +// - internalBinding(): the private internal C++ binding loader, inaccessible +// from user land unless through `require('internal/test/binding')`. +// These C++ bindings are created using NODE_BINDING_CONTEXT_AWARE_INTERNAL() +// and have their nm_flags set to NM_F_INTERNAL. +// +// Internal JavaScript module loader: +// - BuiltinModule: a minimal module system used to load the JavaScript core +// modules found in lib/**/*.js and deps/**/*.js. All core modules are +// compiled into the node binary via node_javascript.cc generated by js2c.py, +// so they can be loaded faster without the cost of I/O. This class makes the +// lib/internal/*, deps/internal/* modules and internalBinding() available by +// default to core modules, and lets the core modules require itself via +// require('internal/bootstrap/realm') even when this file is not written in +// CommonJS style. +// +// Other objects: +// - process.moduleLoadList: an array recording the bindings and the modules +// loaded in the process and the order in which they are loaded. + +'use strict'; + +// This file is compiled as if it's wrapped in a function with arguments +// passed by node::RunBootstrapping() +/* global process, getLinkedBinding, getInternalBinding, primordials */ + +const { + ArrayFrom, + ArrayPrototypeMap, + ArrayPrototypePush, + ArrayPrototypeSlice, + Error, + ObjectCreate, + ObjectDefineProperty, + ObjectKeys, + ObjectPrototypeHasOwnProperty, + ObjectSetPrototypeOf, + ReflectGet, + SafeMap, + SafeSet, + String, + StringPrototypeSlice, + StringPrototypeStartsWith, + TypeError, +} = primordials; + +// Set up process.moduleLoadList. +const moduleLoadList = []; +ObjectDefineProperty(process, 'moduleLoadList', { + __proto__: null, + value: moduleLoadList, + configurable: true, + enumerable: true, + writable: false, +}); + + +// internalBindingAllowlist contains the name of internalBinding modules +// that are allowed for access via process.binding()... This is used +// to provide a transition path for modules that are being moved over to +// internalBinding. +const internalBindingAllowlist = new SafeSet([ + 'async_wrap', + 'buffer', + 'cares_wrap', + 'config', + 'constants', + 'contextify', + 'crypto', + 'fs', + 'fs_event_wrap', + 'http_parser', + 'icu', + 'inspector', + 'js_stream', + 'natives', + 'os', + 'pipe_wrap', + 'process_wrap', + 'signal_wrap', + 'spawn_sync', + 'stream_wrap', + 'tcp_wrap', + 'tls_wrap', + 'tty_wrap', + 'udp_wrap', + 'url', + 'util', + 'uv', + 'v8', + 'zlib', +]); + +const runtimeDeprecatedList = new SafeSet([ + 'async_wrap', + 'crypto', + 'http_parser', + 'signal_wrap', + 'url', + 'v8', +]); + +const legacyWrapperList = new SafeSet([ + 'util', +]); + +// The code bellow assumes that the two lists must not contain any modules +// beginning with "internal/". +// Modules that can only be imported via the node: scheme. +const schemelessBlockList = new SafeSet([ + 'test', + 'test/reporters', +]); +// Modules that will only be enabled at run time. +const experimentalModuleList = new SafeSet(); + +// Set up process.binding() and process._linkedBinding(). +{ + const bindingObj = ObjectCreate(null); + + process.binding = function binding(module) { + module = String(module); + // Deprecated specific process.binding() modules, but not all, allow + // selective fallback to internalBinding for the deprecated ones. + if (internalBindingAllowlist.has(module)) { + if (runtimeDeprecatedList.has(module)) { + runtimeDeprecatedList.delete(module); + process.emitWarning( + `Access to process.binding('${module}') is deprecated.`, + 'DeprecationWarning', + 'DEP0111'); + } + if (legacyWrapperList.has(module)) { + return requireBuiltin('internal/legacy/processbinding')[module](); + } + return internalBinding(module); + } + // eslint-disable-next-line no-restricted-syntax + throw new Error(`No such module: ${module}`); + }; + + process._linkedBinding = function _linkedBinding(module) { + module = String(module); + let mod = bindingObj[module]; + if (typeof mod !== 'object') + mod = bindingObj[module] = getLinkedBinding(module); + return mod; + }; +} + +// Set up internalBinding() in the closure. +/** + * @type {InternalBinding} + */ +let internalBinding; +{ + const bindingObj = ObjectCreate(null); + // eslint-disable-next-line no-global-assign + internalBinding = function internalBinding(module) { + let mod = bindingObj[module]; + if (typeof mod !== 'object') { + mod = bindingObj[module] = getInternalBinding(module); + ArrayPrototypePush(moduleLoadList, `Internal Binding ${module}`); + } + return mod; + }; +} + +const selfId = 'internal/bootstrap/realm'; +const { + builtinIds, + compileFunction, + setInternalLoaders, +} = internalBinding('builtins'); + +const getOwn = (target, property, receiver) => { + return ObjectPrototypeHasOwnProperty(target, property) ? + ReflectGet(target, property, receiver) : + undefined; +}; + +const publicBuiltinIds = builtinIds + .filter((id) => + !StringPrototypeStartsWith(id, 'internal/') && + !experimentalModuleList.has(id), + ); +// Do not expose the loaders to user land even with --expose-internals. +const internalBuiltinIds = builtinIds + .filter((id) => StringPrototypeStartsWith(id, 'internal/') && id !== selfId); + +// When --expose-internals is on we'll add the internal builtin ids to these. +const canBeRequiredByUsersList = new SafeSet(publicBuiltinIds); +const canBeRequiredByUsersWithoutSchemeList = + new SafeSet(publicBuiltinIds.filter((id) => !schemelessBlockList.has(id))); + +/** + * An internal abstraction for the built-in JavaScript modules of Node.js. + * Be careful not to expose this to user land unless --expose-internals is + * used, in which case there is no compatibility guarantee about this class. + */ +class BuiltinModule { + /** + * A map from the module IDs to the module instances. + * @type {Map} + */ + static map = new SafeMap( + ArrayPrototypeMap(builtinIds, (id) => [id, new BuiltinModule(id)]), + ); + + constructor(id) { + this.filename = `${id}.js`; + this.id = id; + + // The CJS exports object of the module. + this.exports = {}; + // States used to work around circular dependencies. + this.loaded = false; + this.loading = false; + + // The following properties are used by the ESM implementation and only + // initialized when the built-in module is loaded by users. + /** + * The C++ ModuleWrap binding used to interface with the ESM implementation. + * @type {ModuleWrap|undefined} + */ + this.module = undefined; + /** + * Exported names for the ESM imports. + * @type {string[]|undefined} + */ + this.exportKeys = undefined; + } + + static allowRequireByUsers(id) { + if (id === selfId) { + // No code because this is an assertion against bugs. + // eslint-disable-next-line no-restricted-syntax + throw new Error(`Should not allow ${id}`); + } + canBeRequiredByUsersList.add(id); + if (!schemelessBlockList.has(id)) { + canBeRequiredByUsersWithoutSchemeList.add(id); + } + } + + // To be called during pre-execution when --expose-internals is on. + // Enables the user-land module loader to access internal modules. + static exposeInternals() { + for (let i = 0; i < internalBuiltinIds.length; ++i) { + BuiltinModule.allowRequireByUsers(internalBuiltinIds[i]); + } + } + + static exists(id) { + return BuiltinModule.map.has(id); + } + + static canBeRequiredByUsers(id) { + return canBeRequiredByUsersList.has(id); + } + + static canBeRequiredWithoutScheme(id) { + return canBeRequiredByUsersWithoutSchemeList.has(id); + } + + static isBuiltin(id) { + return BuiltinModule.canBeRequiredWithoutScheme(id) || ( + typeof id === 'string' && + StringPrototypeStartsWith(id, 'node:') && + BuiltinModule.canBeRequiredByUsers(StringPrototypeSlice(id, 5)) + ); + } + + static getCanBeRequiredByUsersWithoutSchemeList() { + return ArrayFrom(canBeRequiredByUsersWithoutSchemeList); + } + + static normalizeRequirableId(id) { + if (StringPrototypeStartsWith(id, 'node:')) { + const normalizedId = StringPrototypeSlice(id, 5); + if (BuiltinModule.canBeRequiredByUsers(normalizedId)) { + return normalizedId; + } + } else if (BuiltinModule.canBeRequiredWithoutScheme(id)) { + return id; + } + + return undefined; + } + + static getSchemeOnlyModuleNames() { + return ArrayFrom(schemelessBlockList); + } + + // Used by user-land module loaders to compile and load builtins. + compileForPublicLoader() { + if (!BuiltinModule.canBeRequiredByUsers(this.id)) { + // No code because this is an assertion against bugs + // eslint-disable-next-line no-restricted-syntax + throw new Error(`Should not compile ${this.id} for public use`); + } + this.compileForInternalLoader(); + if (!this.exportKeys) { + // When using --expose-internals, we do not want to reflect the named + // exports from core modules as this can trigger unnecessary getters. + const internal = StringPrototypeStartsWith(this.id, 'internal/'); + this.exportKeys = internal ? [] : ObjectKeys(this.exports); + } + this.getESMFacade(); + this.syncExports(); + return this.exports; + } + + getESMFacade() { + if (this.module) return this.module; + const { ModuleWrap } = internalBinding('module_wrap'); + // TODO(aduh95): move this to C++, alongside the initialization of the class. + ObjectSetPrototypeOf(ModuleWrap.prototype, null); + const url = `node:${this.id}`; + const builtin = this; + const exportsKeys = ArrayPrototypeSlice(this.exportKeys); + ArrayPrototypePush(exportsKeys, 'default'); + this.module = new ModuleWrap( + url, undefined, exportsKeys, + function() { + builtin.syncExports(); + this.setExport('default', builtin.exports); + }); + // Ensure immediate sync execution to capture exports now + this.module.instantiate(); + this.module.evaluate(-1, false); + return this.module; + } + + // Provide named exports for all builtin libraries so that the libraries + // may be imported in a nicer way for ESM users. The default export is left + // as the entire namespace (module.exports) and updates when this function is + // called so that APMs and other behavior are supported. + syncExports() { + const names = this.exportKeys; + if (this.module) { + for (let i = 0; i < names.length; i++) { + const exportName = names[i]; + if (exportName === 'default') continue; + this.module.setExport(exportName, + getOwn(this.exports, exportName, this.exports)); + } + } + } + + compileForInternalLoader() { + if (this.loaded || this.loading) { + return this.exports; + } + + const id = this.id; + this.loading = true; + + try { + const requireFn = StringPrototypeStartsWith(this.id, 'internal/deps/') ? + requireWithFallbackInDeps : requireBuiltin; + + const fn = compileFunction(id); + // Arguments must match the parameters specified in + // BuiltinLoader::LookupAndCompile(). + fn(this.exports, requireFn, this, process, internalBinding, primordials); + + this.loaded = true; + } finally { + this.loading = false; + } + + // "NativeModule" is a legacy name of "BuiltinModule". We keep it + // here to avoid breaking users who parse process.moduleLoadList. + ArrayPrototypePush(moduleLoadList, `NativeModule ${id}`); + return this.exports; + } +} + +// Think of this as module.exports in this file even though it is not +// written in CommonJS style. +const loaderExports = { + internalBinding, + BuiltinModule, + require: requireBuiltin, +}; + +function requireBuiltin(id) { + if (id === selfId) { + return loaderExports; + } + + const mod = BuiltinModule.map.get(id); + // Can't load the internal errors module from here, have to use a raw error. + // eslint-disable-next-line no-restricted-syntax + if (!mod) throw new TypeError(`Missing internal module '${id}'`); + return mod.compileForInternalLoader(); +} + +// Allow internal modules from dependencies to require +// other modules from dependencies by providing fallbacks. +function requireWithFallbackInDeps(request) { + if (StringPrototypeStartsWith(request, 'node:')) { + request = StringPrototypeSlice(request, 5); + } else if (!BuiltinModule.map.has(request)) { + request = `internal/deps/${request}`; + } + return requireBuiltin(request); +} + +function setupPrepareStackTrace() { + const { + setEnhanceStackForFatalException, + setPrepareStackTraceCallback, + } = internalBinding('errors'); + const { + prepareStackTrace, + fatalExceptionStackEnhancers: { + beforeInspector, + afterInspector, + }, + } = requireBuiltin('internal/errors'); + // Tell our PrepareStackTraceCallback passed to the V8 API + // to call prepareStackTrace(). + setPrepareStackTraceCallback(prepareStackTrace); + // Set the function used to enhance the error stack for printing + setEnhanceStackForFatalException(beforeInspector, afterInspector); +} + +// Store the internal loaders in C++. +setInternalLoaders(internalBinding, requireBuiltin); + +// Setup per-realm bindings. +setupPrepareStackTrace(); diff --git a/lib/internal/bootstrap/switches/is_main_thread.js b/lib/internal/bootstrap/switches/is_main_thread.js index b2f40d9c9b264a..2767ee12584e02 100644 --- a/lib/internal/bootstrap/switches/is_main_thread.js +++ b/lib/internal/bootstrap/switches/is_main_thread.js @@ -3,9 +3,11 @@ const { ObjectDefineProperty } = primordials; const rawMethods = internalBinding('process_methods'); const { - addSerializeCallback, - isBuildingSnapshot, -} = require('v8').startupSnapshot; + namespace: { + addSerializeCallback, + isBuildingSnapshot, + }, +} = require('internal/v8/startup_snapshot'); // TODO(joyeecheung): deprecate and remove these underscore methods process._debugProcess = rawMethods._debugProcess; process._debugEnd = rawMethods._debugEnd; @@ -284,3 +286,30 @@ rawMethods.resetStdioForTesting = function() { stdout = undefined; stderr = undefined; }; + +// Needed by the module loader and generally needed everywhere. +require('fs'); +require('util'); +require('url'); + +require('internal/modules/cjs/loader'); +require('internal/modules/esm/utils'); +require('internal/vm/module'); +// Needed to refresh the time origin. +require('internal/perf/utils'); +// Needed to register the async hooks. +if (internalBinding('config').hasInspector) { + require('internal/inspector_async_hook'); +} +// Needed to set the wasm web API callbacks. +internalBinding('wasm_web_api'); +// Needed to detect whether it's on main thread. +internalBinding('worker'); +// Needed by most execution modes. +require('internal/modules/run_main'); +// Needed to refresh DNS configurations. +require('internal/dns/utils'); +// Needed by almost all execution modes. It's fine to +// load them into the snapshot as long as we don't run +// any of the initialization. +require('internal/process/pre_execution'); diff --git a/lib/internal/console/constructor.js b/lib/internal/console/constructor.js index 21e74f336c41ac..cbc9cd8d3a531c 100644 --- a/lib/internal/console/constructor.js +++ b/lib/internal/console/constructor.js @@ -693,9 +693,11 @@ function initializeGlobalConsole(globalConsole) { globalConsole[kBindProperties](true, 'auto'); const { - addSerializeCallback, - isBuildingSnapshot, - } = require('v8').startupSnapshot; + namespace: { + addSerializeCallback, + isBuildingSnapshot, + }, + } = require('internal/v8/startup_snapshot'); if (!internalBinding('config').hasInspector || !isBuildingSnapshot()) { return; diff --git a/lib/internal/crypto/ec.js b/lib/internal/crypto/ec.js index aca99902cc7584..ebfcecaff3cfc5 100644 --- a/lib/internal/crypto/ec.js +++ b/lib/internal/crypto/ec.js @@ -264,6 +264,10 @@ async function ecImportKey( break; } + if (!keyObject[kHandle].checkEcKeyData()) { + throw lazyDOMException('Invalid keyData', 'DataError'); + } + const { namedCurve: checkNamedCurve, } = keyObject[kHandle].keyDetail({}); diff --git a/lib/internal/debugger/inspect.js b/lib/internal/debugger/inspect.js index b0a86f8c494129..2522c6f34fc4bc 100644 --- a/lib/internal/debugger/inspect.js +++ b/lib/internal/debugger/inspect.js @@ -331,7 +331,7 @@ function startInspect(argv = ArrayPrototypeSlice(process.argv, 2), process.stderr.write(`Usage: ${invokedAs} script.js\n` + ` ${invokedAs} :\n` + - ` ${invokedAs} --port=\n` + + ` ${invokedAs} --port= Use 0 for random port assignment\n` + ` ${invokedAs} -p \n`); process.exit(1); } diff --git a/lib/internal/dns/callback_resolver.js b/lib/internal/dns/callback_resolver.js index 48e8f7df856c26..e57a597c08c716 100644 --- a/lib/internal/dns/callback_resolver.js +++ b/lib/internal/dns/callback_resolver.js @@ -7,8 +7,6 @@ const { Symbol, } = primordials; -const { toASCII } = require('internal/idna'); - const { codes: { ERR_INVALID_ARG_TYPE, @@ -70,7 +68,7 @@ function resolver(bindingName) { req.hostname = name; req.oncomplete = onresolve; req.ttl = !!(options && options.ttl); - const err = this._handle[bindingName](req, toASCII(name)); + const err = this._handle[bindingName](req, name); if (err) throw dnsException(err, bindingName, name); if (hasObserver('dns')) { startPerf(req, kPerfHooksDnsLookupResolveContext, { diff --git a/lib/internal/dns/promises.js b/lib/internal/dns/promises.js index df41d1267ef421..1169b2735d4efe 100644 --- a/lib/internal/dns/promises.js +++ b/lib/internal/dns/promises.js @@ -46,7 +46,6 @@ const { CANCELLED, } = dnsErrorCodes; const { codes, dnsException } = require('internal/errors'); -const { toASCII } = require('internal/idna'); const { isIP } = require('internal/net'); const { getaddrinfo, @@ -114,6 +113,19 @@ function onlookupall(err, addresses) { } } +/** + * Creates a promise that resolves with the IP address of the given hostname. + * @param {0 | 4 | 6} family - The IP address family (4 or 6, or 0 for both). + * @param {string} hostname - The hostname to resolve. + * @param {boolean} all - Whether to resolve with all IP addresses for the hostname. + * @param {number} hints - One or more supported getaddrinfo flags (supply multiple via + * bitwise OR). + * @param {boolean} verbatim - Whether to use the hostname verbatim. + * @returns {Promise} The IP address(es) of the hostname. + * @typedef {object} DNSLookupResult + * @property {string} address - The IP address. + * @property {0 | 4 | 6} family - The IP address type. 4 for IPv4 or 6 for IPv6, or 0 (for both). + */ function createLookupPromise(family, hostname, all, hints, verbatim) { return new Promise((resolve, reject) => { if (!hostname) { @@ -138,7 +150,7 @@ function createLookupPromise(family, hostname, all, hints, verbatim) { req.resolve = resolve; req.reject = reject; - const err = getaddrinfo(req, toASCII(hostname), family, hints, verbatim); + const err = getaddrinfo(req, hostname, family, hints, verbatim); if (err) { reject(dnsException(err, 'getaddrinfo', hostname)); @@ -155,6 +167,17 @@ function createLookupPromise(family, hostname, all, hints, verbatim) { } const validFamilies = [0, 4, 6]; +/** + * Get the IP address for a given hostname. + * @param {string} hostname - The hostname to resolve (ex. 'nodejs.org'). + * @param {object} [options] - Optional settings. + * @param {boolean} [options.all=false] - Whether to return all or just the first resolved address. + * @param {0 | 4 | 6} [options.family=0] - The record family. Must be 4, 6, or 0 (for both). + * @param {number} [options.hints] - One or more supported getaddrinfo flags (supply multiple via + * bitwise OR). + * @param {boolean} [options.verbatim=false] - Return results in same order DNS resolved them; + * otherwise IPv4 then IPv6. New code should supply `true`. + */ function lookup(hostname, options) { let hints = 0; let family = 0; @@ -274,7 +297,7 @@ function createResolverPromise(resolver, bindingName, hostname, ttl) { req.reject = reject; req.ttl = ttl; - const err = resolver._handle[bindingName](req, toASCII(hostname)); + const err = resolver._handle[bindingName](req, hostname); if (err) reject(dnsException(err, bindingName, hostname)); diff --git a/lib/internal/dns/utils.js b/lib/internal/dns/utils.js index 56b2b3930b2f6e..10395ecb89607b 100644 --- a/lib/internal/dns/utils.js +++ b/lib/internal/dns/utils.js @@ -37,10 +37,12 @@ const { } = errors.codes; const { - addSerializeCallback, - addDeserializeCallback, - isBuildingSnapshot, -} = require('v8').startupSnapshot; + namespace: { + addSerializeCallback, + addDeserializeCallback, + isBuildingSnapshot, + }, +} = require('internal/v8/startup_snapshot'); function validateTimeout(options) { const { timeout = -1 } = { ...options }; diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 63536dee1af393..5d488843f60ab8 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -205,7 +205,7 @@ function lazyBuffer() { function isErrorStackTraceLimitWritable() { // Do no touch Error.stackTraceLimit as V8 would attempt to install // it again during deserialization. - if (require('v8').startupSnapshot.isBuildingSnapshot()) { + if (require('internal/v8/startup_snapshot').namespace.isBuildingSnapshot()) { return false; } @@ -1177,12 +1177,17 @@ E('ERR_HTTP_SOCKET_ENCODING', E('ERR_HTTP_TRAILER_INVALID', 'Trailers are invalid with this transfer encoding', Error); E('ERR_ILLEGAL_CONSTRUCTOR', 'Illegal constructor', TypeError); +// TODO(aduh95): change the error to mention import attributes instead of import assertions. E('ERR_IMPORT_ASSERTION_TYPE_FAILED', 'Module "%s" is not of type "%s"', TypeError); +// TODO(aduh95): change the error to mention import attributes instead of import assertions. E('ERR_IMPORT_ASSERTION_TYPE_MISSING', - 'Module "%s" needs an import assertion of type "%s"', TypeError); + 'Module "%s" needs an import attribute of type "%s"', TypeError); +// TODO(aduh95): change the error to mention import attributes instead of import assertions. E('ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED', - 'Import assertion type "%s" is unsupported', TypeError); + 'Import attribute type "%s" is unsupported', TypeError); +E('ERR_IMPORT_ATTRIBUTE_UNSUPPORTED', + 'Import attribute "%s" with value "%s" is not supported', TypeError); E('ERR_INCOMPATIBLE_OPTION_PAIR', 'Option "%s" cannot be used in combination with option "%s"', TypeError); E('ERR_INPUT_TYPE_NOT_ALLOWED', '--input-type can only be used with string ' + @@ -1453,8 +1458,12 @@ E('ERR_MISSING_ARGS', return `${msg} must be specified`; }, TypeError); E('ERR_MISSING_OPTION', '%s is required', TypeError); -E('ERR_MODULE_NOT_FOUND', (path, base, type = 'package') => { - return `Cannot find ${type} '${path}' imported from ${base}`; +E('ERR_MODULE_NOT_FOUND', function(path, base, exactUrl) { + if (exactUrl) { + lazyInternalUtil().setOwnProperty(this, 'url', `${exactUrl}`); + } + return `Cannot find ${ + exactUrl ? 'module' : 'package'} '${path}' imported from ${base}`; }, Error); E('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times', Error); E('ERR_NAPI_CONS_FUNCTION', 'Constructor must be a function', TypeError); @@ -1542,7 +1551,7 @@ E('ERR_REQUIRE_ESM', msg += `\n${basename} is treated as an ES module file as it is a .js ` + 'file whose nearest parent package.json contains "type": "module" ' + 'which declares all .js files in that package scope as ES modules.' + - `\nInstead rename ${basename} to end in .cjs, change the requiring ` + + `\nInstead either rename ${basename} to end in .cjs, change the requiring ` + 'code to use dynamic import() which is available in all CommonJS ' + 'modules, or change "type": "module" to "type": "commonjs" in ' + `${packageJsonPath} to treat all .js files as CommonJS (using .mjs for ` + @@ -1622,6 +1631,16 @@ E('ERR_TEST_FAILURE', function(error, failureType) { this.cause = error; return msg; }, Error); +E('ERR_TLS_ALPN_CALLBACK_INVALID_RESULT', (value, protocols) => { + return `ALPN callback returned a value (${ + value + }) that did not match any of the client's offered protocols (${ + protocols.join(', ') + })`; +}, TypeError); +E('ERR_TLS_ALPN_CALLBACK_WITH_PROTOCOLS', + 'The ALPNCallback and ALPNProtocols TLS options are mutually exclusive', + TypeError); E('ERR_TLS_CERT_ALTNAME_FORMAT', 'Invalid subject alternative name string', SyntaxError); E('ERR_TLS_CERT_ALTNAME_INVALID', function(reason, host, cert) { @@ -1672,18 +1691,15 @@ E('ERR_UNHANDLED_ERROR', E('ERR_UNKNOWN_BUILTIN_MODULE', 'No such built-in module: %s', Error); E('ERR_UNKNOWN_CREDENTIAL', '%s identifier does not exist: %s', Error); E('ERR_UNKNOWN_ENCODING', 'Unknown encoding: %s', TypeError); -E('ERR_UNKNOWN_FILE_EXTENSION', (ext, path, suggestion) => { - let msg = `Unknown file extension "${ext}" for ${path}`; - if (suggestion) { - msg += `. ${suggestion}`; - } - return msg; -}, TypeError); +E('ERR_UNKNOWN_FILE_EXTENSION', 'Unknown file extension "%s" for %s', TypeError); E('ERR_UNKNOWN_MODULE_FORMAT', 'Unknown module format: %s for URL %s', RangeError); E('ERR_UNKNOWN_SIGNAL', 'Unknown signal: %s', TypeError); -E('ERR_UNSUPPORTED_DIR_IMPORT', "Directory import '%s' is not supported " + -'resolving ES modules imported from %s', Error); +E('ERR_UNSUPPORTED_DIR_IMPORT', function(path, base, exactUrl) { + lazyInternalUtil().setOwnProperty(this, 'url', exactUrl); + return `Directory import '${path}' is not supported ` + + `resolving ES modules imported from ${base}`; +}, Error); E('ERR_UNSUPPORTED_ESM_URL_SCHEME', (url, supported) => { let msg = `Only URLs with a scheme in: ${formatList(supported)} are supported by the default ESM loader`; if (isWindows && url.protocol.length === 2) { diff --git a/lib/internal/event_target.js b/lib/internal/event_target.js index 42b810679dadf7..5f49d7e04df16d 100644 --- a/lib/internal/event_target.js +++ b/lib/internal/event_target.js @@ -62,6 +62,7 @@ const kWeakHandler = Symbol('kWeak'); const kResistStopPropagation = Symbol('kResistStopPropagation'); const kHybridDispatch = SymbolFor('nodejs.internal.kHybridDispatch'); +const kRemoveWeakListenerHelper = Symbol('nodejs.internal.removeWeakListenerHelper'); const kCreateEvent = Symbol('kCreateEvent'); const kNewListener = Symbol('kNewListener'); const kRemoveListener = Symbol('kRemoveListener'); @@ -392,7 +393,7 @@ let weakListenersState = null; let objectToWeakListenerMap = null; function weakListeners() { weakListenersState ??= new SafeFinalizationRegistry( - (listener) => listener.remove(), + ({ eventTarget, listener, eventType }) => eventTarget.deref()?.[kRemoveWeakListenerHelper](eventType, listener), ); objectToWeakListenerMap ??= new SafeWeakMap(); return { registry: weakListenersState, map: objectToWeakListenerMap }; @@ -414,7 +415,7 @@ const kFlagResistStopPropagation = 1 << 6; // the linked list makes dispatching faster, even if adding/removing is // slower. class Listener { - constructor(previous, listener, once, capture, passive, + constructor(eventTarget, eventType, previous, listener, once, capture, passive, isNodeStyleListener, weak, resistStopPropagation) { this.next = undefined; if (previous !== undefined) @@ -441,7 +442,13 @@ class Listener { if (this.weak) { this.callback = new SafeWeakRef(listener); - weakListeners().registry.register(listener, this, this); + weakListeners().registry.register(listener, { + __proto__: null, + // Weak ref so the listener won't hold the eventTarget alive + eventTarget: new SafeWeakRef(eventTarget), + listener: this, + eventType, + }, this); // Make the retainer retain the listener in a WeakMap weakListeners().map.set(weak, listener); this.listener = this.callback; @@ -604,7 +611,7 @@ class EventTarget { if (root === undefined) { root = { size: 1, next: undefined, resistStopPropagation: Boolean(resistStopPropagation) }; // This is the first handler in our linked list. - new Listener(root, listener, once, capture, passive, + new Listener(this, type, root, listener, once, capture, passive, isNodeStyleListener, weak, resistStopPropagation); this[kNewListener]( root.size, @@ -631,7 +638,7 @@ class EventTarget { return; } - new Listener(previous, listener, once, capture, passive, + new Listener(this, type, previous, listener, once, capture, passive, isNodeStyleListener, weak, resistStopPropagation); root.size++; root.resistStopPropagation ||= Boolean(resistStopPropagation); @@ -674,6 +681,28 @@ class EventTarget { } } + [kRemoveWeakListenerHelper](type, listener) { + const root = this[kEvents].get(type); + if (root === undefined || root.next === undefined) + return; + + const capture = listener.capture === true; + + let handler = root.next; + while (handler !== undefined) { + if (handler === listener) { + handler.remove(); + root.size--; + if (root.size === 0) + this[kEvents].delete(type); + // Undefined is passed as the listener as the listener was GCed + this[kRemoveListener](root.size, type, undefined, capture); + break; + } + handler = handler.next; + } + } + /** * @param {Event} event */ diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index 4cf97f2253aa7d..870b323fd6a6e1 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -59,7 +59,6 @@ const { getStatsFromBinding, getValidatedPath, getValidMode, - nullCheck, preprocessSymlinkDestination, stringToFlags, stringToSymlinkType, @@ -249,6 +248,9 @@ class FileHandle extends EventEmitterMixin(JSTransferable) { /** * @typedef {import('../webstreams/readablestream').ReadableStream * } ReadableStream + * @param {{ + * type?: string; + * }} [options] * @returns {ReadableStream} */ readableWebStream(options = kEmptyObject) { @@ -274,17 +276,8 @@ class FileHandle extends EventEmitterMixin(JSTransferable) { this[kHandle], undefined, { ondone: () => this[kUnref]() }); - - const { - readableStreamCancel, - } = require('internal/webstreams/readablestream'); - this[kRef](); - this.once('close', () => { - readableStreamCancel(readable); - }); } else { const { - readableStreamCancel, ReadableStream, } = require('internal/webstreams/readablestream'); @@ -311,14 +304,16 @@ class FileHandle extends EventEmitterMixin(JSTransferable) { ondone(); }, }); - - this[kRef](); - - this.once('close', () => { - readableStreamCancel(readable); - }); } + const { + readableStreamCancel, + } = require('internal/webstreams/readablestream'); + this[kRef](); + this.once('close', () => { + readableStreamCancel(readable); + }); + return readable; } @@ -976,10 +971,17 @@ async function realpath(path, options) { async function mkdtemp(prefix, options) { options = getOptions(options); - validateString(prefix, 'prefix'); - nullCheck(prefix); + prefix = getValidatedPath(prefix, 'prefix'); warnOnNonPortableTemplate(prefix); - return binding.mkdtemp(`${prefix}XXXXXX`, options.encoding, kUsePromises); + + let path; + if (typeof prefix === 'string') { + path = `${prefix}XXXXXX`; + } else { + path = Buffer.concat([prefix, Buffer.from('XXXXXX')]); + } + + return binding.mkdtemp(path, options.encoding, kUsePromises); } async function writeFile(path, data, options) { diff --git a/lib/internal/fs/recursive_watch.js b/lib/internal/fs/recursive_watch.js index ed146fa28bed8d..1cd99ffb41f7e2 100644 --- a/lib/internal/fs/recursive_watch.js +++ b/lib/internal/fs/recursive_watch.js @@ -42,6 +42,7 @@ function lazyLoadFsSync() { internalSync ??= require('fs'); return internalSync; } +let kResistStopPropagation; async function traverse(dir, files = new SafeMap(), symbolicLinks = new SafeSet()) { const { opendir } = lazyLoadFsPromises(); @@ -265,7 +266,8 @@ class FSWatcher extends EventEmitter { } : (resolve, reject) => { const onAbort = () => reject(new AbortError(undefined, { cause: signal.reason })); if (signal.aborted) return onAbort(); - signal.addEventListener('abort', onAbort, { __proto__: null, once: true }); + kResistStopPropagation ??= require('internal/event_target').kResistStopPropagation; + signal.addEventListener('abort', onAbort, { __proto__: null, once: true, [kResistStopPropagation]: true }); this.once('change', (eventType, filename) => { signal.removeEventListener('abort', onAbort); resolve({ __proto__: null, value: { eventType, filename } }); diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js index 23865845bac59e..00889ffccc4b99 100644 --- a/lib/internal/fs/utils.js +++ b/lib/internal/fs/utils.js @@ -21,6 +21,7 @@ const { StringPrototypeEndsWith, StringPrototypeIncludes, Symbol, + TypedArrayPrototypeAt, TypedArrayPrototypeIncludes, } = primordials; @@ -736,7 +737,9 @@ let nonPortableTemplateWarn = true; function warnOnNonPortableTemplate(template) { // Template strings passed to the mkdtemp() family of functions should not // end with 'X' because they are handled inconsistently across platforms. - if (nonPortableTemplateWarn && StringPrototypeEndsWith(template, 'X')) { + if (nonPortableTemplateWarn && + ((typeof template === 'string' && StringPrototypeEndsWith(template, 'X')) || + (typeof template !== 'string' && TypedArrayPrototypeAt(template, -1) === 0x58))) { process.emitWarning('mkdtemp() templates ending with X are not portable. ' + 'For details see: https://nodejs.org/api/fs.html'); nonPortableTemplateWarn = false; diff --git a/lib/internal/fs/watchers.js b/lib/internal/fs/watchers.js index ce885c154c81c5..99212fa713bf3f 100644 --- a/lib/internal/fs/watchers.js +++ b/lib/internal/fs/watchers.js @@ -299,6 +299,8 @@ ObjectDefineProperty(FSEvent.prototype, 'owner', { set(v) { return this[owner_symbol] = v; }, }); +let kResistStopPropagation; + async function* watch(filename, options = kEmptyObject) { const path = toNamespacedPath(getValidatedPath(filename)); validateObject(options, 'options'); @@ -330,7 +332,10 @@ async function* watch(filename, options = kEmptyObject) { }; try { - signal?.addEventListener('abort', oncancel, { once: true }); + if (signal) { + kResistStopPropagation ??= require('internal/event_target').kResistStopPropagation; + signal.addEventListener('abort', oncancel, { __proto__: null, once: true, [kResistStopPropagation]: true }); + } handle.onchange = (status, eventType, filename) => { if (status < 0) { const error = uvException({ diff --git a/lib/internal/js_stream_socket.js b/lib/internal/js_stream_socket.js index 8bc19296620b3f..70d6d03069f3f1 100644 --- a/lib/internal/js_stream_socket.js +++ b/lib/internal/js_stream_socket.js @@ -21,6 +21,7 @@ const { ERR_STREAM_WRAP } = require('internal/errors').codes; const kCurrentWriteRequest = Symbol('kCurrentWriteRequest'); const kCurrentShutdownRequest = Symbol('kCurrentShutdownRequest'); const kPendingShutdownRequest = Symbol('kPendingShutdownRequest'); +const kPendingClose = Symbol('kPendingClose'); function isClosing() { return this[owner_symbol].isClosing(); } @@ -94,6 +95,7 @@ class JSStreamSocket extends Socket { this[kCurrentWriteRequest] = null; this[kCurrentShutdownRequest] = null; this[kPendingShutdownRequest] = null; + this[kPendingClose] = false; this.readable = stream.readable; this.writable = stream.writable; @@ -135,11 +137,19 @@ class JSStreamSocket extends Socket { this[kPendingShutdownRequest] = req; return 0; } + assert(this[kCurrentWriteRequest] === null); assert(this[kCurrentShutdownRequest] === null); this[kCurrentShutdownRequest] = req; + if (this[kPendingClose]) { + // If doClose is pending, the stream & this._handle are gone. We can't do + // anything. doClose will call finishShutdown with ECANCELED for us shortly. + return 0; + } + const handle = this._handle; + assert(handle !== null); process.nextTick(() => { // Ensure that write is dispatched asynchronously. @@ -164,7 +174,16 @@ class JSStreamSocket extends Socket { assert(this[kCurrentWriteRequest] === null); assert(this[kCurrentShutdownRequest] === null); + if (this[kPendingClose]) { + // If doClose is pending, the stream & this._handle are gone. We can't do + // anything. doClose will call finishWrite with ECANCELED for us shortly. + this[kCurrentWriteRequest] = req; // Store req, for doClose to cancel + return 0; + } + const handle = this._handle; + assert(handle !== null); + const self = this; let pending = bufs.length; @@ -217,6 +236,8 @@ class JSStreamSocket extends Socket { } doClose(cb) { + this[kPendingClose] = true; + const handle = this._handle; // When sockets of the "net" module destroyed, they will call @@ -234,6 +255,8 @@ class JSStreamSocket extends Socket { this.finishWrite(handle, uv.UV_ECANCELED); this.finishShutdown(handle, uv.UV_ECANCELED); + this[kPendingClose] = false; + cb(); }); } diff --git a/lib/internal/main/check_syntax.js b/lib/internal/main/check_syntax.js index 52c83be33287c0..b6ee64de499c2f 100644 --- a/lib/internal/main/check_syntax.js +++ b/lib/internal/main/check_syntax.js @@ -63,7 +63,8 @@ function loadESMIfNeeded(cb) { async function checkSyntax(source, filename) { let isModule = true; if (filename === '[stdin]' || filename === '[eval]') { - isModule = getOptionValue('--input-type') === 'module'; + isModule = getOptionValue('--input-type') === 'module' || + (getOptionValue('--experimental-default-type') === 'module' && getOptionValue('--input-type') !== 'commonjs'); } else { const { defaultResolve } = require('internal/modules/esm/resolve'); const { defaultGetFormat } = require('internal/modules/esm/get_format'); diff --git a/lib/internal/main/eval_stdin.js b/lib/internal/main/eval_stdin.js index d947af49a6a942..d71751e781b9b5 100644 --- a/lib/internal/main/eval_stdin.js +++ b/lib/internal/main/eval_stdin.js @@ -25,12 +25,14 @@ readStdin((code) => { const print = getOptionValue('--print'); const loadESM = getOptionValue('--import').length > 0; - if (getOptionValue('--input-type') === 'module') + if (getOptionValue('--input-type') === 'module' || + (getOptionValue('--experimental-default-type') === 'module' && getOptionValue('--input-type') !== 'commonjs')) { evalModule(code, print); - else + } else { evalScript('[stdin]', code, getOptionValue('--inspect-brk'), print, loadESM); + } }); diff --git a/lib/internal/main/eval_string.js b/lib/internal/main/eval_string.js index cb5b758ad4152e..4e2edf9ce62499 100644 --- a/lib/internal/main/eval_string.js +++ b/lib/internal/main/eval_string.js @@ -12,7 +12,7 @@ const { markBootstrapComplete, } = require('internal/process/pre_execution'); const { evalModule, evalScript } = require('internal/process/execution'); -const { addBuiltinLibsToObject } = require('internal/modules/cjs/helpers'); +const { addBuiltinLibsToObject } = require('internal/modules/helpers'); const { getOptionValue } = require('internal/options'); @@ -22,12 +22,14 @@ markBootstrapComplete(); const source = getOptionValue('--eval'); const print = getOptionValue('--print'); -const loadESM = getOptionValue('--import').length > 0; -if (getOptionValue('--input-type') === 'module') +const loadESM = getOptionValue('--import').length > 0 || getOptionValue('--experimental-loader').length > 0; +if (getOptionValue('--input-type') === 'module' || + (getOptionValue('--experimental-default-type') === 'module' && getOptionValue('--input-type') !== 'commonjs')) { evalModule(source, print); -else +} else { evalScript('[eval]', source, getOptionValue('--inspect-brk'), print, loadESM); +} diff --git a/lib/internal/main/mksnapshot.js b/lib/internal/main/mksnapshot.js index 6dee4334fbaa4f..d39f29236385b4 100644 --- a/lib/internal/main/mksnapshot.js +++ b/lib/internal/main/mksnapshot.js @@ -7,12 +7,10 @@ const { ObjectSetPrototypeOf, SafeArrayIterator, SafeSet, - StringPrototypeStartsWith, - StringPrototypeSlice, } = primordials; const binding = internalBinding('mksnapshot'); -const { BuiltinModule } = require('internal/bootstrap/loaders'); +const { BuiltinModule: { normalizeRequirableId } } = require('internal/bootstrap/realm'); const { compileSerializeMain, } = binding; @@ -97,13 +95,8 @@ function supportedInUserSnapshot(id) { } function requireForUserSnapshot(id) { - let normalizedId = id; - if (StringPrototypeStartsWith(id, 'node:')) { - normalizedId = StringPrototypeSlice(id, 5); - } - if (!BuiltinModule.canBeRequiredByUsers(normalizedId) || - (id !== normalizedId && - !BuiltinModule.canBeRequiredWithoutScheme(normalizedId))) { + const normalizedId = normalizeRequirableId(id); + if (!normalizedId) { // eslint-disable-next-line no-restricted-syntax const err = new Error( `Cannot find module '${id}'. `, diff --git a/lib/internal/main/run_main_module.js b/lib/internal/main/run_main_module.js index 51331270a2161f..5d09203b8c27ee 100644 --- a/lib/internal/main/run_main_module.js +++ b/lib/internal/main/run_main_module.js @@ -6,18 +6,24 @@ const { prepareMainThreadExecution, markBootstrapComplete, } = require('internal/process/pre_execution'); +const { getOptionValue } = require('internal/options'); -prepareMainThreadExecution(true); +const mainEntry = prepareMainThreadExecution(true); markBootstrapComplete(); // Necessary to reset RegExp statics before user code runs. RegExpPrototypeExec(/^/, ''); -// Note: this loads the module through the ESM loader if the module is -// determined to be an ES module. This hangs from the CJS module loader -// because we currently allow monkey-patching of the module loaders -// in the preloaded scripts through require('module'). -// runMain here might be monkey-patched by users in --require. -// XXX: the monkey-patchability here should probably be deprecated. -require('internal/modules/cjs/loader').Module.runMain(process.argv[1]); +if (getOptionValue('--experimental-default-type') === 'module') { + require('internal/modules/run_main').executeUserEntryPoint(mainEntry); +} else { + /** + * To support legacy monkey-patching of `Module.runMain`, we call `runMain` here to have the CommonJS loader begin + * the execution of the main entry point, even if the ESM loader immediately takes over because the main entry is an + * ES module or one of the other opt-in conditions (such as the use of `--import`) are met. Users can monkey-patch + * before the main entry point is loaded by doing so via scripts loaded through `--require`. This monkey-patchability + * is undesirable and is removed in `--experimental-default-type=module` mode. + */ + require('internal/modules/cjs/loader').Module.runMain(mainEntry); +} diff --git a/lib/internal/main/single_executable_application.js b/lib/internal/main/single_executable_application.js index d9604cff720d2f..f2995757b21fef 100644 --- a/lib/internal/main/single_executable_application.js +++ b/lib/internal/main/single_executable_application.js @@ -7,6 +7,7 @@ const { getSingleExecutableCode } = internalBinding('sea'); const { emitExperimentalWarning } = require('internal/util'); const { Module, wrapSafe } = require('internal/modules/cjs/loader'); const { codes: { ERR_UNKNOWN_BUILTIN_MODULE } } = require('internal/errors'); +const { BuiltinModule: { normalizeRequirableId } } = require('internal/bootstrap/realm'); prepareMainThreadExecution(false, true); markBootstrapComplete(); @@ -33,12 +34,13 @@ customModule.paths = Module._nodeModulePaths(customModule.path); const customExports = customModule.exports; -function customRequire(path) { - if (!Module.isBuiltin(path)) { - throw new ERR_UNKNOWN_BUILTIN_MODULE(path); +function customRequire(id) { + const normalizedId = normalizeRequirableId(id); + if (!normalizedId) { + throw new ERR_UNKNOWN_BUILTIN_MODULE(id); } - return require(path); + return require(normalizedId); } customRequire.main = customModule; diff --git a/lib/internal/main/test_runner.js b/lib/internal/main/test_runner.js index 134dadcf505f35..7ca1646a2d90ba 100644 --- a/lib/internal/main/test_runner.js +++ b/lib/internal/main/test_runner.js @@ -7,11 +7,24 @@ const { getOptionValue } = require('internal/options'); const { isUsingInspector } = require('internal/util/inspector'); const { run } = require('internal/test_runner/runner'); const { setupTestReporters } = require('internal/test_runner/utils'); +const { + codes: { + ERR_INVALID_ARG_VALUE, + }, +} = require('internal/errors'); +const { + NumberParseInt, + RegExpPrototypeExec, + StringPrototypeSplit, +} = primordials; +let debug = require('internal/util/debuglog').debuglog('test_runner', (fn) => { + debug = fn; +}); prepareMainThreadExecution(false); markBootstrapComplete(); -let concurrency = true; +let concurrency = getOptionValue('--test-concurrency') || true; let inspectPort; if (isUsingInspector()) { @@ -21,7 +34,41 @@ if (isUsingInspector()) { inspectPort = process.debugPort; } -run({ concurrency, inspectPort, watch: getOptionValue('--watch'), setup: setupTestReporters }) -.once('test:fail', () => { - process.exitCode = 1; +let shard; +const shardOption = getOptionValue('--test-shard'); +if (shardOption) { + if (!RegExpPrototypeExec(/^\d+\/\d+$/, shardOption)) { + process.exitCode = 1; + + throw new ERR_INVALID_ARG_VALUE( + '--test-shard', + shardOption, + 'must be in the form of /', + ); + } + + const { 0: indexStr, 1: totalStr } = StringPrototypeSplit(shardOption, '/'); + + const index = NumberParseInt(indexStr, 10); + const total = NumberParseInt(totalStr, 10); + + shard = { + __proto__: null, + index, + total, + }; +} + +const options = { + concurrency, + inspectPort, + watch: getOptionValue('--watch'), + setup: setupTestReporters, + shard, +}; +debug('test runner configuration:', options); +run(options).on('test:fail', (data) => { + if (data.todo === undefined || data.todo === false) { + process.exitCode = 1; + } }); diff --git a/lib/internal/main/watch_mode.js b/lib/internal/main/watch_mode.js index 84f27303294f4a..1fcb6453d903dc 100644 --- a/lib/internal/main/watch_mode.js +++ b/lib/internal/main/watch_mode.js @@ -42,7 +42,7 @@ const args = ArrayPrototypeFilter(process.execArgv, (arg, i, arr) => arg !== '--watch' && arg !== '--watch-preserve-output'); ArrayPrototypePushApply(args, kCommand); -const watcher = new FilesWatcher({ throttle: 500, mode: kShouldFilterModules ? 'filter' : 'all' }); +const watcher = new FilesWatcher({ debounce: 200, mode: kShouldFilterModules ? 'filter' : 'all' }); ArrayPrototypeForEach(kWatchedPaths, (p) => watcher.watchPath(p)); let graceTimer; diff --git a/lib/internal/main/worker_thread.js b/lib/internal/main/worker_thread.js index 7fbfb64984c290..b905de0da20a20 100644 --- a/lib/internal/main/worker_thread.js +++ b/lib/internal/main/worker_thread.js @@ -10,6 +10,7 @@ const { ObjectDefineProperty, PromisePrototypeThen, RegExpPrototypeExec, + SafeWeakMap, globalThis: { Atomics, SharedArrayBuffer, @@ -88,23 +89,25 @@ port.on('message', (message) => { const { argv, cwdCounter, - filename, doEval, - workerData, environmentData, - publicPort, + filename, + hasStdin, manifestSrc, manifestURL, - hasStdin, + publicPort, + workerData, } = message; - if (argv !== undefined) { - ArrayPrototypePushApply(process.argv, argv); - } + if (doEval !== 'internal') { + if (argv !== undefined) { + ArrayPrototypePushApply(process.argv, argv); + } - const publicWorker = require('worker_threads'); - publicWorker.parentPort = publicPort; - publicWorker.workerData = workerData; + const publicWorker = require('worker_threads'); + publicWorker.parentPort = publicPort; + publicWorker.workerData = workerData; + } require('internal/worker').assignEnvironmentData(environmentData); @@ -129,7 +132,10 @@ port.on('message', (message) => { if (manifestSrc) { require('internal/process/policy').setup(manifestSrc, manifestURL); } - setupUserModules(); + const isLoaderWorker = + doEval === 'internal' && + filename === require('internal/modules/esm/utils').loaderWorkerId; + setupUserModules(isLoaderWorker); if (!hasStdin) process.stdin.push(null); @@ -137,31 +143,47 @@ port.on('message', (message) => { debug(`[${threadId}] starts worker script ${filename} ` + `(eval = ${doEval}) at cwd = ${process.cwd()}`); port.postMessage({ type: UP_AND_RUNNING }); - if (doEval === 'classic') { - const { evalScript } = require('internal/process/execution'); - const name = '[worker eval]'; - // This is necessary for CJS module compilation. - // TODO: pass this with something really internal. - ObjectDefineProperty(process, '_eval', { - __proto__: null, - configurable: true, - enumerable: true, - value: filename, - }); - ArrayPrototypeSplice(process.argv, 1, 0, name); - evalScript(name, filename); - } else if (doEval === 'module') { - const { evalModule } = require('internal/process/execution'); - PromisePrototypeThen(evalModule(filename), undefined, (e) => { - workerOnGlobalUncaughtException(e, true); - }); - } else { - // script filename - // runMain here might be monkey-patched by users in --require. - // XXX: the monkey-patchability here should probably be deprecated. - ArrayPrototypeSplice(process.argv, 1, 0, filename); - const CJSLoader = require('internal/modules/cjs/loader'); - CJSLoader.Module.runMain(filename); + switch (doEval) { + case 'internal': { + // Create this WeakMap in js-land because V8 has no C++ API for WeakMap. + internalBinding('module_wrap').callbackMap = new SafeWeakMap(); + require(filename)(workerData, publicPort); + break; + } + + case 'classic': { + const { evalScript } = require('internal/process/execution'); + const name = '[worker eval]'; + // This is necessary for CJS module compilation. + // TODO: pass this with something really internal. + ObjectDefineProperty(process, '_eval', { + __proto__: null, + configurable: true, + enumerable: true, + value: filename, + }); + ArrayPrototypeSplice(process.argv, 1, 0, name); + evalScript(name, filename); + break; + } + + case 'module': { + const { evalModule } = require('internal/process/execution'); + PromisePrototypeThen(evalModule(filename), undefined, (e) => { + workerOnGlobalUncaughtException(e, true); + }); + break; + } + + default: { + // script filename + // runMain here might be monkey-patched by users in --require. + // XXX: the monkey-patchability here should probably be deprecated. + ArrayPrototypeSplice(process.argv, 1, 0, filename); + const CJSLoader = require('internal/modules/cjs/loader'); + CJSLoader.Module.runMain(filename); + break; + } } } else if (message.type === STDIO_PAYLOAD) { const { stream, chunks } = message; diff --git a/lib/internal/modules/cjs/helpers.js b/lib/internal/modules/cjs/helpers.js deleted file mode 100644 index 00d2b628c44172..00000000000000 --- a/lib/internal/modules/cjs/helpers.js +++ /dev/null @@ -1,256 +0,0 @@ -'use strict'; - -const { - ArrayPrototypeForEach, - ArrayPrototypeJoin, - ArrayPrototypeSome, - ObjectDefineProperty, - ObjectPrototypeHasOwnProperty, - SafeMap, - SafeSet, - StringPrototypeCharCodeAt, - StringPrototypeIncludes, - StringPrototypeSlice, - StringPrototypeStartsWith, -} = primordials; -const { - ERR_INVALID_ARG_TYPE, - ERR_MANIFEST_DEPENDENCY_MISSING, - ERR_UNKNOWN_BUILTIN_MODULE, -} = require('internal/errors').codes; -const { BuiltinModule } = require('internal/bootstrap/loaders'); - -const { validateString } = require('internal/validators'); -const path = require('path'); -const { pathToFileURL, fileURLToPath, URL } = require('internal/url'); - -const { getOptionValue } = require('internal/options'); -const { setOwnProperty } = require('internal/util'); -const userConditions = getOptionValue('--conditions'); - -const { - privateSymbols: { - require_private_symbol, - }, -} = internalBinding('util'); - -let debug = require('internal/util/debuglog').debuglog('module', (fn) => { - debug = fn; -}); - -const noAddons = getOptionValue('--no-addons'); -const addonConditions = noAddons ? [] : ['node-addons']; - -// TODO: Use this set when resolving pkg#exports conditions in loader.js. -const cjsConditions = new SafeSet([ - 'require', - 'node', - ...addonConditions, - ...userConditions, -]); - -function loadBuiltinModule(filename, request) { - const mod = BuiltinModule.map.get(filename); - if (mod?.canBeRequiredByUsers) { - debug('load built-in module %s', request); - // compileForPublicLoader() throws if mod.canBeRequiredByUsers is false: - mod.compileForPublicLoader(); - return mod; - } -} - -let $Module = null; -function lazyModule() { - $Module = $Module || require('internal/modules/cjs/loader').Module; - return $Module; -} - -// Invoke with makeRequireFunction(module) where |module| is the Module object -// to use as the context for the require() function. -// Use redirects to set up a mapping from a policy and restrict dependencies -const urlToFileCache = new SafeMap(); -function makeRequireFunction(mod, redirects) { - // lazy due to cycle - const Module = lazyModule(); - if (mod instanceof Module !== true) { - throw new ERR_INVALID_ARG_TYPE('mod', 'Module', mod); - } - - let require; - if (redirects) { - const id = mod.filename || mod.id; - const conditions = cjsConditions; - const { resolve, reaction } = redirects; - require = function require(specifier) { - let missing = true; - const destination = resolve(specifier, conditions); - if (destination === true) { - missing = false; - } else if (destination) { - const { href, protocol } = destination; - if (protocol === 'node:') { - const specifier = destination.pathname; - const mod = loadBuiltinModule(specifier, href); - if (mod && mod.canBeRequiredByUsers) { - return mod.exports; - } - throw new ERR_UNKNOWN_BUILTIN_MODULE(specifier); - } else if (protocol === 'file:') { - let filepath = urlToFileCache.get(href); - if (!filepath) { - filepath = fileURLToPath(destination); - urlToFileCache.set(href, filepath); - } - return mod[require_private_symbol](mod, filepath); - } - } - if (missing) { - reaction(new ERR_MANIFEST_DEPENDENCY_MISSING( - id, - specifier, - ArrayPrototypeJoin([...conditions], ', '), - )); - } - return mod[require_private_symbol](mod, specifier); - }; - } else { - require = function require(path) { - // When no policy manifest, the original prototype.require is sustained - return mod.require(path); - }; - } - - function resolve(request, options) { - validateString(request, 'request'); - return Module._resolveFilename(request, mod, false, options); - } - - require.resolve = resolve; - - function paths(request) { - validateString(request, 'request'); - return Module._resolveLookupPaths(request, mod); - } - - resolve.paths = paths; - - setOwnProperty(require, 'main', process.mainModule); - - // Enable support to add extra extension types. - require.extensions = Module._extensions; - - require.cache = Module._cache; - - return require; -} - -/** - * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) - * because the buffer-to-string conversion in `fs.readFileSync()` - * translates it to FEFF, the UTF-16 BOM. - */ -function stripBOM(content) { - if (StringPrototypeCharCodeAt(content) === 0xFEFF) { - content = StringPrototypeSlice(content, 1); - } - return content; -} - -function addBuiltinLibsToObject(object, dummyModuleName) { - // Make built-in modules available directly (loaded lazily). - const Module = require('internal/modules/cjs/loader').Module; - const { builtinModules } = Module; - - // To require built-in modules in user-land and ignore modules whose - // `canBeRequiredByUsers` is false. So we create a dummy module object and not - // use `require()` directly. - const dummyModule = new Module(dummyModuleName); - - ArrayPrototypeForEach(builtinModules, (name) => { - // Neither add underscored modules, nor ones that contain slashes (e.g., - // 'fs/promises') or ones that are already defined. - if (StringPrototypeStartsWith(name, '_') || - StringPrototypeIncludes(name, '/') || - ObjectPrototypeHasOwnProperty(object, name)) { - return; - } - // Goals of this mechanism are: - // - Lazy loading of built-in modules - // - Having all built-in modules available as non-enumerable properties - // - Allowing the user to re-assign these variables as if there were no - // pre-existing globals with the same name. - - const setReal = (val) => { - // Deleting the property before re-assigning it disables the - // getter/setter mechanism. - delete object[name]; - object[name] = val; - }; - - ObjectDefineProperty(object, name, { - __proto__: null, - get: () => { - const lib = dummyModule.require(name); - - try { - // Override the current getter/setter and set up a new - // non-enumerable property. - ObjectDefineProperty(object, name, { - __proto__: null, - get: () => lib, - set: setReal, - configurable: true, - enumerable: false, - }); - } catch { - // If the property is no longer configurable, ignore the error. - } - - return lib; - }, - set: setReal, - configurable: true, - enumerable: false, - }); - }); -} - -/** - * - * @param {string | URL} referrer - * @returns {string} - */ -function normalizeReferrerURL(referrer) { - if (typeof referrer === 'string' && path.isAbsolute(referrer)) { - return pathToFileURL(referrer).href; - } - return new URL(referrer).href; -} - -// For error messages only - used to check if ESM syntax is in use. -function hasEsmSyntax(code) { - debug('Checking for ESM syntax'); - const parser = require('internal/deps/acorn/acorn/dist/acorn').Parser; - let root; - try { - root = parser.parse(code, { sourceType: 'module', ecmaVersion: 'latest' }); - } catch { - return false; - } - - return ArrayPrototypeSome(root.body, (stmt) => - stmt.type === 'ExportDefaultDeclaration' || - stmt.type === 'ExportNamedDeclaration' || - stmt.type === 'ImportDeclaration' || - stmt.type === 'ExportAllDeclaration'); -} - -module.exports = { - addBuiltinLibsToObject, - cjsConditions, - hasEsmSyntax, - loadBuiltinModule, - makeRequireFunction, - normalizeReferrerURL, - stripBOM, -}; diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index 88bb870a8fd2e5..316996a8c329a1 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -34,7 +34,6 @@ const { ArrayPrototypeSplice, ArrayPrototypeUnshift, ArrayPrototypeUnshiftApply, - ArrayPrototypeFlatMap, Boolean, Error, JSONParse, @@ -52,13 +51,11 @@ const { ReflectSet, RegExpPrototypeExec, SafeMap, - SafeSet, SafeWeakMap, String, StringPrototypeCharAt, StringPrototypeCharCodeAt, StringPrototypeEndsWith, - StringPrototypeLastIndexOf, StringPrototypeIndexOf, StringPrototypeRepeat, StringPrototypeSlice, @@ -71,31 +68,28 @@ const cjsParseCache = new SafeWeakMap(); // Set first due to cycle with ESM loader functions. module.exports = { - wrapSafe, Module, toRealPath, readPackageScope, cjsParseCache, + wrapSafe, Module, cjsParseCache, get hasLoadedAnyUserCJSModule() { return hasLoadedAnyUserCJSModule; }, + initializeCJS, }; -const { BuiltinModule } = require('internal/bootstrap/loaders'); +const { BuiltinModule } = require('internal/bootstrap/realm'); const { maybeCacheSourceMap, } = require('internal/source_map/source_map_cache'); const { pathToFileURL, fileURLToPath, isURL } = require('internal/url'); const { - deprecate, + pendingDeprecate, emitExperimentalWarning, kEmptyObject, - filterOwnProperties, setOwnProperty, + getLazy, } = require('internal/util'); -const { Script } = require('vm'); const { internalCompileFunction } = require('internal/vm'); const assert = require('internal/assert'); const fs = require('fs'); -const internalFS = require('internal/fs/utils'); const path = require('path'); -const { sep } = path; const { internalModuleStat } = internalBinding('fs'); -const packageJsonReader = require('internal/modules/package_json_reader'); const { safeGetenv } = internalBinding('credentials'); const { privateSymbols: { @@ -103,21 +97,25 @@ const { }, } = internalBinding('util'); const { - cjsConditions, + getCjsConditions, + initializeCjsConditions, hasEsmSyntax, loadBuiltinModule, makeRequireFunction, normalizeReferrerURL, stripBOM, -} = require('internal/modules/cjs/helpers'); -const { getOptionValue } = require('internal/options'); -const preserveSymlinks = getOptionValue('--preserve-symlinks'); -const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main'); -const shouldReportRequiredModules = process.env.WATCH_REPORT_DEPENDENCIES; -// Do not eagerly grab .manifest, it may be in TDZ -const policy = getOptionValue('--experimental-policy') ? - require('internal/process/policy') : - null; + toRealPath, +} = require('internal/modules/helpers'); +const packageJsonReader = require('internal/modules/package_json_reader'); +const { getOptionValue, getEmbedderOptions } = require('internal/options'); +const policy = getLazy( + () => (getOptionValue('--experimental-policy') ? require('internal/process/policy') : null), +); +const shouldReportRequiredModules = getLazy(() => process.env.WATCH_REPORT_DEPENDENCIES); + +const getCascadedLoader = getLazy( + () => require('internal/process/esm_loader').esmLoader, +); // Whether any user-provided CJS modules had been loaded (executed). // Used for internal assertions. @@ -133,7 +131,6 @@ const { setArrowMessage, } = require('internal/errors'); const { validateString } = require('internal/validators'); -const pendingDeprecation = getOptionValue('--pending-deprecation'); const { CHAR_BACKWARD_SLASH, @@ -146,15 +143,7 @@ const { isProxy, } = require('internal/util/types'); -const asyncESM = require('internal/process/esm_loader'); -const { enrichCJSError } = require('internal/modules/esm/translators'); const { kEvaluated } = internalBinding('module_wrap'); -const { - encodedSepRegEx, - packageExportsResolve, - packageImportsResolve, -} = require('internal/modules/esm/resolve'); - const isWindows = process.platform === 'win32'; const relativeResolveCache = ObjectCreate(null); @@ -163,6 +152,11 @@ let requireDepth = 0; let isPreloading = false; let statCache = null; +/** + * Our internal implementation of `require`. + * @param {Module} module Parent module of what is being required + * @param {string} id Specifier of the child module being imported + */ function internalRequire(module, id) { validateString(id, 'id'); if (id === '') { @@ -177,11 +171,15 @@ function internalRequire(module, id) { } } +/** + * Get a path's properties, using an in-memory cache to minimize lookups. + * @param {string} filename Absolute path to the file + */ function stat(filename) { filename = path.toNamespacedPath(filename); if (statCache !== null) { const result = statCache.get(filename); - if (result !== undefined) return result; + if (result !== undefined) { return result; } } const result = internalModuleStat(filename); if (statCache !== null && result >= 0) { @@ -203,25 +201,47 @@ ObjectDefineProperty(Module, '_stat', { configurable: true, }); +/** + * Update the parent's children array with the child module. + * @param {Module} parent Module requiring the children + * @param {Module} child Module being required + * @param {boolean} scan Add the child to the parent's children if not already present + */ function updateChildren(parent, child, scan) { const children = parent?.children; - if (children && !(scan && ArrayPrototypeIncludes(children, child))) + if (children && !(scan && ArrayPrototypeIncludes(children, child))) { ArrayPrototypePush(children, child); + } } +/** + * Tell the watch mode that a module was required. + * @param {string} filename Absolute path of the module + */ function reportModuleToWatchMode(filename) { - if (shouldReportRequiredModules && process.send) { + if (shouldReportRequiredModules() && process.send) { process.send({ 'watch:require': [filename] }); } } +/** + * Tell the watch mode that a module was not found. + * @param {string} basePath The absolute path that errored + * @param {string[]} extensions The extensions that were tried + */ function reportModuleNotFoundToWatchMode(basePath, extensions) { - if (shouldReportRequiredModules && process.send) { + if (shouldReportRequiredModules() && process.send) { process.send({ 'watch:require': ArrayPrototypeMap(extensions, (ext) => path.resolve(`${basePath}${ext}`)) }); } } +/** @type {Map} */ const moduleParentCache = new SafeWeakMap(); +/** + * Create a new module instance. + * @param {string} id + * @param {Module} parent + */ function Module(id = '', parent) { this.id = id; this.path = path.dirname(id); @@ -232,9 +252,10 @@ function Module(id = '', parent) { this.loaded = false; this.children = []; let redirects; - if (policy?.manifest) { + const manifest = policy()?.manifest; + if (manifest) { const moduleURL = pathToFileURL(id); - redirects = policy.manifest.getDependencyMapper(moduleURL); + redirects = manifest.getDependencyMapper(moduleURL); // TODO(rafaelgss): remove the necessity of this branch setOwnProperty(this, 'require', makeRequireFunction(this, redirects)); // eslint-disable-next-line no-proto @@ -243,32 +264,24 @@ function Module(id = '', parent) { this[require_private_symbol] = internalRequire; } -const builtinModules = []; -for (const { 0: id, 1: mod } of BuiltinModule.map) { - if (mod.canBeRequiredByUsers && - BuiltinModule.canBeRequiredWithoutScheme(id)) { - ArrayPrototypePush(builtinModules, id); - } -} - -const allBuiltins = new SafeSet( - ArrayPrototypeFlatMap(builtinModules, (bm) => [bm, `node:${bm}`]), -); -BuiltinModule.getSchemeOnlyModuleNames().forEach((builtin) => allBuiltins.add(`node:${builtin}`)); - -ObjectFreeze(builtinModules); -Module.builtinModules = builtinModules; - -Module._cache = ObjectCreate(null); -Module._pathCache = ObjectCreate(null); -Module._extensions = ObjectCreate(null); +/** @type {Record} */ +Module._cache = { __proto__: null }; +/** @type {Record} */ +Module._pathCache = { __proto__: null }; +/** @type {Record void>} */ +Module._extensions = { __proto__: null }; +/** @type {string[]} */ let modulePaths = []; +/** @type {string[]} */ Module.globalPaths = []; let patched = false; -// eslint-disable-next-line func-style -let wrap = function(script) { +/** + * Add the CommonJS wrapper around a module's source code. + * @param {string} script Module source code + */ +let wrap = function(script) { // eslint-disable-line func-style return Module.wrapper[0] + script + Module.wrapper[1]; }; @@ -319,34 +332,62 @@ const isPreloadingDesc = { get() { return isPreloading; } }; ObjectDefineProperty(Module.prototype, 'isPreloading', isPreloadingDesc); ObjectDefineProperty(BuiltinModule.prototype, 'isPreloading', isPreloadingDesc); +/** + * Get the parent of the current module from our cache. + */ function getModuleParent() { return moduleParentCache.get(this); } +/** + * Set the parent of the current module in our cache. + * @param {Module} value + */ function setModuleParent(value) { moduleParentCache.set(this, value); } +let debug = require('internal/util/debuglog').debuglog('module', (fn) => { + debug = fn; +}); + ObjectDefineProperty(Module.prototype, 'parent', { __proto__: null, - get: pendingDeprecation ? deprecate( + get: pendingDeprecate( getModuleParent, 'module.parent is deprecated due to accuracy issues. Please use ' + 'require.main to find program entry point instead.', 'DEP0144', - ) : getModuleParent, - set: pendingDeprecation ? deprecate( + ), + set: pendingDeprecate( setModuleParent, 'module.parent is deprecated due to accuracy issues. Please use ' + 'require.main to find program entry point instead.', 'DEP0144', - ) : setModuleParent, + ), }); +Module._debug = pendingDeprecate(debug, 'Module._debug is deprecated.', 'DEP0077'); +Module.isBuiltin = BuiltinModule.isBuiltin; -let debug = require('internal/util/debuglog').debuglog('module', (fn) => { - debug = fn; -}); -Module._debug = deprecate(debug, 'Module._debug is deprecated.', 'DEP0077'); +/** + * Prepare to run CommonJS code. + * This function is called during pre-execution, before any user code is run. + */ +function initializeCJS() { + // This need to be done at runtime in case --expose-internals is set. + const builtinModules = BuiltinModule.getCanBeRequiredByUsersWithoutSchemeList(); + Module.builtinModules = ObjectFreeze(builtinModules); + + initializeCjsConditions(); + + if (!getEmbedderOptions().noGlobalSearchPaths) { + Module._initPaths(); + } + + // TODO(joyeecheung): deprecate this in favor of a proper hook? + Module.runMain = + require('internal/modules/run_main').executeUserEntryPoint; +} // Given a module name, and a list of paths to test, returns the first // matching file in the following precedence. @@ -359,39 +400,7 @@ Module._debug = deprecate(debug, 'Module._debug is deprecated.', 'DEP0077'); // -> a. // -> a/index. -const packageJsonCache = new SafeMap(); - -function readPackage(requestPath) { - const jsonPath = path.resolve(requestPath, 'package.json'); - - const existing = packageJsonCache.get(jsonPath); - if (existing !== undefined) return existing; - - const result = packageJsonReader.read(jsonPath); - const json = result.containsKeys === false ? '{}' : result.string; - if (json === undefined) { - packageJsonCache.set(jsonPath, false); - return false; - } - - try { - const filtered = filterOwnProperties(JSONParse(json), [ - 'name', - 'main', - 'exports', - 'imports', - 'type', - ]); - packageJsonCache.set(jsonPath, filtered); - return filtered; - } catch (e) { - e.path = jsonPath; - e.message = 'Error parsing ' + jsonPath + ': ' + e.message; - throw e; - } -} - -let _readPackage = readPackage; +let _readPackage = packageJsonReader.readPackage; ObjectDefineProperty(Module, '_readPackage', { __proto__: null, get() { return _readPackage; }, @@ -403,25 +412,15 @@ ObjectDefineProperty(Module, '_readPackage', { configurable: true, }); -function readPackageScope(checkPath) { - const rootSeparatorIndex = StringPrototypeIndexOf(checkPath, sep); - let separatorIndex; - do { - separatorIndex = StringPrototypeLastIndexOf(checkPath, sep); - checkPath = StringPrototypeSlice(checkPath, 0, separatorIndex); - if (StringPrototypeEndsWith(checkPath, sep + 'node_modules')) - return false; - const pjson = _readPackage(checkPath + sep); - if (pjson) return { - data: pjson, - path: checkPath, - }; - } while (separatorIndex > rootSeparatorIndex); - return false; -} - +/** + * Try to load a specifier as a package. + * @param {string} requestPath The path to what we are trying to load + * @param {string[]} exts File extensions to try appending in order to resolve the file + * @param {boolean} isMain Whether the file is the main entry point of the app + * @param {string} originalPath The specifier passed to `require` + */ function tryPackage(requestPath, exts, isMain, originalPath) { - const pkg = _readPackage(requestPath)?.main; + const pkg = _readPackage(requestPath).main; if (!pkg) { return tryExtensions(path.resolve(requestPath, 'index'), exts, isMain); @@ -457,34 +456,30 @@ function tryPackage(requestPath, exts, isMain, originalPath) { return actual; } -// In order to minimize unnecessary lstat() calls, -// this cache is a list of known-real paths. -// Set to an empty Map to reset. -const realpathCache = new SafeMap(); - -// Check if the file exists and is not a directory -// if using --preserve-symlinks and isMain is false, -// keep symlinks intact, otherwise resolve to the -// absolute realpath. +/** + * Check if the file exists and is not a directory if using `--preserve-symlinks` and `isMain` is false, keep symlinks + * intact, otherwise resolve to the absolute realpath. + * @param {string} requestPath The path to the file to load. + * @param {boolean} isMain Whether the file is the main module. + */ function tryFile(requestPath, isMain) { const rc = _stat(requestPath); - if (rc !== 0) return; - if (preserveSymlinks && !isMain) { + if (rc !== 0) { return; } + if (getOptionValue('--preserve-symlinks') && !isMain) { return path.resolve(requestPath); } return toRealPath(requestPath); } -function toRealPath(requestPath) { - return fs.realpathSync(requestPath, { - [internalFS.realpathCacheKey]: realpathCache, - }); -} - -// Given a path, check if the file exists with any of the set extensions -function tryExtensions(p, exts, isMain) { +/** + * Given a path, check if the file exists with any of the set extensions. + * @param {string} basePath The path and filename without extension + * @param {string[]} exts The extensions to try + * @param {boolean} isMain Whether the module is the main module + */ +function tryExtensions(basePath, exts, isMain) { for (let i = 0; i < exts.length; i++) { - const filename = tryFile(p + exts[i], isMain); + const filename = tryFile(basePath + exts[i], isMain); if (filename) { return filename; @@ -493,8 +488,10 @@ function tryExtensions(p, exts, isMain) { return false; } -// Find the longest (possibly multi-dot) extension registered in -// Module._extensions +/** + * Find the longest (possibly multi-dot) extension registered in `Module._extensions`. + * @param {string} filename The filename to find the longest registered extension for. + */ function findLongestRegisteredExtension(filename) { const name = path.basename(filename); let currentExtension; @@ -502,15 +499,19 @@ function findLongestRegisteredExtension(filename) { let startIndex = 0; while ((index = StringPrototypeIndexOf(name, '.', startIndex)) !== -1) { startIndex = index + 1; - if (index === 0) continue; // Skip dotfiles like .gitignore + if (index === 0) { continue; } // Skip dotfiles like .gitignore currentExtension = StringPrototypeSlice(name, index); - if (Module._extensions[currentExtension]) return currentExtension; + if (Module._extensions[currentExtension]) { return currentExtension; } } return '.js'; } +/** + * Tries to get the absolute file path of the parent module. + * @param {Module} parent The parent module object. + */ function trySelfParentPath(parent) { - if (!parent) return false; + if (!parent) { return false; } if (parent.filename) { return parent.filename; @@ -523,12 +524,18 @@ function trySelfParentPath(parent) { } } +/** + * Attempt to resolve a module request using the parent module package metadata. + * @param {string} parentPath The path of the parent module + * @param {string} request The module request to resolve + */ function trySelf(parentPath, request) { - if (!parentPath) return false; + if (!parentPath) { return false; } - const { data: pkg, path: pkgPath } = readPackageScope(parentPath) || {}; - if (!pkg || pkg.exports === undefined) return false; - if (typeof pkg.name !== 'string') return false; + const { data: pkg, path: pkgPath } = packageJsonReader.readPackageScope(parentPath); + if (!pkg || pkg.exports == null || pkg.name === undefined) { + return false; + } let expansion; if (request === pkg.name) { @@ -540,45 +547,57 @@ function trySelf(parentPath, request) { } try { + const { packageExportsResolve } = require('internal/modules/esm/resolve'); return finalizeEsmResolution(packageExportsResolve( pathToFileURL(pkgPath + '/package.json'), expansion, pkg, - pathToFileURL(parentPath), cjsConditions), parentPath, pkgPath); + pathToFileURL(parentPath), getCjsConditions()), parentPath, pkgPath); } catch (e) { - if (e.code === 'ERR_MODULE_NOT_FOUND') + if (e.code === 'ERR_MODULE_NOT_FOUND') { throw createEsmNotFoundErr(request, pkgPath + '/package.json'); + } throw e; } } -// This only applies to requests of a specific form: -// 1. name/.* -// 2. @scope/name/.* +/** + * This only applies to requests of a specific form: + * 1. `name/.*` + * 2. `@scope/name/.*` + */ const EXPORTS_PATTERN = /^((?:@[^/\\%]+\/)?[^./\\%][^/\\%]*)(\/.*)?$/; + +/** + * Resolves the exports for a given module path and request. + * @param {string} nmPath The path to the module. + * @param {string} request The request for the module. + */ function resolveExports(nmPath, request) { // The implementation's behavior is meant to mirror resolution in ESM. const { 1: name, 2: expansion = '' } = RegExpPrototypeExec(EXPORTS_PATTERN, request) || kEmptyObject; - if (!name) - return; + if (!name) { return; } const pkgPath = path.resolve(nmPath, name); const pkg = _readPackage(pkgPath); - if (pkg?.exports != null) { + if (pkg.exists && pkg.exports != null) { try { + const { packageExportsResolve } = require('internal/modules/esm/resolve'); return finalizeEsmResolution(packageExportsResolve( pathToFileURL(pkgPath + '/package.json'), '.' + expansion, pkg, null, - cjsConditions), null, pkgPath); + getCjsConditions()), null, pkgPath); } catch (e) { - if (e.code === 'ERR_MODULE_NOT_FOUND') + if (e.code === 'ERR_MODULE_NOT_FOUND') { throw createEsmNotFoundErr(request, pkgPath + '/package.json'); + } throw e; } } } /** - * @param {string} request a relative or absolute file path - * @param {Array} paths file system directories to search as file paths - * @param {boolean} isMain if the request is the main app entry point + * Get the absolute path to a module. + * @param {string} request Relative or absolute file path + * @param {Array} paths Folders to search as file paths + * @param {boolean} isMain Whether the request is the main app entry point * @returns {string | false} */ Module._findPath = function(request, paths, isMain) { @@ -591,8 +610,9 @@ Module._findPath = function(request, paths, isMain) { const cacheKey = request + '\x00' + ArrayPrototypeJoin(paths, '\x00'); const entry = Module._pathCache[cacheKey]; - if (entry) + if (entry) { return entry; + } let exts; const trailingSlash = request.length > 0 && @@ -630,12 +650,15 @@ Module._findPath = function(request, paths, isMain) { for (let i = 0; i < paths.length; i++) { // Don't search further if path doesn't exist and request is inside the path const curPath = paths[i]; - if (insidePath && curPath && _stat(curPath) < 1) continue; + if (insidePath && curPath && _stat(curPath) < 1) { + continue; + } if (!absoluteRequest) { const exportsResolved = resolveExports(curPath, request); - if (exportsResolved) + if (exportsResolved) { return exportsResolved; + } } const basePath = path.resolve(curPath, request); @@ -645,19 +668,19 @@ Module._findPath = function(request, paths, isMain) { if (!trailingSlash) { if (rc === 0) { // File. if (!isMain) { - if (preserveSymlinks) { + if (getOptionValue('--preserve-symlinks')) { filename = path.resolve(basePath); } else { filename = toRealPath(basePath); } - } else if (preserveSymlinksMain) { - // For the main module, we use the preserveSymlinksMain flag instead + } else if (getOptionValue('--preserve-symlinks-main')) { + // For the main module, we use the --preserve-symlinks-main flag instead // mainly for backward compatibility, as the preserveSymlinks flag // historically has not applied to the main module. Most likely this // was intended to keep .bin/ binaries working, as following those // symlinks is usually required for the imports in the corresponding // files to resolve; that said, in some use cases following symlinks - // causes bigger problems which is why the preserveSymlinksMain option + // causes bigger problems which is why the --preserve-symlinks-main option // is needed. filename = path.resolve(basePath); } else { @@ -667,16 +690,18 @@ Module._findPath = function(request, paths, isMain) { if (!filename) { // Try it with each of the extensions - if (exts === undefined) + if (exts === undefined) { exts = ObjectKeys(Module._extensions); + } filename = tryExtensions(basePath, exts, isMain); } } if (!filename && rc === 1) { // Directory. // try it with each of the extensions at "index" - if (exts === undefined) + if (exts === undefined) { exts = ObjectKeys(Module._extensions); + } filename = tryPackage(basePath, exts, isMain, request); } @@ -695,11 +720,14 @@ Module._findPath = function(request, paths, isMain) { return false; }; -// 'node_modules' character codes reversed +/** `node_modules` character codes reversed */ const nmChars = [ 115, 101, 108, 117, 100, 111, 109, 95, 101, 100, 111, 110 ]; const nmLen = nmChars.length; if (isWindows) { - // 'from' is the __dirname of the module. + /** + * Get the paths to the `node_modules` folder for a given path. + * @param {string} from `__dirname` of the module + */ Module._nodeModulePaths = function(from) { // Guarantee that 'from' is absolute. from = path.resolve(from); @@ -712,9 +740,11 @@ if (isWindows) { // path.resolve will make sure from.length >=3 in Windows. if (StringPrototypeCharCodeAt(from, from.length - 1) === CHAR_BACKWARD_SLASH && - StringPrototypeCharCodeAt(from, from.length - 2) === CHAR_COLON) + StringPrototypeCharCodeAt(from, from.length - 2) === CHAR_COLON) { return [from + 'node_modules']; + } + /** @type {string[]} */ const paths = []; for (let i = from.length - 1, p = 0, last = from.length; i >= 0; --i) { const code = StringPrototypeCharCodeAt(from, i); @@ -726,11 +756,12 @@ if (isWindows) { if (code === CHAR_BACKWARD_SLASH || code === CHAR_FORWARD_SLASH || code === CHAR_COLON) { - if (p !== nmLen) + if (p !== nmLen) { ArrayPrototypePush( paths, StringPrototypeSlice(from, 0, last) + '\\node_modules', ); + } last = i; p = 0; } else if (p !== -1) { @@ -745,27 +776,33 @@ if (isWindows) { return paths; }; } else { // posix - // 'from' is the __dirname of the module. + /** + * Get the paths to the `node_modules` folder for a given path. + * @param {string} from `__dirname` of the module + */ Module._nodeModulePaths = function(from) { // Guarantee that 'from' is absolute. from = path.resolve(from); // Return early not only to avoid unnecessary work, but to *avoid* returning // an array of two items for a root: [ '//node_modules', '/node_modules' ] - if (from === '/') + if (from === '/') { return ['/node_modules']; + } // note: this approach *only* works when the path is guaranteed // to be absolute. Doing a fully-edge-case-correct path.split // that works on both Windows and Posix is non-trivial. + /** @type {string[]} */ const paths = []; for (let i = from.length - 1, p = 0, last = from.length; i >= 0; --i) { const code = StringPrototypeCharCodeAt(from, i); if (code === CHAR_FORWARD_SLASH) { - if (p !== nmLen) + if (p !== nmLen) { ArrayPrototypePush( paths, StringPrototypeSlice(from, 0, last) + '/node_modules', ); + } last = i; p = 0; } else if (p !== -1) { @@ -784,14 +821,13 @@ if (isWindows) { }; } +/** + * Get the paths for module resolution. + * @param {string} request + * @param {Module} parent + */ Module._resolveLookupPaths = function(request, parent) { - if (( - StringPrototypeStartsWith(request, 'node:') && - BuiltinModule.canBeRequiredByUsers(StringPrototypeSlice(request, 5)) - ) || ( - BuiltinModule.canBeRequiredByUsers(request) && - BuiltinModule.canBeRequiredWithoutScheme(request) - )) { + if (BuiltinModule.normalizeRequirableId(request)) { debug('looking for %j in []', request); return null; } @@ -803,6 +839,7 @@ Module._resolveLookupPaths = function(request, parent) { StringPrototypeCharAt(request, 1) !== '/' && (!isWindows || StringPrototypeCharAt(request, 1) !== '\\'))) { + /** @type {string[]} */ let paths; if (parent?.paths?.length) { paths = ArrayPrototypeSlice(modulePaths); @@ -832,6 +869,10 @@ Module._resolveLookupPaths = function(request, parent) { return parentDir; }; +/** + * Emits a warning when a non-existent property of module exports is accessed inside a circular dependency. + * @param {string} prop The name of the non-existent property. + */ function emitCircularRequireWarning(prop) { process.emitWarning( `Accessing non-existent property '${String(prop)}' of module exports ` + @@ -848,19 +889,26 @@ const CircularRequirePrototypeWarningProxy = new Proxy({}, { // Allow __esModule access in any case because it is used in the output // of transpiled code to determine whether something comes from an // ES module, and is not used as a regular key of `module.exports`. - if (prop in target || prop === '__esModule') return target[prop]; + if (prop in target || prop === '__esModule') { return target[prop]; } emitCircularRequireWarning(prop); return undefined; }, getOwnPropertyDescriptor(target, prop) { - if (ObjectPrototypeHasOwnProperty(target, prop) || prop === '__esModule') + if (ObjectPrototypeHasOwnProperty(target, prop) || prop === '__esModule') { return ObjectGetOwnPropertyDescriptor(target, prop); + } emitCircularRequireWarning(prop); return undefined; }, }); +/** + * Returns the exports object for a module that has a circular `require`. + * If the exports object is a plain object, it is wrapped in a proxy that warns + * about circular dependencies. + * @param {Module} module The module instance + */ function getExportsForCircularRequire(module) { if (module.exports && !isProxy(module.exports) && @@ -878,13 +926,17 @@ function getExportsForCircularRequire(module) { return module.exports; } -// Check the cache for the requested file. -// 1. If a module already exists in the cache: return its exports object. -// 2. If the module is native: call -// `BuiltinModule.prototype.compileForPublicLoader()` and return the exports. -// 3. Otherwise, create a new module for the file and save it to the cache. -// Then have it load the file contents before returning its exports -// object. +/** + * Load a module from cache if it exists, otherwise create a new module instance. + * 1. If a module already exists in the cache: return its exports object. + * 2. If the module is native: call + * `BuiltinModule.prototype.compileForPublicLoader()` and return the exports. + * 3. Otherwise, create a new module for the file and save it to the cache. + * Then have it load the file contents before returning its exports object. + * @param {string} request Specifier of module to load via `require` + * @param {string} parent Absolute path of the module importing the child + * @param {boolean} isMain Whether the module is the main entry point + */ Module._load = function(request, parent, isMain) { let relResolveCacheIdentifier; if (parent) { @@ -899,8 +951,9 @@ Module._load = function(request, parent, isMain) { const cachedModule = Module._cache[filename]; if (cachedModule !== undefined) { updateChildren(parent, cachedModule, true); - if (!cachedModule.loaded) + if (!cachedModule.loaded) { return getExportsForCircularRequire(cachedModule); + } return cachedModule.exports; } delete relativeResolveCache[relResolveCacheIdentifier]; @@ -911,11 +964,11 @@ Module._load = function(request, parent, isMain) { // Slice 'node:' prefix const id = StringPrototypeSlice(request, 5); - const module = loadBuiltinModule(id, request); - if (!module?.canBeRequiredByUsers) { + if (!BuiltinModule.canBeRequiredByUsers(id)) { throw new ERR_UNKNOWN_BUILTIN_MODULE(request); } + const module = loadBuiltinModule(id, request); return module.exports; } @@ -925,17 +978,17 @@ Module._load = function(request, parent, isMain) { updateChildren(parent, cachedModule, true); if (!cachedModule.loaded) { const parseCachedModule = cjsParseCache.get(cachedModule); - if (!parseCachedModule || parseCachedModule.loaded) + if (!parseCachedModule || parseCachedModule.loaded) { return getExportsForCircularRequire(cachedModule); + } parseCachedModule.loaded = true; } else { return cachedModule.exports; } } - const mod = loadBuiltinModule(filename, request); - if (mod?.canBeRequiredByUsers && - BuiltinModule.canBeRequiredWithoutScheme(filename)) { + if (BuiltinModule.canBeRequiredWithoutScheme(filename)) { + const mod = loadBuiltinModule(filename, request); return mod.exports; } @@ -983,16 +1036,17 @@ Module._load = function(request, parent, isMain) { return module.exports; }; +/** + * Given a `require` string and its context, get its absolute file path. + * @param {string} request The specifier to resolve + * @param {Module} parent The module containing the `require` call + * @param {boolean} isMain Whether the module is the main entry point + * @param {ResolveFilenameOptions} options Options object + * @typedef {object} ResolveFilenameOptions + * @property {string[]} paths Paths to search for modules in + */ Module._resolveFilename = function(request, parent, isMain, options) { - if ( - ( - StringPrototypeStartsWith(request, 'node:') && - BuiltinModule.canBeRequiredByUsers(StringPrototypeSlice(request, 5)) - ) || ( - BuiltinModule.canBeRequiredByUsers(request) && - BuiltinModule.canBeRequiredWithoutScheme(request) - ) - ) { + if (BuiltinModule.normalizeRequirableId(request)) { return request; } @@ -1018,8 +1072,9 @@ Module._resolveFilename = function(request, parent, isMain, options) { const lookupPaths = Module._resolveLookupPaths(request, fakeParent); for (let j = 0; j < lookupPaths.length; j++) { - if (!ArrayPrototypeIncludes(paths, lookupPaths[j])) + if (!ArrayPrototypeIncludes(paths, lookupPaths[j])) { ArrayPrototypePush(paths, lookupPaths[j]); + } } } } @@ -1034,16 +1089,18 @@ Module._resolveFilename = function(request, parent, isMain, options) { if (request[0] === '#' && (parent?.filename || parent?.id === '')) { const parentPath = parent?.filename ?? process.cwd() + path.sep; - const pkg = readPackageScope(parentPath) || {}; + const pkg = packageJsonReader.readPackageScope(parentPath) || { __proto__: null }; if (pkg.data?.imports != null) { try { + const { packageImportsResolve } = require('internal/modules/esm/resolve'); return finalizeEsmResolution( packageImportsResolve(request, pathToFileURL(parentPath), - cjsConditions), parentPath, + getCjsConditions()), parentPath, pkg.path); } catch (e) { - if (e.code === 'ERR_MODULE_NOT_FOUND') + if (e.code === 'ERR_MODULE_NOT_FOUND') { throw createEsmNotFoundErr(request); + } throw e; } } @@ -1061,7 +1118,7 @@ Module._resolveFilename = function(request, parent, isMain, options) { // Look up the filename first, since that's the cache key. const filename = Module._findPath(request, paths, isMain); - if (filename) return filename; + if (filename) { return filename; } const requireStack = []; for (let cursor = parent; cursor; @@ -1080,30 +1137,50 @@ Module._resolveFilename = function(request, parent, isMain, options) { throw err; }; +/** + * Finishes resolving an ES module specifier into an absolute file path. + * @param {string} resolved The resolved module specifier + * @param {string} parentPath The path of the parent module + * @param {string} pkgPath The path of the package.json file + * @throws {ERR_INVALID_MODULE_SPECIFIER} If the resolved module specifier contains encoded `/` or `\\` characters + * @throws {Error} If the module cannot be found + */ function finalizeEsmResolution(resolved, parentPath, pkgPath) { - if (RegExpPrototypeExec(encodedSepRegEx, resolved) !== null) + const { encodedSepRegEx } = require('internal/modules/esm/resolve'); + if (RegExpPrototypeExec(encodedSepRegEx, resolved) !== null) { throw new ERR_INVALID_MODULE_SPECIFIER( resolved, 'must not include encoded "/" or "\\" characters', parentPath); + } const filename = fileURLToPath(resolved); const actual = tryFile(filename); - if (actual) + if (actual) { return actual; + } const err = createEsmNotFoundErr(filename, path.resolve(pkgPath, 'package.json')); throw err; } +/** + * Creates an error object for when a requested ES module cannot be found. + * @param {string} request The name of the requested module + * @param {string} [path] The path to the requested module + */ function createEsmNotFoundErr(request, path) { // eslint-disable-next-line no-restricted-syntax const err = new Error(`Cannot find module '${request}'`); err.code = 'MODULE_NOT_FOUND'; - if (path) + if (path) { err.path = path; + } // TODO(BridgeAR): Add the requireStack as well. return err; } -// Given a file name, pass it to the proper extension handler. +/** + * Given a file name, pass it to the proper extension handler. + * @param {string} filename The `require` specifier + */ Module.prototype.load = function(filename) { debug('load %j for module %j', filename, this.id); @@ -1113,25 +1190,30 @@ Module.prototype.load = function(filename) { const extension = findLongestRegisteredExtension(filename); // allow .mjs to be overridden - if (StringPrototypeEndsWith(filename, '.mjs') && !Module._extensions['.mjs']) + if (StringPrototypeEndsWith(filename, '.mjs') && !Module._extensions['.mjs']) { throw new ERR_REQUIRE_ESM(filename, true); + } Module._extensions[extension](this, filename); this.loaded = true; - const esmLoader = asyncESM.esmLoader; + const cascadedLoader = getCascadedLoader(); // Create module entry at load time to snapshot exports correctly const exports = this.exports; // Preemptively cache if ((module?.module === undefined || module.module.getStatus() < kEvaluated) && - !esmLoader.cjsCache.has(this)) - esmLoader.cjsCache.set(this, exports); + !cascadedLoader.cjsCache.has(this)) { + cascadedLoader.cjsCache.set(this, exports); + } }; -// Loads a module at the given file path. Returns that module's -// `exports` property. -// Note: when using the experimental policy mechanism this function is overridden +/** + * Loads a module at the given file path. Returns that module's `exports` property. + * Note: when using the experimental policy mechanism this function is overridden. + * @param {string} id + * @throws {ERR_INVALID_ARG_TYPE} When `id` is not a string + */ Module.prototype.require = function(id) { validateString(id, 'id'); if (id === '') { @@ -1146,21 +1228,35 @@ Module.prototype.require = function(id) { } }; -// Resolved path to process.argv[1] will be lazily placed here -// (needed for setting breakpoint when called with --inspect-brk) +/** + * Resolved path to `process.argv[1]` will be lazily placed here + * (needed for setting breakpoint when called with `--inspect-brk`). + * @type {string | undefined} + */ let resolvedArgv; let hasPausedEntry = false; +/** @type {import('vm').Script} */ +let Script; +/** + * Wraps the given content in a script and runs it in a new context. + * @param {string} filename The name of the file being loaded + * @param {string} content The content of the file being loaded + * @param {Module} cjsModuleInstance The CommonJS loader instance + */ function wrapSafe(filename, content, cjsModuleInstance) { if (patched) { const wrapper = Module.wrap(content); + if (Script === undefined) { + ({ Script } = require('vm')); + } const script = new Script(wrapper, { filename, lineOffset: 0, - importModuleDynamically: async (specifier, _, importAssertions) => { - const loader = asyncESM.esmLoader; - return loader.import(specifier, normalizeReferrerURL(filename), - importAssertions); + importModuleDynamically: async (specifier, _, importAttributes) => { + const cascadedLoader = getCascadedLoader(); + return cascadedLoader.import(specifier, normalizeReferrerURL(filename), + importAttributes); }, }); @@ -1183,10 +1279,10 @@ function wrapSafe(filename, content, cjsModuleInstance) { '__dirname', ], { filename, - importModuleDynamically(specifier, _, importAssertions) { - const loader = asyncESM.esmLoader; - return loader.import(specifier, normalizeReferrerURL(filename), - importAssertions); + importModuleDynamically(specifier, _, importAttributes) { + const cascadedLoader = getCascadedLoader(); + return cascadedLoader.import(specifier, normalizeReferrerURL(filename), + importAttributes); }, }); @@ -1197,20 +1293,24 @@ function wrapSafe(filename, content, cjsModuleInstance) { return result.function; } catch (err) { - if (process.mainModule === cjsModuleInstance) + if (process.mainModule === cjsModuleInstance) { + const { enrichCJSError } = require('internal/modules/esm/translators'); enrichCJSError(err, content); + } throw err; } } -// Run the file contents in the correct scope or sandbox. Expose -// the correct helper variables (require, module, exports) to -// the file. -// Returns exception, if any. +/** + * Run the file contents in the correct scope or sandbox. Expose the correct helper variables (`require`, `module`, + * `exports`) to the file. Returns exception, if any. + * @param {string} content The source code of the module + * @param {string} filename The file path of the module + */ Module.prototype._compile = function(content, filename) { let moduleURL; let redirects; - const manifest = policy?.manifest; + const manifest = policy()?.manifest; if (manifest) { moduleURL = pathToFileURL(filename); redirects = manifest.getDependencyMapper(moduleURL); @@ -1248,7 +1348,7 @@ Module.prototype._compile = function(content, filename) { const exports = this.exports; const thisValue = exports; const module = this; - if (requireDepth === 0) statCache = new SafeMap(); + if (requireDepth === 0) { statCache = new SafeMap(); } if (inspectorWrapper) { result = inspectorWrapper(compiledWrapper, thisValue, exports, require, module, filename, dirname); @@ -1257,11 +1357,15 @@ Module.prototype._compile = function(content, filename) { [exports, require, module, filename, dirname]); } hasLoadedAnyUserCJSModule = true; - if (requireDepth === 0) statCache = null; + if (requireDepth === 0) { statCache = null; } return result; }; -// Native extension for .js +/** + * Native handler for `.js` files. + * @param {Module} module The module to compile + * @param {string} filename The file path of the module + */ Module._extensions['.js'] = function(module, filename) { // If already analyzed the source, then it will be cached. const cached = cjsParseCache.get(module); @@ -1273,9 +1377,9 @@ Module._extensions['.js'] = function(module, filename) { content = fs.readFileSync(filename, 'utf8'); } if (StringPrototypeEndsWith(filename, '.js')) { - const pkg = readPackageScope(filename); + const pkg = packageJsonReader.readPackageScope(filename) || { __proto__: null }; // Function require shouldn't be used in ES modules. - if (pkg?.data?.type === 'module') { + if (pkg.data?.type === 'module') { const parent = moduleParentCache.get(module); const parentPath = parent?.filename; const packageJsonPath = path.resolve(pkg.path, 'package.json'); @@ -1310,14 +1414,18 @@ Module._extensions['.js'] = function(module, filename) { module._compile(content, filename); }; - -// Native extension for .json +/** + * Native handler for `.json` files. + * @param {Module} module The module to compile + * @param {string} filename The file path of the module + */ Module._extensions['.json'] = function(module, filename) { const content = fs.readFileSync(filename, 'utf8'); - if (policy?.manifest) { + const manifest = policy()?.manifest; + if (manifest) { const moduleURL = pathToFileURL(filename); - policy.manifest.assertIntegrity(moduleURL, content); + manifest.assertIntegrity(moduleURL, content); } try { @@ -1328,18 +1436,26 @@ Module._extensions['.json'] = function(module, filename) { } }; - -// Native extension for .node +/** + * Native handler for `.node` files. + * @param {Module} module The module to compile + * @param {string} filename The file path of the module + */ Module._extensions['.node'] = function(module, filename) { - if (policy?.manifest) { + const manifest = policy()?.manifest; + if (manifest) { const content = fs.readFileSync(filename); const moduleURL = pathToFileURL(filename); - policy.manifest.assertIntegrity(moduleURL, content); + manifest.assertIntegrity(moduleURL, content); } // Be aware this doesn't use `content` return process.dlopen(module, path.toNamespacedPath(filename)); }; +/** + * Creates a `require` function that can be used to load modules from the specified path. + * @param {string} filename The path to the module + */ function createRequireFromPath(filename) { // Allow a directory to be passed as the filename const trailingSlash = @@ -1360,6 +1476,12 @@ function createRequireFromPath(filename) { const createRequireError = 'must be a file URL object, file URL string, or ' + 'absolute path string'; +/** + * Creates a new `require` function that can be used to load modules. + * @param {string | URL} filename The path or URL to the module context for this `require` + * @throws {ERR_INVALID_ARG_VALUE} If `filename` is not a string or URL, or if it is a relative path that cannot be + * resolved to an absolute path. + */ function createRequire(filename) { let filepath; @@ -1381,6 +1503,9 @@ function createRequire(filename) { Module.createRequire = createRequire; +/** + * Define the paths to use for resolving a module. + */ Module._initPaths = function() { const homeDir = isWindows ? process.env.USERPROFILE : safeGetenv('HOME'); const nodePath = isWindows ? process.env.NODE_PATH : safeGetenv('NODE_PATH'); @@ -1411,9 +1536,12 @@ Module._initPaths = function() { Module.globalPaths = ArrayPrototypeSlice(modulePaths); }; +/** + * Handle modules loaded via `--require`. + * @param {string[]} requests The values of `--require` + */ Module._preloadModules = function(requests) { - if (!ArrayIsArray(requests)) - return; + if (!ArrayIsArray(requests)) { return; } isPreloading = true; @@ -1429,28 +1557,28 @@ Module._preloadModules = function(requests) { throw e; } } - for (let n = 0; n < requests.length; n++) + for (let n = 0; n < requests.length; n++) { internalRequire(parent, requests[n]); + } isPreloading = false; }; +/** + * If the user has overridden an export from a builtin module, this function can ensure that the override is used in + * both CommonJS and ES module contexts. + */ Module.syncBuiltinESMExports = function syncBuiltinESMExports() { for (const mod of BuiltinModule.map.values()) { - if (mod.canBeRequiredByUsers && - BuiltinModule.canBeRequiredWithoutScheme(mod.id)) { + if (BuiltinModule.canBeRequiredWithoutScheme(mod.id)) { mod.syncExports(); } } }; -Module.isBuiltin = function isBuiltin(moduleName) { - return allBuiltins.has(moduleName); -}; - ObjectDefineProperty(Module.prototype, 'constructor', { __proto__: null, get: function() { - return policy ? undefined : Module; + return policy() ? undefined : Module; }, configurable: false, enumerable: false, diff --git a/lib/internal/modules/esm/assert.js b/lib/internal/modules/esm/assert.js index b1267a10a7a6b2..ce3280de84bf4d 100644 --- a/lib/internal/modules/esm/assert.js +++ b/lib/internal/modules/esm/assert.js @@ -3,7 +3,6 @@ const { ArrayPrototypeFilter, ArrayPrototypeIncludes, - ObjectCreate, ObjectKeys, ObjectValues, ObjectPrototypeHasOwnProperty, @@ -14,16 +13,15 @@ const { ERR_IMPORT_ASSERTION_TYPE_FAILED, ERR_IMPORT_ASSERTION_TYPE_MISSING, ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED, + ERR_IMPORT_ATTRIBUTE_UNSUPPORTED, } = require('internal/errors').codes; // The HTML spec has an implied default type of `'javascript'`. const kImplicitAssertType = 'javascript'; -let alreadyWarned = false; - /** - * Define a map of module formats to import assertion types (the value of - * `type` in `assert { type: 'json' }`). + * Define a map of module formats to import attributes types (the value of + * `type` in `with { type: 'json' }`). * @type {Map} */ const formatTypeMap = { @@ -32,13 +30,13 @@ const formatTypeMap = { 'commonjs': kImplicitAssertType, 'json': 'json', 'module': kImplicitAssertType, - 'wasm': kImplicitAssertType, // It's unclear whether the HTML spec will require an assertion type or not for Wasm; see https://github.com/WebAssembly/esm-integration/issues/42 + 'wasm': kImplicitAssertType, // It's unclear whether the HTML spec will require an attribute type or not for Wasm; see https://github.com/WebAssembly/esm-integration/issues/42 }; /** * The HTML spec disallows the default type to be explicitly specified * (for now); so `import './file.js'` is okay but - * `import './file.js' assert { type: 'javascript' }` throws. + * `import './file.js' with { type: 'javascript' }` throws. * @type {Array} */ const supportedAssertionTypes = ArrayPrototypeFilter( @@ -47,54 +45,50 @@ const supportedAssertionTypes = ArrayPrototypeFilter( /** - * Test a module's import assertions. + * Test a module's import attributes. * @param {string} url The URL of the imported module, for error reporting. * @param {string} format One of Node's supported translators - * @param {Record} importAssertions Validations for the + * @param {Record} importAttributes Validations for the * module import. * @returns {true} * @throws {TypeError} If the format and assertion type are incompatible. */ -function validateAssertions(url, format, - importAssertions = ObjectCreate(null)) { - const validType = formatTypeMap[format]; - - if (!alreadyWarned && ObjectKeys(importAssertions).length !== 0) { - alreadyWarned = true; - process.emitWarning( - 'Import assertions are not a stable feature of the JavaScript language. ' + - 'Avoid relying on their current behavior and syntax as those might change ' + - 'in a future version of Node.js.', - 'ExperimentalWarning', - ); +function validateAttributes(url, format, + importAttributes = { __proto__: null }) { + const keys = ObjectKeys(importAttributes); + for (let i = 0; i < keys.length; i++) { + if (keys[i] !== 'type') { + throw new ERR_IMPORT_ATTRIBUTE_UNSUPPORTED(keys[i], importAttributes[keys[i]]); + } } + const validType = formatTypeMap[format]; switch (validType) { case undefined: - // Ignore assertions for module formats we don't recognize, to allow new + // Ignore attributes for module formats we don't recognize, to allow new // formats in the future. return true; case kImplicitAssertType: // This format doesn't allow an import assertion type, so the property - // must not be set on the import assertions object. - if (!ObjectPrototypeHasOwnProperty(importAssertions, 'type')) { + // must not be set on the import attributes object. + if (!ObjectPrototypeHasOwnProperty(importAttributes, 'type')) { return true; } - return handleInvalidType(url, importAssertions.type); + return handleInvalidType(url, importAttributes.type); - case importAssertions.type: + case importAttributes.type: // The asserted type is the valid type for this format. return true; default: // There is an expected type for this format, but the value of - // `importAssertions.type` might not have been it. - if (!ObjectPrototypeHasOwnProperty(importAssertions, 'type')) { + // `importAttributes.type` might not have been it. + if (!ObjectPrototypeHasOwnProperty(importAttributes, 'type')) { // `type` wasn't specified at all. throw new ERR_IMPORT_ASSERTION_TYPE_MISSING(url, validType); } - return handleInvalidType(url, importAssertions.type); + return handleInvalidType(url, importAttributes.type); } } @@ -119,5 +113,5 @@ function handleInvalidType(url, type) { module.exports = { kImplicitAssertType, - validateAssertions, + validateAttributes, }; diff --git a/lib/internal/modules/esm/create_dynamic_module.js b/lib/internal/modules/esm/create_dynamic_module.js index c99da19d5c8271..c0060c47e93b5a 100644 --- a/lib/internal/modules/esm/create_dynamic_module.js +++ b/lib/internal/modules/esm/create_dynamic_module.js @@ -12,12 +12,22 @@ let debug = require('internal/util/debuglog').debuglog('esm', (fn) => { debug = fn; }); +/** + * Creates an import statement for a given module path and index. + * @param {string} impt - The module path to import. + * @param {number} index - The index of the import statement. + */ function createImport(impt, index) { const imptPath = JSONStringify(impt); return `import * as $import_${index} from ${imptPath}; import.meta.imports[${imptPath}] = $import_${index};`; } +/** + * Creates an export for a given module. + * @param {string} expt - The name of the export. + * @param {number} index - The index of the export statement. + */ function createExport(expt, index) { const nameStringLit = JSONStringify(expt); return `let $export_${index}; @@ -28,6 +38,17 @@ import.meta.exports[${nameStringLit}] = { };`; } +/** + * Creates a dynamic module with the given imports, exports, URL, and evaluate function. + * @param {string[]} imports - An array of imports. + * @param {string[]} exports - An array of exports. + * @param {string} [url=''] - The URL of the module. + * @param {(reflect: DynamicModuleReflect) => void} evaluate - The function to evaluate the module. + * @typedef {object} DynamicModuleReflect + * @property {string[]} imports - The imports of the module. + * @property {string[]} exports - The exports of the module. + * @property {(cb: (reflect: DynamicModuleReflect) => void) => void} onReady - Callback to evaluate the module. + */ const createDynamicModule = (imports, exports, url = '', evaluate) => { debug('creating ESM facade for %s with exports: %j', url, exports); const source = ` @@ -35,23 +56,26 @@ ${ArrayPrototypeJoin(ArrayPrototypeMap(imports, createImport), '\n')} ${ArrayPrototypeJoin(ArrayPrototypeMap(exports, createExport), '\n')} import.meta.done(); `; - const { ModuleWrap, callbackMap } = internalBinding('module_wrap'); + const { ModuleWrap } = internalBinding('module_wrap'); const m = new ModuleWrap(`${url}`, undefined, source, 0, 0); const readyfns = new SafeSet(); + /** @type {DynamicModuleReflect} */ const reflect = { exports: ObjectCreate(null), onReady: (cb) => { readyfns.add(cb); }, }; - if (imports.length) - reflect.imports = ObjectCreate(null); - - callbackMap.set(m, { + if (imports.length) { + reflect.imports = { __proto__: null }; + } + const { setCallbackForWrap } = require('internal/modules/esm/utils'); + setCallbackForWrap(m, { initializeImportMeta: (meta, wrap) => { meta.exports = reflect.exports; - if (reflect.imports) + if (reflect.imports) { meta.imports = reflect.imports; + } meta.done = () => { evaluate(reflect); reflect.onReady = (cb) => cb(reflect); diff --git a/lib/internal/modules/esm/fetch_module.js b/lib/internal/modules/esm/fetch_module.js index 74d2d2599dbd45..21b7456899604f 100644 --- a/lib/internal/modules/esm/fetch_module.js +++ b/lib/internal/modules/esm/fetch_module.js @@ -44,37 +44,56 @@ const cacheForGET = new SafeMap(); // [2] Creating a new agent instead of using the gloabl agent improves // performance and precludes the agent becoming tainted. +/** @type {import('https').Agent} The Cached HTTP Agent for **secure** HTTP requests. */ let HTTPSAgent; -function HTTPSGet(url, opts) { +/** + * Make a HTTPs GET request (handling agent setup if needed, caching the agent to avoid + * redudant instantiations). + * @param {Parameters[0]} input - The URI to fetch. + * @param {Parameters[1]} options - See https.get() options. + */ +function HTTPSGet(input, options) { const https = require('https'); // [1] HTTPSAgent ??= new https.Agent({ // [2] keepAlive: true, }); - return https.get(url, { + return https.get(input, { agent: HTTPSAgent, - ...opts, + ...options, }); } +/** @type {import('https').Agent} The Cached HTTP Agent for **insecure** HTTP requests. */ let HTTPAgent; -function HTTPGet(url, opts) { +/** + * Make a HTTP GET request (handling agent setup if needed, caching the agent to avoid + * redudant instantiations). + * @param {Parameters[0]} input - The URI to fetch. + * @param {Parameters[1]} options - See http.get() options. + */ +function HTTPGet(input, options) { const http = require('http'); // [1] HTTPAgent ??= new http.Agent({ // [2] keepAlive: true, }); - return http.get(url, { + return http.get(input, { agent: HTTPAgent, - ...opts, + ...options, }); } -function dnsLookup(name, opts) { +/** @type {import('../../dns/promises.js').lookup} */ +function dnsLookup(hostname, options) { // eslint-disable-next-line no-func-assign dnsLookup = require('dns/promises').lookup; - return dnsLookup(name, opts); + return dnsLookup(hostname, options); } let zlib; +/** + * Create a decompressor for the Brotli format. + * @returns {import('zlib').BrotliDecompress} + */ function createBrotliDecompress() { zlib ??= require('zlib'); // [1] // eslint-disable-next-line no-func-assign @@ -82,6 +101,10 @@ function createBrotliDecompress() { return createBrotliDecompress(); } +/** + * Create an unzip handler. + * @returns {import('zlib').Unzip} + */ function createUnzip() { zlib ??= require('zlib'); // [1] // eslint-disable-next-line no-func-assign @@ -144,7 +167,7 @@ function fetchWithRedirects(parsed) { return entry; } if (res.statusCode === 404) { - const err = new ERR_MODULE_NOT_FOUND(parsed.href, null); + const err = new ERR_MODULE_NOT_FOUND(parsed.href, null, parsed); err.message = `Cannot find module '${parsed.href}', HTTP 404`; throw err; } diff --git a/lib/internal/modules/esm/formats.js b/lib/internal/modules/esm/formats.js index b52a31ff54080e..f56da5de7cbf56 100644 --- a/lib/internal/modules/esm/formats.js +++ b/lib/internal/modules/esm/formats.js @@ -2,9 +2,11 @@ const { RegExpPrototypeExec, + Uint8Array, } = primordials; const { getOptionValue } = require('internal/options'); +const { closeSync, openSync, readSync } = require('fs'); const experimentalWasmModules = getOptionValue('--experimental-wasm-modules'); @@ -36,12 +38,12 @@ if (experimentalWasmModules) { function mimeToFormat(mime) { if ( RegExpPrototypeExec( - /\s*(text|application)\/javascript\s*(;\s*charset=utf-?8\s*)?/i, + /^\s*(text|application)\/javascript\s*(;\s*charset=utf-?8\s*)?$/i, mime, ) !== null - ) return 'module'; - if (mime === 'application/json') return 'json'; - if (experimentalWasmModules && mime === 'application/wasm') return 'wasm'; + ) { return 'module'; } + if (mime === 'application/json') { return 'json'; } + if (experimentalWasmModules && mime === 'application/wasm') { return 'wasm'; } return null; } @@ -49,8 +51,34 @@ function getLegacyExtensionFormat(ext) { return legacyExtensionFormatMap[ext]; } +/** + * For extensionless files in a `module` package scope, or a default `module` scope enabled by the + * `--experimental-default-type` flag, we check the file contents to disambiguate between ES module JavaScript and Wasm. + * We do this by taking advantage of the fact that all Wasm files start with the header `0x00 0x61 0x73 0x6d` (`_asm`). + * @param {URL} url + */ +function getFormatOfExtensionlessFile(url) { + if (!experimentalWasmModules) { return 'module'; } + + const magic = new Uint8Array(4); + let fd; + try { + // TODO(@anonrig): Optimize the following by having a single C++ call + fd = openSync(url); + readSync(fd, magic, 0, 4); // Only read the first four bytes + if (magic[0] === 0x00 && magic[1] === 0x61 && magic[2] === 0x73 && magic[3] === 0x6d) { + return 'wasm'; + } + } finally { + if (fd !== undefined) { closeSync(fd); } + } + + return 'module'; +} + module.exports = { extensionFormatMap, + getFormatOfExtensionlessFile, getLegacyExtensionFormat, legacyExtensionFormatMap, mimeToFormat, diff --git a/lib/internal/modules/esm/get_format.js b/lib/internal/modules/esm/get_format.js index 219ef03a21214d..9ad0110b0c3716 100644 --- a/lib/internal/modules/esm/get_format.js +++ b/lib/internal/modules/esm/get_format.js @@ -1,16 +1,18 @@ 'use strict'; + const { RegExpPrototypeExec, ObjectPrototypeHasOwnProperty, PromisePrototypeThen, PromiseResolve, + StringPrototypeIncludes, + StringPrototypeCharCodeAt, StringPrototypeSlice, } = primordials; -const { basename, extname, relative } = require('path'); const { getOptionValue } = require('internal/options'); -const { fetchModule } = require('internal/modules/esm/fetch_module'); const { extensionFormatMap, + getFormatOfExtensionlessFile, getLegacyExtensionFormat, mimeToFormat, } = require('internal/modules/esm/formats'); @@ -19,7 +21,10 @@ const experimentalNetworkImports = getOptionValue('--experimental-network-imports'); const experimentalSpecifierResolution = getOptionValue('--experimental-specifier-resolution'); -const { getPackageType, getPackageScopeConfig } = require('internal/modules/esm/resolve'); +const defaultTypeFlag = getOptionValue('--experimental-default-type'); +// The next line is where we flip the default to ES modules someday. +const defaultType = defaultTypeFlag === 'module' ? 'module' : 'commonjs'; +const { getPackageType } = require('internal/modules/esm/resolve'); const { fileURLToPath } = require('internal/url'); const { ERR_UNKNOWN_FILE_EXTENSION } = require('internal/errors').codes; @@ -45,6 +50,42 @@ function getDataProtocolModuleFormat(parsed) { return mimeToFormat(mime); } +const DOT_CODE = 46; +const SLASH_CODE = 47; + +/** + * Returns the file extension from a URL. Should give similar result to + * `require('node:path').extname(require('node:url').fileURLToPath(url))` + * when used with a `file:` URL. + * @param {URL} url + * @returns {string} + */ +function extname(url) { + const { pathname } = url; + for (let i = pathname.length - 1; i > 0; i--) { + switch (StringPrototypeCharCodeAt(pathname, i)) { + case SLASH_CODE: + return ''; + + case DOT_CODE: + return StringPrototypeCharCodeAt(pathname, i - 1) === SLASH_CODE ? '' : StringPrototypeSlice(pathname, i); + } + } + return ''; +} + +/** + * Determine whether the given file URL is under a `node_modules` folder. + * This function assumes that the input has already been verified to be a `file:` URL, + * and is a file rather than a folder. + * @param {URL} url + */ +function underNodeModules(url) { + if (url.protocol !== 'file:') { return false; } // We determine module types for other protocols based on MIME header + + return StringPrototypeIncludes(url.pathname, '/node_modules/'); +} + /** * @param {URL} url * @param {{parentURL: string}} context @@ -52,31 +93,47 @@ function getDataProtocolModuleFormat(parsed) { * @returns {string} */ function getFileProtocolModuleFormat(url, context, ignoreErrors) { - const filepath = fileURLToPath(url); - const ext = extname(filepath); + const ext = extname(url); + if (ext === '.js') { - return getPackageType(url) === 'module' ? 'module' : 'commonjs'; + const packageType = getPackageType(url); + if (packageType !== 'none') { + return packageType; + } + // The controlling `package.json` file has no `type` field. + if (defaultType === 'module') { + // An exception to the type flag making ESM the default everywhere is that package scopes under `node_modules` + // should retain the assumption that a lack of a `type` field means CommonJS. + return underNodeModules(url) ? 'commonjs' : 'module'; + } + return 'commonjs'; + } + + if (ext === '') { + const packageType = getPackageType(url); + if (defaultType === 'commonjs') { // Legacy behavior + if (packageType === 'none' || packageType === 'commonjs') { + return 'commonjs'; + } // Else packageType === 'module' + return getFormatOfExtensionlessFile(url); + } // Else defaultType === 'module' + if (underNodeModules(url)) { // Exception for package scopes under `node_modules` + return packageType === 'module' ? getFormatOfExtensionlessFile(url) : 'commonjs'; + } + if (packageType === 'none' || packageType === 'module') { + return getFormatOfExtensionlessFile(url); + } // Else packageType === 'commonjs' + return 'commonjs'; } const format = extensionFormatMap[ext]; - if (format) return format; + if (format) { return format; } if (experimentalSpecifierResolution !== 'node') { // Explicit undefined return indicates load hook should rerun format check - if (ignoreErrors) return undefined; - let suggestion = ''; - if (getPackageType(url) === 'module' && ext === '') { - const config = getPackageScopeConfig(url); - const fileBasename = basename(filepath); - const relativePath = StringPrototypeSlice(relative(config.pjsonPath, filepath), 1); - suggestion = 'Loading extensionless files is not supported inside of ' + - '"type":"module" package.json contexts. The package.json file ' + - `${config.pjsonPath} caused this "type":"module" context. Try ` + - `changing ${filepath} to have a file extension. Note the "bin" ` + - 'field of package.json can point to a file with an extension, for example ' + - `{"type":"module","bin":{"${fileBasename}":"${relativePath}.js"}}`; - } - throw new ERR_UNKNOWN_FILE_EXTENSION(ext, filepath, suggestion); + if (ignoreErrors) { return undefined; } + const filepath = fileURLToPath(url); + throw new ERR_UNKNOWN_FILE_EXTENSION(ext, filepath); } return getLegacyExtensionFormat(ext) ?? null; @@ -89,6 +146,7 @@ function getFileProtocolModuleFormat(url, context, ignoreErrors) { */ function getHttpProtocolModuleFormat(url, context) { if (experimentalNetworkImports) { + const { fetchModule } = require('internal/modules/esm/fetch_module'); return PromisePrototypeThen( PromiseResolve(fetchModule(url, context)), (entry) => { @@ -128,4 +186,5 @@ module.exports = { defaultGetFormat, defaultGetFormatWithoutErrors, extensionFormatMap, + extname, }; diff --git a/lib/internal/modules/esm/handle_process_exit.js b/lib/internal/modules/esm/handle_process_exit.js index db830900bd3154..4febbcce54dd94 100644 --- a/lib/internal/modules/esm/handle_process_exit.js +++ b/lib/internal/modules/esm/handle_process_exit.js @@ -1,8 +1,10 @@ 'use strict'; -// Handle a Promise from running code that potentially does Top-Level Await. -// In that case, it makes sense to set the exit code to a specific non-zero -// value if the main code never finishes running. +/** + * Handle a Promise from running code that potentially does Top-Level Await. + * In that case, it makes sense to set the exit code to a specific non-zero value + * if the main code never finishes running. + */ function handleProcessExit() { process.exitCode ??= 13; } diff --git a/lib/internal/modules/esm/hooks.js b/lib/internal/modules/esm/hooks.js new file mode 100644 index 00000000000000..d6f7e04923bff2 --- /dev/null +++ b/lib/internal/modules/esm/hooks.js @@ -0,0 +1,878 @@ +'use strict'; + +const { + ArrayPrototypePush, + ArrayPrototypePushApply, + FunctionPrototypeCall, + Int32Array, + ObjectAssign, + ObjectDefineProperty, + ObjectSetPrototypeOf, + Promise, + ReflectSet, + SafeSet, + StringPrototypeSlice, + StringPrototypeStartsWith, + StringPrototypeToUpperCase, + globalThis, +} = primordials; + +const { + Atomics: { + load: AtomicsLoad, + wait: AtomicsWait, + waitAsync: AtomicsWaitAsync, + }, + SharedArrayBuffer, +} = globalThis; + +const { + ERR_INTERNAL_ASSERTION, + ERR_INVALID_ARG_TYPE, + ERR_INVALID_ARG_VALUE, + ERR_INVALID_RETURN_PROPERTY_VALUE, + ERR_INVALID_RETURN_VALUE, + ERR_LOADER_CHAIN_INCOMPLETE, + ERR_METHOD_NOT_IMPLEMENTED, + ERR_UNKNOWN_BUILTIN_MODULE, + ERR_WORKER_UNSERIALIZABLE_ERROR, +} = require('internal/errors').codes; +const { URL } = require('internal/url'); +const { canParse: URLCanParse } = internalBinding('url'); +const { receiveMessageOnPort } = require('worker_threads'); +const { + isAnyArrayBuffer, + isArrayBufferView, +} = require('internal/util/types'); +const { + validateObject, + validateString, +} = require('internal/validators'); +const { + emitExperimentalWarning, + kEmptyObject, +} = require('internal/util'); + +const { + defaultResolve, + throwIfInvalidParentURL, +} = require('internal/modules/esm/resolve'); +const { + getDefaultConditions, + loaderWorkerId, +} = require('internal/modules/esm/utils'); +const { deserializeError } = require('internal/error_serdes'); +const { + SHARED_MEMORY_BYTE_LENGTH, + WORKER_TO_MAIN_THREAD_NOTIFICATION, +} = require('internal/modules/esm/shared_constants'); +let debug = require('internal/util/debuglog').debuglog('esm', (fn) => { + debug = fn; +}); +let importMetaInitializer; + +let importAssertionAlreadyWarned = false; + +function emitImportAssertionWarning() { + if (!importAssertionAlreadyWarned) { + importAssertionAlreadyWarned = true; + process.emitWarning('Use `importAttributes` instead of `importAssertions`', 'ExperimentalWarning'); + } +} + +function defineImportAssertionAlias(context) { + return ObjectDefineProperty(context, 'importAssertions', { + __proto__: null, + configurable: true, + get() { + emitImportAssertionWarning(); + return this.importAttributes; + }, + set(value) { + emitImportAssertionWarning(); + return ReflectSet(this, 'importAttributes', value); + }, + }); +} + +/** + * @typedef {object} ExportedHooks + * @property {Function} initialize Customizations setup hook. + * @property {Function} globalPreload Global preload hook. + * @property {Function} resolve Resolve hook. + * @property {Function} load Load hook. + */ + +/** + * @typedef {object} KeyedHook + * @property {Function} fn The hook function. + * @property {URL['href']} url The URL of the module. + */ + +// [2] `validate...()`s throw the wrong error + +class Hooks { + #chains = { + /** + * Prior to ESM loading. These are called once before any modules are started. + * @private + * @property {KeyedHook[]} globalPreload Last-in-first-out list of preload hooks. + */ + globalPreload: [], + + /** + * Phase 1 of 2 in ESM loading. + * The output of the `resolve` chain of hooks is passed into the `load` chain of hooks. + * @private + * @property {KeyedHook[]} resolve Last-in-first-out collection of resolve hooks. + */ + resolve: [ + { + fn: defaultResolve, + url: 'node:internal/modules/esm/resolve', + }, + ], + + /** + * Phase 2 of 2 in ESM loading. + * @private + * @property {KeyedHook[]} load Last-in-first-out collection of loader hooks. + */ + load: [ + { + fn: require('internal/modules/esm/load').defaultLoad, + url: 'node:internal/modules/esm/load', + }, + ], + }; + + // Cache URLs we've already validated to avoid repeated validation + #validatedUrls = new SafeSet(); + + allowImportMetaResolve = false; + + /** + * Import and register custom/user-defined module loader hook(s). + * @param {string} urlOrSpecifier + * @param {string} parentURL + * @param {any} [data] Arbitrary data to be passed from the custom + * loader (user-land) to the worker. + */ + async register(urlOrSpecifier, parentURL, data) { + const moduleLoader = require('internal/process/esm_loader').esmLoader; + const keyedExports = await moduleLoader.import( + urlOrSpecifier, + parentURL, + kEmptyObject, + ); + await this.addCustomLoader(urlOrSpecifier, keyedExports, data); + } + + /** + * Collect custom/user-defined module loader hook(s). + * After all hooks have been collected, the global preload hook(s) must be initialized. + * @param {string} url Custom loader specifier + * @param {Record} exports + * @param {any} [data] Arbitrary data to be passed from the custom loader (user-land) + * to the worker. + * @returns {any | Promise} User data, ignored unless it's a promise, in which case it will be awaited. + */ + addCustomLoader(url, exports, data) { + const { + globalPreload, + initialize, + resolve, + load, + } = pluckHooks(exports); + + if (globalPreload && !initialize) { + emitExperimentalWarning( + '`globalPreload` is planned for removal in favor of `initialize`. `globalPreload`', + ); + ArrayPrototypePush(this.#chains.globalPreload, { __proto__: null, fn: globalPreload, url }); + } + if (resolve) { + const next = this.#chains.resolve[this.#chains.resolve.length - 1]; + ArrayPrototypePush(this.#chains.resolve, { __proto__: null, fn: resolve, url, next }); + } + if (load) { + const next = this.#chains.load[this.#chains.load.length - 1]; + ArrayPrototypePush(this.#chains.load, { __proto__: null, fn: load, url, next }); + } + return initialize?.(data); + } + + /** + * Initialize `globalPreload` hooks. + */ + initializeGlobalPreload() { + const preloadScripts = []; + for (let i = this.#chains.globalPreload.length - 1; i >= 0; i--) { + const { MessageChannel } = require('internal/worker/io'); + const channel = new MessageChannel(); + const { + port1: insidePreload, + port2: insideLoader, + } = channel; + + insidePreload.unref(); + insideLoader.unref(); + + const { + fn: preload, + url: specifier, + } = this.#chains.globalPreload[i]; + + const preloaded = preload({ + port: insideLoader, + }); + + if (preloaded == null) { continue; } + + if (typeof preloaded !== 'string') { // [2] + throw new ERR_INVALID_RETURN_VALUE( + 'a string', + `${specifier} globalPreload`, + preload, + ); + } + + ArrayPrototypePush(preloadScripts, { + code: preloaded, + port: insidePreload, + }); + } + return preloadScripts; + } + + /** + * Resolve the location of the module. + * + * Internally, this behaves like a backwards iterator, wherein the stack of + * hooks starts at the top and each call to `nextResolve()` moves down 1 step + * until it reaches the bottom or short-circuits. + * @param {string} originalSpecifier The specified URL path of the module to + * be resolved. + * @param {string} [parentURL] The URL path of the module's parent. + * @param {ImportAttributes} [importAttributes] Attributes from the import + * statement or expression. + * @returns {Promise<{ format: string, url: URL['href'] }>} + */ + async resolve( + originalSpecifier, + parentURL, + importAttributes = { __proto__: null }, + ) { + throwIfInvalidParentURL(parentURL); + + const chain = this.#chains.resolve; + const context = { + conditions: getDefaultConditions(), + importAttributes, + parentURL, + }; + const meta = { + chainFinished: null, + context, + hookErrIdentifier: '', + hookName: 'resolve', + shortCircuited: false, + }; + + const validateArgs = (hookErrIdentifier, suppliedSpecifier, ctx) => { + validateString( + suppliedSpecifier, + `${hookErrIdentifier} specifier`, + ); // non-strings can be coerced to a URL string + + if (ctx) { validateObject(ctx, `${hookErrIdentifier} context`); } + }; + const validateOutput = (hookErrIdentifier, output) => { + if (typeof output !== 'object' || output === null) { // [2] + throw new ERR_INVALID_RETURN_VALUE( + 'an object', + hookErrIdentifier, + output, + ); + } + }; + + const nextResolve = nextHookFactory(chain[chain.length - 1], meta, { validateArgs, validateOutput }); + + const resolution = await nextResolve(originalSpecifier, context); + const { hookErrIdentifier } = meta; // Retrieve the value after all settled + + validateOutput(hookErrIdentifier, resolution); + + if (resolution?.shortCircuit === true) { meta.shortCircuited = true; } + + if (!meta.chainFinished && !meta.shortCircuited) { + throw new ERR_LOADER_CHAIN_INCOMPLETE(hookErrIdentifier); + } + + let resolvedImportAttributes; + const { + format, + url, + } = resolution; + + if (typeof url !== 'string') { + // non-strings can be coerced to a URL string + // validateString() throws a less-specific error + throw new ERR_INVALID_RETURN_PROPERTY_VALUE( + 'a URL string', + hookErrIdentifier, + 'url', + url, + ); + } + + // Avoid expensive URL instantiation for known-good URLs + if (!this.#validatedUrls.has(url)) { + // No need to convert to string, since the type is already validated + if (!URLCanParse(url)) { + throw new ERR_INVALID_RETURN_PROPERTY_VALUE( + 'a URL string', + hookErrIdentifier, + 'url', + url, + ); + } + + this.#validatedUrls.add(url); + } + + if (!('importAttributes' in resolution) && ('importAssertions' in resolution)) { + emitImportAssertionWarning(); + resolvedImportAttributes = resolution.importAssertions; + } else { + resolvedImportAttributes = resolution.importAttributes; + } + + if ( + resolvedImportAttributes != null && + typeof resolvedImportAttributes !== 'object' + ) { + throw new ERR_INVALID_RETURN_PROPERTY_VALUE( + 'an object', + hookErrIdentifier, + 'importAttributes', + resolvedImportAttributes, + ); + } + + if ( + format != null && + typeof format !== 'string' // [2] + ) { + throw new ERR_INVALID_RETURN_PROPERTY_VALUE( + 'a string', + hookErrIdentifier, + 'format', + format, + ); + } + + return { + __proto__: null, + format, + importAttributes: resolvedImportAttributes, + url, + }; + } + + resolveSync(_originalSpecifier, _parentURL, _importAttributes) { + throw new ERR_METHOD_NOT_IMPLEMENTED('resolveSync()'); + } + + /** + * Provide source that is understood by one of Node's translators. + * + * Internally, this behaves like a backwards iterator, wherein the stack of + * hooks starts at the top and each call to `nextLoad()` moves down 1 step + * until it reaches the bottom or short-circuits. + * @param {URL['href']} url The URL/path of the module to be loaded + * @param {object} context Metadata about the module + * @returns {Promise<{ format: ModuleFormat, source: ModuleSource }>} + */ + async load(url, context = {}) { + const chain = this.#chains.load; + const meta = { + chainFinished: null, + context, + hookErrIdentifier: '', + hookName: 'load', + shortCircuited: false, + }; + + const validateArgs = (hookErrIdentifier, nextUrl, ctx) => { + if (typeof nextUrl !== 'string') { + // Non-strings can be coerced to a URL string + // validateString() throws a less-specific error + throw new ERR_INVALID_ARG_TYPE( + `${hookErrIdentifier} url`, + 'a URL string', + nextUrl, + ); + } + + // Avoid expensive URL instantiation for known-good URLs + if (!this.#validatedUrls.has(nextUrl)) { + // No need to convert to string, since the type is already validated + if (!URLCanParse(nextUrl)) { + throw new ERR_INVALID_ARG_VALUE( + `${hookErrIdentifier} url`, + nextUrl, + 'should be a URL string', + ); + } + + this.#validatedUrls.add(nextUrl); + } + + if (ctx) { validateObject(ctx, `${hookErrIdentifier} context`); } + }; + const validateOutput = (hookErrIdentifier, output) => { + if (typeof output !== 'object' || output === null) { // [2] + throw new ERR_INVALID_RETURN_VALUE( + 'an object', + hookErrIdentifier, + output, + ); + } + }; + + const nextLoad = nextHookFactory(chain[chain.length - 1], meta, { validateArgs, validateOutput }); + + const loaded = await nextLoad(url, defineImportAssertionAlias(context)); + const { hookErrIdentifier } = meta; // Retrieve the value after all settled + + validateOutput(hookErrIdentifier, loaded); + + if (loaded?.shortCircuit === true) { meta.shortCircuited = true; } + + if (!meta.chainFinished && !meta.shortCircuited) { + throw new ERR_LOADER_CHAIN_INCOMPLETE(hookErrIdentifier); + } + + const { + format, + source, + } = loaded; + let responseURL = loaded.responseURL; + + if (responseURL === undefined) { + responseURL = url; + } + + let responseURLObj; + if (typeof responseURL === 'string') { + try { + responseURLObj = new URL(responseURL); + } catch { + // responseURLObj not defined will throw in next branch. + } + } + + if (responseURLObj?.href !== responseURL) { + throw new ERR_INVALID_RETURN_PROPERTY_VALUE( + 'undefined or a fully resolved URL string', + hookErrIdentifier, + 'responseURL', + responseURL, + ); + } + + if (format == null) { + require('internal/modules/esm/load').throwUnknownModuleFormat(url, format); + } + + if (typeof format !== 'string') { // [2] + throw new ERR_INVALID_RETURN_PROPERTY_VALUE( + 'a string', + hookErrIdentifier, + 'format', + format, + ); + } + + if ( + source != null && + typeof source !== 'string' && + !isAnyArrayBuffer(source) && + !isArrayBufferView(source) + ) { + throw ERR_INVALID_RETURN_PROPERTY_VALUE( + 'a string, an ArrayBuffer, or a TypedArray', + hookErrIdentifier, + 'source', + source, + ); + } + + return { + __proto__: null, + format, + responseURL, + source, + }; + } + + forceLoadHooks() { + // No-op + } + + importMetaInitialize(meta, context, loader) { + importMetaInitializer ??= require('internal/modules/esm/initialize_import_meta').initializeImportMeta; + meta = importMetaInitializer(meta, context, loader); + return meta; + } +} +ObjectSetPrototypeOf(Hooks.prototype, null); + +/** + * There may be multiple instances of Hooks/HooksProxy, but there is only 1 Internal worker, so + * there is only 1 MessageChannel. + */ +let MessageChannel; +class HooksProxy { + /** + * Shared memory. Always use Atomics method to read or write to it. + * @type {Int32Array} + */ + #lock; + /** + * The InternalWorker instance, which lets us communicate with the loader thread. + */ + #worker; + + /** + * The last notification ID received from the worker. This is used to detect + * if the worker has already sent a notification before putting the main + * thread to sleep, to avoid a race condition. + * @type {number} + */ + #workerNotificationLastId = 0; + + /** + * Track how many async responses the main thread should expect. + * @type {number} + */ + #numberOfPendingAsyncResponses = 0; + + #isReady = false; + + constructor() { + const { InternalWorker } = require('internal/worker'); + MessageChannel ??= require('internal/worker/io').MessageChannel; + + const lock = new SharedArrayBuffer(SHARED_MEMORY_BYTE_LENGTH); + this.#lock = new Int32Array(lock); + + this.#worker = new InternalWorker(loaderWorkerId, { + stderr: false, + stdin: false, + stdout: false, + trackUnmanagedFds: false, + workerData: { + lock, + }, + }); + this.#worker.unref(); // ! Allows the process to eventually exit. + this.#worker.on('exit', process.exit); + } + + waitForWorker() { + if (!this.#isReady) { + const { kIsOnline } = require('internal/worker'); + if (!this.#worker[kIsOnline]) { + debug('wait for signal from worker'); + AtomicsWait(this.#lock, WORKER_TO_MAIN_THREAD_NOTIFICATION, 0); + const response = this.#worker.receiveMessageSync(); + if (response == null || response.message.status === 'exit') { return; } + const { preloadScripts } = this.#unwrapMessage(response); + this.#executePreloadScripts(preloadScripts); + } + + this.#isReady = true; + } + } + + /** + * Invoke a remote method asynchronously. + * @param {string} method Method to invoke + * @param {any[]} [transferList] Objects in `args` to be transferred + * @param {any[]} args Arguments to pass to `method` + * @returns {Promise} + */ + async makeAsyncRequest(method, transferList, ...args) { + this.waitForWorker(); + + MessageChannel ??= require('internal/worker/io').MessageChannel; + const asyncCommChannel = new MessageChannel(); + + // Pass work to the worker. + debug('post async message to worker', { method, args, transferList }); + const finalTransferList = [asyncCommChannel.port2]; + if (transferList) { + ArrayPrototypePushApply(finalTransferList, transferList); + } + this.#worker.postMessage({ + __proto__: null, + method, args, + port: asyncCommChannel.port2, + }, finalTransferList); + + if (this.#numberOfPendingAsyncResponses++ === 0) { + // On the next lines, the main thread will await a response from the worker thread that might + // come AFTER the last task in the event loop has run its course and there would be nothing + // left keeping the thread alive (and once the main thread dies, the whole process stops). + // However we want to keep the process alive until the worker thread responds (or until the + // event loop of the worker thread is also empty), so we ref the worker until we get all the + // responses back. + this.#worker.ref(); + } + + let response; + do { + debug('wait for async response from worker', { method, args }); + await AtomicsWaitAsync(this.#lock, WORKER_TO_MAIN_THREAD_NOTIFICATION, this.#workerNotificationLastId).value; + this.#workerNotificationLastId = AtomicsLoad(this.#lock, WORKER_TO_MAIN_THREAD_NOTIFICATION); + + response = receiveMessageOnPort(asyncCommChannel.port1); + } while (response == null); + debug('got async response from worker', { method, args }, this.#lock); + + if (--this.#numberOfPendingAsyncResponses === 0) { + // We got all the responses from the worker, its job is done (until next time). + this.#worker.unref(); + } + + const body = this.#unwrapMessage(response); + asyncCommChannel.port1.close(); + return body; + } + + /** + * Invoke a remote method synchronously. + * @param {string} method Method to invoke + * @param {any[]} [transferList] Objects in `args` to be transferred + * @param {any[]} args Arguments to pass to `method` + * @returns {any} + */ + makeSyncRequest(method, transferList, ...args) { + this.waitForWorker(); + + // Pass work to the worker. + debug('post sync message to worker', { method, args, transferList }); + this.#worker.postMessage({ __proto__: null, method, args }, transferList); + + let response; + do { + debug('wait for sync response from worker', { method, args }); + // Sleep until worker responds. + AtomicsWait(this.#lock, WORKER_TO_MAIN_THREAD_NOTIFICATION, this.#workerNotificationLastId); + this.#workerNotificationLastId = AtomicsLoad(this.#lock, WORKER_TO_MAIN_THREAD_NOTIFICATION); + + response = this.#worker.receiveMessageSync(); + } while (response == null); + debug('got sync response from worker', { method, args }); + if (response.message.status === 'never-settle') { + process.exit(13); + } else if (response.message.status === 'exit') { + process.exit(response.message.body); + } + return this.#unwrapMessage(response); + } + + #unwrapMessage(response) { + if (response.message.status === 'never-settle') { + return new Promise(() => {}); + } + const { status, body } = response.message; + if (status === 'error') { + if (body == null || typeof body !== 'object') { throw body; } + if (body.serializationFailed || body.serialized == null) { + throw ERR_WORKER_UNSERIALIZABLE_ERROR(); + } + + // eslint-disable-next-line no-restricted-syntax + throw deserializeError(body.serialized); + } else { + return body; + } + } + + #importMetaInitializer = require('internal/modules/esm/initialize_import_meta').initializeImportMeta; + + importMetaInitialize(meta, context, loader) { + this.#importMetaInitializer(meta, context, loader); + } + + #executePreloadScripts(preloadScripts) { + for (let i = 0; i < preloadScripts.length; i++) { + const { code, port } = preloadScripts[i]; + const { compileFunction } = require('vm'); + const preloadInit = compileFunction( + code, + ['getBuiltin', 'port', 'setImportMetaCallback'], + { + filename: '', + }, + ); + let finished = false; + let replacedImportMetaInitializer = false; + let next = this.#importMetaInitializer; + const { BuiltinModule } = require('internal/bootstrap/realm'); + // Calls the compiled preload source text gotten from the hook + // Since the parameters are named we use positional parameters + // see compileFunction above to cross reference the names + try { + FunctionPrototypeCall( + preloadInit, + globalThis, + // Param getBuiltin + (builtinName) => { + if (StringPrototypeStartsWith(builtinName, 'node:')) { + builtinName = StringPrototypeSlice(builtinName, 5); + } else if (!BuiltinModule.canBeRequiredWithoutScheme(builtinName)) { + throw new ERR_UNKNOWN_BUILTIN_MODULE(builtinName); + } + if (BuiltinModule.canBeRequiredByUsers(builtinName)) { + return require(builtinName); + } + throw new ERR_UNKNOWN_BUILTIN_MODULE(builtinName); + }, + // Param port + port, + // setImportMetaCallback + (fn) => { + if (finished || typeof fn !== 'function') { + throw new ERR_INVALID_ARG_TYPE('fn', fn); + } + replacedImportMetaInitializer = true; + const parent = next; + next = (meta, context) => { + return fn(meta, context, parent); + }; + }, + ); + } finally { + finished = true; + if (replacedImportMetaInitializer) { + this.#importMetaInitializer = next; + } + } + } + } +} +ObjectSetPrototypeOf(HooksProxy.prototype, null); + +/** + * A utility function to pluck the hooks from a user-defined loader. + * @param {import('./loader.js).ModuleExports} exports + * @returns {ExportedHooks} + */ +function pluckHooks({ + globalPreload, + initialize, + resolve, + load, +}) { + const acceptedHooks = { __proto__: null }; + + if (globalPreload) { + acceptedHooks.globalPreload = globalPreload; + } + if (resolve) { + acceptedHooks.resolve = resolve; + } + if (load) { + acceptedHooks.load = load; + } + + if (initialize) { + acceptedHooks.initialize = initialize; + } + + return acceptedHooks; +} + + +/** + * A utility function to iterate through a hook chain, track advancement in the + * chain, and generate and supply the `next` argument to the custom + * hook. + * @param {Hook} current The (currently) first hook in the chain (this shifts + * on every call). + * @param {object} meta Properties that change as the current hook advances + * along the chain. + * @param {boolean} meta.chainFinished Whether the end of the chain has been + * reached AND invoked. + * @param {string} meta.hookErrIdentifier A user-facing identifier to help + * pinpoint where an error occurred. Ex "file:///foo.mjs 'resolve'". + * @param {string} meta.hookName The kind of hook the chain is (ex 'resolve') + * @param {boolean} meta.shortCircuited Whether a hook signaled a short-circuit. + * @param {(hookErrIdentifier, hookArgs) => void} validate A wrapper function + * containing all validation of a custom loader hook's intermediary output. Any + * validation within MUST throw. + * @returns {function next(...hookArgs)} The next hook in the chain. + */ +function nextHookFactory(current, meta, { validateArgs, validateOutput }) { + // First, prepare the current + const { hookName } = meta; + const { + fn: hook, + url: hookFilePath, + next, + } = current; + + // ex 'nextResolve' + const nextHookName = `next${ + StringPrototypeToUpperCase(hookName[0]) + + StringPrototypeSlice(hookName, 1) + }`; + + let nextNextHook; + if (next) { + nextNextHook = nextHookFactory(next, meta, { validateArgs, validateOutput }); + } else { + // eslint-disable-next-line func-name-matching + nextNextHook = function chainAdvancedTooFar() { + throw new ERR_INTERNAL_ASSERTION( + `ESM custom loader '${hookName}' advanced beyond the end of the chain.`, + ); + }; + } + + return ObjectDefineProperty( + async (arg0 = undefined, context) => { + // Update only when hook is invoked to avoid fingering the wrong filePath + meta.hookErrIdentifier = `${hookFilePath} '${hookName}'`; + + validateArgs(`${meta.hookErrIdentifier} hook's ${nextHookName}()`, arg0, context); + + const outputErrIdentifier = `${hookFilePath} '${hookName}' hook's ${nextHookName}()`; + + // Set when next is actually called, not just generated. + if (!next) { meta.chainFinished = true; } + + if (context) { // `context` has already been validated, so no fancy check needed. + ObjectAssign(meta.context, context); + } + + const output = await hook(arg0, meta.context, nextNextHook); + validateOutput(outputErrIdentifier, output); + + if (output?.shortCircuit === true) { meta.shortCircuited = true; } + + return output; + }, + 'name', + { __proto__: null, value: nextHookName }, + ); +} + + +exports.Hooks = Hooks; +exports.HooksProxy = HooksProxy; diff --git a/lib/internal/modules/esm/initialize_import_meta.js b/lib/internal/modules/esm/initialize_import_meta.js index fe5ba4a3cc1248..f55f60a5b7647a 100644 --- a/lib/internal/modules/esm/initialize_import_meta.js +++ b/lib/internal/modules/esm/initialize_import_meta.js @@ -1,39 +1,63 @@ 'use strict'; const { getOptionValue } = require('internal/options'); -const experimentalImportMetaResolve = - getOptionValue('--experimental-import-meta-resolve'); -const { - PromisePrototypeThen, - PromiseReject, -} = primordials; -const asyncESM = require('internal/process/esm_loader'); - -function createImportMetaResolve(defaultParentUrl) { - return async function resolve(specifier, parentUrl = defaultParentUrl) { - return PromisePrototypeThen( - asyncESM.esmLoader.resolve(specifier, parentUrl), - ({ url }) => url, - (error) => ( - error.code === 'ERR_UNSUPPORTED_DIR_IMPORT' ? - error.url : PromiseReject(error)), - ); +const experimentalImportMetaResolve = getOptionValue('--experimental-import-meta-resolve'); + +/** + * Generate a function to be used as import.meta.resolve for a particular module. + * @param {string} defaultParentURL The default base to use for resolution + * @param {typeof import('./loader.js').ModuleLoader} loader Reference to the current module loader + * @param {bool} allowParentURL Whether to permit parentURL second argument for contextual resolution + * @returns {(specifier: string) => string} Function to assign to import.meta.resolve + */ +function createImportMetaResolve(defaultParentURL, loader, allowParentURL) { + /** + * @param {string} specifier + * @param {URL['href']} [parentURL] When `--experimental-import-meta-resolve` is specified, a + * second argument can be provided. + */ + return function resolve(specifier, parentURL = defaultParentURL) { + let url; + + if (!allowParentURL) { + parentURL = defaultParentURL; + } + + try { + ({ url } = loader.resolveSync(specifier, parentURL)); + return url; + } catch (error) { + switch (error?.code) { + case 'ERR_UNSUPPORTED_DIR_IMPORT': + case 'ERR_MODULE_NOT_FOUND': + ({ url } = error); + if (url) { + return url; + } + } + throw error; + } }; } /** + * Create the `import.meta` object for a module. * @param {object} meta * @param {{url: string}} context + * @param {typeof import('./loader.js').ModuleLoader} loader Reference to the current module loader + * @returns {{url: string, resolve?: Function}} */ -function initializeImportMeta(meta, context) { +function initializeImportMeta(meta, context, loader) { const { url } = context; // Alphabetical - if (experimentalImportMetaResolve) { - meta.resolve = createImportMetaResolve(url); + if (!loader || loader.allowImportMetaResolve) { + meta.resolve = createImportMetaResolve(url, loader, experimentalImportMetaResolve); } meta.url = url; + + return meta; } module.exports = { diff --git a/lib/internal/modules/esm/load.js b/lib/internal/modules/esm/load.js index 71a9f8da0b49f3..4b5ff362ed0c4a 100644 --- a/lib/internal/modules/esm/load.js +++ b/lib/internal/modules/esm/load.js @@ -5,11 +5,11 @@ const { RegExpPrototypeExec, decodeURIComponent, } = primordials; +const { kEmptyObject } = require('internal/util'); const { defaultGetFormat } = require('internal/modules/esm/get_format'); -const { validateAssertions } = require('internal/modules/esm/assert'); +const { validateAttributes, emitImportAssertionWarning } = require('internal/modules/esm/assert'); const { getOptionValue } = require('internal/options'); -const { fetchModule } = require('internal/modules/esm/fetch_module'); // Do not eagerly grab .manifest, it may be in TDZ const policy = getOptionValue('--experimental-policy') ? @@ -20,10 +20,10 @@ const experimentalNetworkImports = const { Buffer: { from: BufferFrom } } = require('buffer'); -const { readFile: readFileAsync } = require('internal/fs/promises').exports; const { URL } = require('internal/url'); const { ERR_INVALID_URL, + ERR_UNKNOWN_MODULE_FORMAT, ERR_UNSUPPORTED_ESM_URL_SCHEME, } = require('internal/errors').codes; @@ -39,6 +39,7 @@ async function getSource(url, context) { let responseURL = href; let source; if (protocol === 'file:') { + const { readFile: readFileAsync } = require('internal/fs/promises').exports; source = await readFileAsync(url); } else if (protocol === 'data:') { const match = RegExpPrototypeExec(DATA_URL_PATTERN, url.pathname); @@ -51,6 +52,7 @@ async function getSource(url, context) { protocol === 'https:' || protocol === 'http:' )) { + const { fetchModule } = require('internal/modules/esm/fetch_module'); const res = await fetchModule(url, context); source = await res.body; responseURL = res.resolvedHREF; @@ -74,21 +76,31 @@ async function getSource(url, context) { * @param {object} context * @returns {object} */ -async function defaultLoad(url, context) { +async function defaultLoad(url, context = kEmptyObject) { let responseURL = url; - const { importAssertions } = context; let { + importAttributes, format, source, } = context; + if (importAttributes == null && !('importAttributes' in context) && 'importAssertions' in context) { + emitImportAssertionWarning(); + importAttributes = context.importAssertions; + // Alias `importAssertions` to `importAttributes` + context = { + ...context, + importAttributes, + }; + } + const urlInstance = new URL(url); throwIfUnsupportedURLScheme(urlInstance, experimentalNetworkImports); format ??= await defaultGetFormat(urlInstance, context); - validateAssertions(url, format, importAssertions); + validateAttributes(url, format, importAttributes); if ( format === 'builtin' || @@ -107,6 +119,7 @@ async function defaultLoad(url, context) { }; } + /** * throws an error if the protocol is not one of the protocols * that can be loaded in the default loader @@ -137,6 +150,26 @@ function throwIfUnsupportedURLScheme(parsed, experimentalNetworkImports) { } } +/** + * For a falsy `format` returned from `load`, throw an error. + * This could happen from either a custom user loader _or_ from the default loader, because the default loader tries to + * determine formats for data URLs. + * @param {string} url The resolved URL of the module + * @param {null | undefined | false | 0 | -0 | 0n | ''} format Falsy format returned from `load` + */ +function throwUnknownModuleFormat(url, format) { + const dataUrl = RegExpPrototypeExec( + /^data:([^/]+\/[^;,]+)(?:[^,]*?)(;base64)?,/, + url, + ); + + throw new ERR_UNKNOWN_MODULE_FORMAT( + dataUrl ? dataUrl[1] : format, + url); +} + + module.exports = { defaultLoad, + throwUnknownModuleFormat, }; diff --git a/lib/internal/modules/esm/loader.js b/lib/internal/modules/esm/loader.js index 32b34ee8478e37..6e42f1a5db5a8a 100644 --- a/lib/internal/modules/esm/loader.js +++ b/lib/internal/modules/esm/loader.js @@ -4,79 +4,66 @@ require('internal/modules/cjs/loader'); const { - Array, - ArrayIsArray, ArrayPrototypeJoin, - ArrayPrototypePush, + ArrayPrototypeMap, + ArrayPrototypeReduce, FunctionPrototypeCall, - ObjectAssign, - ObjectCreate, - ObjectDefineProperty, + JSONStringify, ObjectSetPrototypeOf, - RegExpPrototypeExec, - SafePromiseAllReturnArrayLike, + RegExpPrototypeSymbolReplace, SafeWeakMap, - StringPrototypeSlice, - StringPrototypeToUpperCase, - globalThis, + encodeURIComponent, + hardenRegExp, } = primordials; -const { MessageChannel } = require('internal/worker/io'); const { - ERR_LOADER_CHAIN_INCOMPLETE, - ERR_INTERNAL_ASSERTION, - ERR_INVALID_ARG_TYPE, - ERR_INVALID_ARG_VALUE, - ERR_INVALID_RETURN_PROPERTY_VALUE, - ERR_INVALID_RETURN_VALUE, ERR_UNKNOWN_MODULE_FORMAT, } = require('internal/errors').codes; -const { pathToFileURL, isURL, URL } = require('internal/url'); +const { getOptionValue } = require('internal/options'); +const { pathToFileURL, isURL } = require('internal/url'); const { emitExperimentalWarning } = require('internal/util'); const { - isAnyArrayBuffer, - isArrayBufferView, -} = require('internal/util/types'); -const { - validateObject, - validateString, -} = require('internal/validators'); -const ModuleMap = require('internal/modules/esm/module_map'); -const ModuleJob = require('internal/modules/esm/module_job'); + getDefaultConditions, +} = require('internal/modules/esm/utils'); +let defaultResolve, defaultLoad, importMetaInitializer; -const { - defaultResolve, - DEFAULT_CONDITIONS, -} = require('internal/modules/esm/resolve'); -const { - initializeImportMeta, -} = require('internal/modules/esm/initialize_import_meta'); -const { defaultLoad } = require('internal/modules/esm/load'); -const { translators } = require( - 'internal/modules/esm/translators'); -const { getOptionValue } = require('internal/options'); +/** + * Lazy loads the module_map module and returns a new instance of ResolveCache. + * @returns {import('./module_map.js').ResolveCache')} + */ +function newResolveCache() { + const { ResolveCache } = require('internal/modules/esm/module_map'); + return new ResolveCache(); +} /** - * @typedef {object} ExportedHooks - * @property {Function} globalPreload Global preload hook. - * @property {Function} resolve Resolve hook. - * @property {Function} load Load hook. + * Generate a load cache (to store the final result of a load-chain for a particular module). + * @returns {import('./module_map.js').LoadCache')} */ +function newLoadCache() { + const { LoadCache } = require('internal/modules/esm/module_map'); + return new LoadCache(); +} /** - * @typedef {Record} ModuleExports + * Lazy-load translators to avoid potentially unnecessary work at startup (ex if ESM is not used). + * @returns {import('./translators.js').Translators} */ +function getTranslators() { + const { translators } = require('internal/modules/esm/translators'); + return translators; +} /** - * @typedef {object} KeyedExports - * @property {ModuleExports} exports The contents of the module. - * @property {URL['href']} url The URL of the module. + * @type {HooksProxy} + * Multiple loader instances exist for various, specific reasons (see code comments at site). + * In order to maintain consistency, we use a single worker (sandbox), which must sit apart of an + * individual loader instance. */ +let hooksProxy; /** - * @typedef {object} KeyedHook - * @property {Function} fn The hook function. - * @property {URL['href']} url The URL of the module. + * @typedef {Record} ModuleExports */ /** @@ -87,132 +74,18 @@ const { getOptionValue } = require('internal/options'); * @typedef {ArrayBuffer|TypedArray|string} ModuleSource */ -// [2] `validate...()`s throw the wrong error - let emittedSpecifierResolutionWarning = false; /** - * A utility function to iterate through a hook chain, track advancement in the - * chain, and generate and supply the `next` argument to the custom - * hook. - * @param {KeyedHook[]} chain The whole hook chain. - * @param {object} meta Properties that change as the current hook advances - * along the chain. - * @param {boolean} meta.chainFinished Whether the end of the chain has been - * reached AND invoked. - * @param {string} meta.hookErrIdentifier A user-facing identifier to help - * pinpoint where an error occurred. Ex "file:///foo.mjs 'resolve'". - * @param {number} meta.hookIndex A non-negative integer tracking the current - * position in the hook chain. - * @param {string} meta.hookName The kind of hook the chain is (ex 'resolve') - * @param {boolean} meta.shortCircuited Whether a hook signaled a short-circuit. - * @param {(hookErrIdentifier, hookArgs) => void} validate A wrapper function - * containing all validation of a custom loader hook's intermediary output. Any - * validation within MUST throw. - * @returns {function next(...hookArgs)} The next hook in the chain. - */ -function nextHookFactory(chain, meta, { validateArgs, validateOutput }) { - // First, prepare the current - const { hookName } = meta; - const { - fn: hook, - url: hookFilePath, - } = chain[meta.hookIndex]; - - // ex 'nextResolve' - const nextHookName = `next${ - StringPrototypeToUpperCase(hookName[0]) + - StringPrototypeSlice(hookName, 1) - }`; - - // When hookIndex is 0, it's reached the default, which does not call next() - // so feed it a noop that blows up if called, so the problem is obvious. - const generatedHookIndex = meta.hookIndex; - let nextNextHook; - if (meta.hookIndex > 0) { - // Now, prepare the next: decrement the pointer so the next call to the - // factory generates the next link in the chain. - meta.hookIndex--; - - nextNextHook = nextHookFactory(chain, meta, { validateArgs, validateOutput }); - } else { - // eslint-disable-next-line func-name-matching - nextNextHook = function chainAdvancedTooFar() { - throw new ERR_INTERNAL_ASSERTION( - `ESM custom loader '${hookName}' advanced beyond the end of the chain.`, - ); - }; - } - - return ObjectDefineProperty( - async (arg0 = undefined, context) => { - // Update only when hook is invoked to avoid fingering the wrong filePath - meta.hookErrIdentifier = `${hookFilePath} '${hookName}'`; - - validateArgs(`${meta.hookErrIdentifier} hook's ${nextHookName}()`, arg0, context); - - const outputErrIdentifier = `${chain[generatedHookIndex].url} '${hookName}' hook's ${nextHookName}()`; - - // Set when next is actually called, not just generated. - if (generatedHookIndex === 0) { meta.chainFinished = true; } - - if (context) { // `context` has already been validated, so no fancy check needed. - ObjectAssign(meta.context, context); - } - - const output = await hook(arg0, meta.context, nextNextHook); - - validateOutput(outputErrIdentifier, output); - - if (output?.shortCircuit === true) { meta.shortCircuited = true; } - return output; - - }, - 'name', - { __proto__: null, value: nextHookName }, - ); -} - -/** - * An ESMLoader instance is used as the main entry point for loading ES modules. - * Currently, this is a singleton -- there is only one used for loading - * the main module and everything in its dependency graph. + * This class covers the base machinery of module loading. To add custom + * behavior you can pass a customizations object and this object will be + * used to do the loading/resolving/registration process. */ -class ESMLoader { - #hooks = { - /** - * Prior to ESM loading. These are called once before any modules are started. - * @private - * @property {KeyedHook[]} globalPreload Last-in-first-out list of preload hooks. - */ - globalPreload: [], - - /** - * Phase 2 of 2 in ESM loading (phase 1 is below). - * @private - * @property {KeyedHook[]} load Last-in-first-out collection of loader hooks. - */ - load: [ - { - fn: defaultLoad, - url: 'node:internal/modules/esm/load', - }, - ], - - /** - * Phase 1 of 2 in ESM loading. - * @private - * @property {KeyedHook[]} resolve Last-in-first-out collection of resolve hooks. - */ - resolve: [ - { - fn: defaultResolve, - url: 'node:internal/modules/esm/resolve', - }, - ], - }; - - #importMetaInitializer = initializeImportMeta; +class ModuleLoader { + /** + * The conditions for resolving packages if `--conditions` is not used. + */ + #defaultConditions = getDefaultConditions(); /** * Map of already-loaded CJS modules to use @@ -224,20 +97,40 @@ class ESMLoader { */ evalIndex = 0; + /** + * Registry of resolved specifiers + */ + #resolveCache = newResolveCache(); + /** * Registry of loaded modules, akin to `require.cache` */ - moduleMap = new ModuleMap(); + loadCache = newLoadCache(); /** * Methods which translate input code or other information into ES modules */ - translators = translators; + translators = getTranslators(); - constructor() { - if (getOptionValue('--experimental-loader').length > 0) { - emitExperimentalWarning('Custom ESM Loaders'); - } + /** + * Truthy to allow the use of `import.meta.resolve`. This is needed + * currently because the `Hooks` class does not have `resolveSync` + * implemented and `import.meta.resolve` requires it. + */ + allowImportMetaResolve; + + /** + * Customizations to pass requests to. + * + * Note that this value _MUST_ be set with `setCustomizations` + * because it needs to copy `customizations.allowImportMetaResolve` + * to this property and failure to do so will cause undefined + * behavior when invoking `import.meta.resolve`. + * @see {ModuleLoader.setCustomizations} + */ + #customizations; + + constructor(customizations) { if (getOptionValue('--experimental-network-imports')) { emitExperimentalWarning('Network Imports'); } @@ -251,122 +144,64 @@ class ESMLoader { ); emittedSpecifierResolutionWarning = true; } + this.setCustomizations(customizations); } /** + * Change the currently activate customizations for this module + * loader to be the provided `customizations`. * - * @param {ModuleExports} exports - * @returns {ExportedHooks} - */ - static pluckHooks({ - globalPreload, - resolve, - load, - // obsolete hooks: - dynamicInstantiate, - getFormat, - getGlobalPreloadCode, - getSource, - transformSource, - }) { - const obsoleteHooks = []; - const acceptedHooks = ObjectCreate(null); - - if (getGlobalPreloadCode) { - globalPreload ??= getGlobalPreloadCode; - - process.emitWarning( - 'Loader hook "getGlobalPreloadCode" has been renamed to "globalPreload"', - ); - } - if (dynamicInstantiate) ArrayPrototypePush( - obsoleteHooks, - 'dynamicInstantiate', - ); - if (getFormat) ArrayPrototypePush( - obsoleteHooks, - 'getFormat', - ); - if (getSource) ArrayPrototypePush( - obsoleteHooks, - 'getSource', - ); - if (transformSource) ArrayPrototypePush( - obsoleteHooks, - 'transformSource', - ); - - if (obsoleteHooks.length) process.emitWarning( - `Obsolete loader hook(s) supplied and will be ignored: ${ - ArrayPrototypeJoin(obsoleteHooks, ', ') - }`, - 'DeprecationWarning', - ); - - if (globalPreload) { - acceptedHooks.globalPreload = globalPreload; - } - if (resolve) { - acceptedHooks.resolve = resolve; - } - if (load) { - acceptedHooks.load = load; - } - - return acceptedHooks; - } - - /** - * Collect custom/user-defined hook(s). After all hooks have been collected, - * calls global preload hook(s). - * @param {KeyedExports} customLoaders - * A list of exports from user-defined loaders (as returned by - * ESMLoader.import()). + * If present, this class customizes its core functionality to the + * `customizations` object, including registration, loading, and resolving. + * There are some responsibilities that this class _always_ takes + * care of, like validating outputs, so that the customizations object + * does not have to do so. + * + * The customizations object has the shape: + * + * ```ts + * interface LoadResult { + * format: ModuleFormat; + * source: ModuleSource; + * } + * + * interface ResolveResult { + * format: string; + * url: URL['href']; + * } + * + * interface Customizations { + * allowImportMetaResolve: boolean; + * load(url: string, context: object): Promise + * resolve( + * originalSpecifier: + * string, parentURL: string, + * importAttributes: Record + * ): Promise + * resolveSync( + * originalSpecifier: + * string, parentURL: string, + * importAttributes: Record + * ) ResolveResult; + * register(specifier: string, parentURL: string): any; + * forceLoadHooks(): void; + * } + * ``` + * + * Note that this class _also_ implements the `Customizations` + * interface, as does `CustomizedModuleLoader` and `Hooks`. + * + * Calling this function alters how modules are loaded and should be + * invoked with care. + * @param {object} customizations */ - addCustomLoaders( - customLoaders = [], - ) { - for (let i = 0; i < customLoaders.length; i++) { - const { - exports, - url, - } = customLoaders[i]; - const { - globalPreload, - resolve, - load, - } = ESMLoader.pluckHooks(exports); - - if (globalPreload) { - ArrayPrototypePush( - this.#hooks.globalPreload, - { - fn: globalPreload, - url, - }, - ); - } - if (resolve) { - ArrayPrototypePush( - this.#hooks.resolve, - { - fn: resolve, - url, - }, - ); - } - if (load) { - ArrayPrototypePush( - this.#hooks.load, - { - fn: load, - url, - }, - ); - } + setCustomizations(customizations) { + this.#customizations = customizations; + if (customizations) { + this.allowImportMetaResolve = customizations.allowImportMetaResolve; + } else { + this.allowImportMetaResolve = true; } - - this.preload(); } async eval( @@ -374,19 +209,22 @@ class ESMLoader { url = pathToFileURL(`${process.cwd()}/[eval${++this.evalIndex}]`).href, ) { const evalInstance = (url) => { - const { ModuleWrap, callbackMap } = internalBinding('module_wrap'); + const { ModuleWrap } = internalBinding('module_wrap'); + const { setCallbackForWrap } = require('internal/modules/esm/utils'); const module = new ModuleWrap(url, undefined, source, 0, 0); - callbackMap.set(module, { - importModuleDynamically: (specifier, { url }, importAssertions) => { - return this.import(specifier, url, importAssertions); + setCallbackForWrap(module, { + initializeImportMeta: (meta, wrap) => this.importMetaInitialize(meta, { url }), + importModuleDynamically: (specifier, { url }, importAttributes) => { + return this.import(specifier, url, importAttributes); }, }); return module; }; + const ModuleJob = require('internal/modules/esm/module_job'); const job = new ModuleJob( this, url, undefined, evalInstance, false, false); - this.moduleMap.set(url, undefined, job); + this.loadCache.set(url, undefined, job); const { module } = await job.run(); return { @@ -403,35 +241,27 @@ class ESMLoader { * @param {string | undefined} parentURL The URL of the module importing this * one, unless this is the Node.js entry * point. - * @param {Record} importAssertions Validations for the + * @param {Record} importAttributes Validations for the * module import. * @returns {Promise} The (possibly pending) module job */ - async getModuleJob(specifier, parentURL, importAssertions) { - let importAssertionsForResolve; - - // By default, `this.#hooks.load` contains just the Node default load hook - if (this.#hooks.load.length !== 1) { - // We can skip cloning if there are no user-provided loaders because - // the Node.js default resolve hook does not use import assertions. - importAssertionsForResolve = { - __proto__: null, - ...importAssertions, - }; - } - - const { format, url } = - await this.resolve(specifier, parentURL, importAssertionsForResolve); + async getModuleJob(specifier, parentURL, importAttributes) { + const resolveResult = await this.resolve(specifier, parentURL, importAttributes); + return this.getJobFromResolveResult(resolveResult, parentURL, importAttributes); + } - let job = this.moduleMap.get(url, importAssertions.type); + getJobFromResolveResult(resolveResult, parentURL, importAttributes) { + const { url, format } = resolveResult; + const resolvedImportAttributes = resolveResult.importAttributes ?? importAttributes; + let job = this.loadCache.get(url, resolvedImportAttributes.type); // CommonJS will set functions for lazy job evaluation. if (typeof job === 'function') { - this.moduleMap.set(url, undefined, job = job()); + this.loadCache.set(url, undefined, job = job()); } if (job === undefined) { - job = this.#createModuleJob(url, importAssertions, parentURL, format); + job = this.#createModuleJob(url, resolvedImportAttributes, parentURL, format); } return job; @@ -440,7 +270,7 @@ class ESMLoader { /** * Create and cache an object representing a loaded module. * @param {string} url The absolute URL that was resolved for this module - * @param {Record} importAssertions Validations for the + * @param {Record} importAttributes Validations for the * module import. * @param {string} [parentURL] The absolute URL of the module importing this * one, unless this is the Node.js entry point @@ -448,7 +278,7 @@ class ESMLoader { * `resolve` hook * @returns {Promise} The (possibly pending) module job */ - #createModuleJob(url, importAssertions, parentURL, format) { + #createModuleJob(url, importAttributes, parentURL, format) { const moduleProvider = async (url, isMain) => { const { format: finalFormat, @@ -456,10 +286,10 @@ class ESMLoader { source, } = await this.load(url, { format, - importAssertions, + importAttributes, }); - const translator = translators.get(finalFormat); + const translator = getTranslators().get(finalFormat); if (!translator) { throw new ERR_UNKNOWN_MODULE_FORMAT(finalFormat, responseURL); @@ -477,422 +307,305 @@ class ESMLoader { process.send({ 'watch:import': [url] }); } + const ModuleJob = require('internal/modules/esm/module_job'); const job = new ModuleJob( this, url, - importAssertions, + importAttributes, moduleProvider, parentURL === undefined, inspectBrk, ); - this.moduleMap.set(url, importAssertions.type, job); + this.loadCache.set(url, importAttributes.type, job); return job; } /** * This method is usually called indirectly as part of the loading processes. - * Internally, it is used directly to add loaders. Use directly with caution. - * - * This method must NOT be renamed: it functions as a dynamic import on a - * loader module. - * @param {string | string[]} specifiers Path(s) to the module. + * Use directly with caution. + * @param {string} specifier The first parameter of an `import()` expression. * @param {string} parentURL Path of the parent importing the module. - * @param {Record} importAssertions Validations for the + * @param {Record} importAttributes Validations for the * module import. - * @returns {Promise} - * A collection of module export(s) or a list of collections of module - * export(s). + * @returns {Promise} */ - async import(specifiers, parentURL, importAssertions) { - // For loaders, `import` is passed multiple things to process, it returns a - // list pairing the url and exports collected. This is especially useful for - // error messaging, to identity from where an export came. But, in most - // cases, only a single url is being "imported" (ex `import()`), so there is - // only 1 possible url from which the exports were collected and it is - // already known to the caller. Nesting that in a list would only ever - // create redundant work for the caller, so it is later popped off the - // internal list. - const wasArr = ArrayIsArray(specifiers); - if (!wasArr) { specifiers = [specifiers]; } - - const count = specifiers.length; - const jobs = new Array(count); - - for (let i = 0; i < count; i++) { - jobs[i] = this.getModuleJob(specifiers[i], parentURL, importAssertions) - .then((job) => job.run()) - .then(({ module }) => module.getNamespace()); - } - - const namespaces = await SafePromiseAllReturnArrayLike(jobs); - - if (!wasArr) { return namespaces[0]; } // We can skip the pairing below - - for (let i = 0; i < count; i++) { - namespaces[i] = { - __proto__: null, - url: specifiers[i], - exports: namespaces[i], - }; - } - - return namespaces; + async import(specifier, parentURL, importAttributes) { + const moduleJob = await this.getModuleJob(specifier, parentURL, importAttributes); + const { module } = await moduleJob.run(); + return module.getNamespace(); } /** - * Provide source that is understood by one of Node's translators. - * - * Internally, this behaves like a backwards iterator, wherein the stack of - * hooks starts at the top and each call to `nextLoad()` moves down 1 step - * until it reaches the bottom or short-circuits. - * @param {URL['href']} url The URL/path of the module to be loaded - * @param {object} context Metadata about the module - * @returns {{ format: ModuleFormat, source: ModuleSource }} + * @see {@link CustomizedModuleLoader.register} */ - async load(url, context = {}) { - const chain = this.#hooks.load; - const meta = { - chainFinished: null, - context, - hookErrIdentifier: '', - hookIndex: chain.length - 1, - hookName: 'load', - shortCircuited: false, - }; - - const validateArgs = (hookErrIdentifier, nextUrl, ctx) => { - if (typeof nextUrl !== 'string') { - // non-strings can be coerced to a url string - // validateString() throws a less-specific error - throw new ERR_INVALID_ARG_TYPE( - `${hookErrIdentifier} url`, - 'a url string', - nextUrl, - ); - } - - // Try to avoid expensive URL instantiation for known-good urls - if (!this.moduleMap.has(nextUrl)) { - try { - new URL(nextUrl); - } catch { - throw new ERR_INVALID_ARG_VALUE( - `${hookErrIdentifier} url`, - nextUrl, - 'should be a url string', - ); - } - } - - if (ctx) validateObject(ctx, `${hookErrIdentifier} context`); - }; - const validateOutput = (hookErrIdentifier, output) => { - if (typeof output !== 'object' || output === null) { // [2] - throw new ERR_INVALID_RETURN_VALUE( - 'an object', - hookErrIdentifier, - output, - ); - } - }; - - const nextLoad = nextHookFactory(chain, meta, { validateArgs, validateOutput }); - - const loaded = await nextLoad(url, context); - const { hookErrIdentifier } = meta; // Retrieve the value after all settled - - validateOutput(hookErrIdentifier, loaded); - - if (loaded?.shortCircuit === true) { meta.shortCircuited = true; } - - if (!meta.chainFinished && !meta.shortCircuited) { - throw new ERR_LOADER_CHAIN_INCOMPLETE(hookErrIdentifier); - } - - const { - format, - source, - } = loaded; - let responseURL = loaded.responseURL; - - if (responseURL === undefined) { - responseURL = url; - } - - let responseURLObj; - if (typeof responseURL === 'string') { - try { - responseURLObj = new URL(responseURL); - } catch { - // responseURLObj not defined will throw in next branch. - } + register(specifier, parentURL, data, transferList) { + if (!this.#customizations) { + // `CustomizedModuleLoader` is defined at the bottom of this file and + // available well before this line is ever invoked. This is here in + // order to preserve the git diff instead of moving the class. + // eslint-disable-next-line no-use-before-define + this.setCustomizations(new CustomizedModuleLoader()); } + return this.#customizations.register(`${specifier}`, `${parentURL}`, data, transferList); + } - if (responseURLObj?.href !== responseURL) { - throw new ERR_INVALID_RETURN_PROPERTY_VALUE( - 'undefined or a fully resolved URL string', - hookErrIdentifier, - 'responseURL', - responseURL, - ); + /** + * Resolve the location of the module. + * @param {string} originalSpecifier The specified URL path of the module to + * be resolved. + * @param {string} [parentURL] The URL path of the module's parent. + * @param {ImportAttributes} importAttributes Attributes from the import + * statement or expression. + * @returns {{ format: string, url: URL['href'] }} + */ + resolve(originalSpecifier, parentURL, importAttributes) { + if (this.#customizations) { + return this.#customizations.resolve(originalSpecifier, parentURL, importAttributes); } - - if (format == null) { - const dataUrl = RegExpPrototypeExec( - /^data:([^/]+\/[^;,]+)(?:[^,]*?)(;base64)?,/, - url, - ); - - throw new ERR_UNKNOWN_MODULE_FORMAT( - dataUrl ? dataUrl[1] : format, - url); + const requestKey = this.#resolveCache.serializeKey(originalSpecifier, importAttributes); + const cachedResult = this.#resolveCache.get(requestKey, parentURL); + if (cachedResult != null) { + return cachedResult; } + const result = this.defaultResolve(originalSpecifier, parentURL, importAttributes); + this.#resolveCache.set(requestKey, parentURL, result); + return result; + } - if (typeof format !== 'string') { // [2] - throw new ERR_INVALID_RETURN_PROPERTY_VALUE( - 'a string', - hookErrIdentifier, - 'format', - format, - ); + /** + * Just like `resolve` except synchronous. This is here specifically to support + * `import.meta.resolve` which must happen synchronously. + */ + resolveSync(originalSpecifier, parentURL, importAttributes) { + if (this.#customizations) { + return this.#customizations.resolveSync(originalSpecifier, parentURL, importAttributes); } + return this.defaultResolve(originalSpecifier, parentURL, importAttributes); + } - if ( - source != null && - typeof source !== 'string' && - !isAnyArrayBuffer(source) && - !isArrayBufferView(source) - ) { - throw ERR_INVALID_RETURN_PROPERTY_VALUE( - 'a string, an ArrayBuffer, or a TypedArray', - hookErrIdentifier, - 'source', - source, - ); - } + /** + * Our `defaultResolve` is synchronous and can be used in both + * `resolve` and `resolveSync`. This function is here just to avoid + * repeating the same code block twice in those functions. + */ + defaultResolve(originalSpecifier, parentURL, importAttributes) { + defaultResolve ??= require('internal/modules/esm/resolve').defaultResolve; - return { + const context = { __proto__: null, - format, - responseURL, - source, + conditions: this.#defaultConditions, + importAttributes, + parentURL, }; + + return defaultResolve(originalSpecifier, context); } - preload() { - for (let i = this.#hooks.globalPreload.length - 1; i >= 0; i--) { - const channel = new MessageChannel(); - const { - port1: insidePreload, - port2: insideLoader, - } = channel; + /** + * Provide source that is understood by one of Node's translators. + * @param {URL['href']} url The URL/path of the module to be loaded + * @param {object} [context] Metadata about the module + * @returns {Promise<{ format: ModuleFormat, source: ModuleSource }>} + */ + async load(url, context) { + defaultLoad ??= require('internal/modules/esm/load').defaultLoad; + const result = this.#customizations ? + await this.#customizations.load(url, context) : + await defaultLoad(url, context); + this.validateLoadResult(url, result?.format); + return result; + } - insidePreload.unref(); - insideLoader.unref(); + validateLoadResult(url, format) { + if (format == null) { + require('internal/modules/esm/load').throwUnknownModuleFormat(url, format); + } + } - const { - fn: preload, - url: specifier, - } = this.#hooks.globalPreload[i]; + importMetaInitialize(meta, context) { + if (this.#customizations) { + return this.#customizations.importMetaInitialize(meta, context, this); + } + importMetaInitializer ??= require('internal/modules/esm/initialize_import_meta').initializeImportMeta; + meta = importMetaInitializer(meta, context, this); + return meta; + } - const preloaded = preload({ - port: insideLoader, - }); + /** + * No-op when no hooks have been supplied. + */ + forceLoadHooks() { + this.#customizations?.forceLoadHooks(); + } +} +ObjectSetPrototypeOf(ModuleLoader.prototype, null); - if (preloaded == null) { return; } +class CustomizedModuleLoader { - const hookErrIdentifier = `${specifier} globalPreload`; + allowImportMetaResolve = true; - if (typeof preloaded !== 'string') { // [2] - throw new ERR_INVALID_RETURN_VALUE( - 'a string', - hookErrIdentifier, - preload, - ); - } - const { compileFunction } = require('vm'); - const preloadInit = compileFunction( - preloaded, - ['getBuiltin', 'port', 'setImportMetaCallback'], - { - filename: '', - }, - ); - const { BuiltinModule } = require('internal/bootstrap/loaders'); - // We only allow replacing the importMetaInitializer during preload, - // after preload is finished, we disable the ability to replace it - // - // This exposes accidentally setting the initializer too late by - // throwing an error. - let finished = false; - let replacedImportMetaInitializer = false; - let next = this.#importMetaInitializer; - try { - // Calls the compiled preload source text gotten from the hook - // Since the parameters are named we use positional parameters - // see compileFunction above to cross reference the names - FunctionPrototypeCall( - preloadInit, - globalThis, - // Param getBuiltin - (builtinName) => { - if (BuiltinModule.canBeRequiredByUsers(builtinName) && - BuiltinModule.canBeRequiredWithoutScheme(builtinName)) { - return require(builtinName); - } - throw new ERR_INVALID_ARG_VALUE('builtinName', builtinName); - }, - // Param port - insidePreload, - // Param setImportMetaCallback - (fn) => { - if (finished || typeof fn !== 'function') { - throw new ERR_INVALID_ARG_TYPE('fn', fn); - } - replacedImportMetaInitializer = true; - const parent = next; - next = (meta, context) => { - return fn(meta, context, parent); - }; - }); - } finally { - finished = true; - if (replacedImportMetaInitializer) { - this.#importMetaInitializer = next; - } - } - } + /** + * Instantiate a module loader that uses user-provided custom loader hooks. + */ + constructor() { + getHooksProxy(); } - importMetaInitialize(meta, context) { - this.#importMetaInitializer(meta, context); + /** + * Register some loader specifier. + * @param {string} originalSpecifier The specified URL path of the loader to + * be registered. + * @param {string} parentURL The parent URL from where the loader will be + * registered if using it package name as specifier + * @param {any} [data] Arbitrary data to be passed from the custom loader + * (user-land) to the worker. + * @param {any[]} [transferList] Objects in `data` that are changing ownership + * @returns {{ format: string, url: URL['href'] }} + */ + register(originalSpecifier, parentURL, data, transferList) { + return hooksProxy.makeSyncRequest('register', transferList, originalSpecifier, parentURL, data); } /** * Resolve the location of the module. - * - * Internally, this behaves like a backwards iterator, wherein the stack of - * hooks starts at the top and each call to `nextResolve()` moves down 1 step - * until it reaches the bottom or short-circuits. * @param {string} originalSpecifier The specified URL path of the module to * be resolved. * @param {string} [parentURL] The URL path of the module's parent. - * @param {ImportAssertions} importAssertions Assertions from the import - * statement or expression. + * @param {ImportAttributes} importAttributes Attributes from the import + * statement or expression. * @returns {{ format: string, url: URL['href'] }} */ - async resolve(originalSpecifier, parentURL, importAssertions) { - const isMain = parentURL === undefined; - - if ( - !isMain && - typeof parentURL !== 'string' && - !isURL(parentURL) - ) { - throw new ERR_INVALID_ARG_TYPE( - 'parentURL', - ['string', 'URL'], - parentURL, - ); - } - const chain = this.#hooks.resolve; - const context = { - conditions: DEFAULT_CONDITIONS, - importAssertions, - parentURL, - }; - const meta = { - chainFinished: null, - context, - hookErrIdentifier: '', - hookIndex: chain.length - 1, - hookName: 'resolve', - shortCircuited: false, - }; - - const validateArgs = (hookErrIdentifier, suppliedSpecifier, ctx) => { - validateString( - suppliedSpecifier, - `${hookErrIdentifier} specifier`, - ); // non-strings can be coerced to a url string - - if (ctx) validateObject(ctx, `${hookErrIdentifier} context`); - }; - const validateOutput = (hookErrIdentifier, output) => { - if (typeof output !== 'object' || output === null) { // [2] - throw new ERR_INVALID_RETURN_VALUE( - 'an object', - hookErrIdentifier, - output, - ); - } - }; + resolve(originalSpecifier, parentURL, importAttributes) { + return hooksProxy.makeAsyncRequest('resolve', undefined, originalSpecifier, parentURL, importAttributes); + } - const nextResolve = nextHookFactory(chain, meta, { validateArgs, validateOutput }); + resolveSync(originalSpecifier, parentURL, importAttributes) { + // This happens only as a result of `import.meta.resolve` calls, which must be sync per spec. + return hooksProxy.makeSyncRequest('resolve', undefined, originalSpecifier, parentURL, importAttributes); + } - const resolution = await nextResolve(originalSpecifier, context); - const { hookErrIdentifier } = meta; // Retrieve the value after all settled + /** + * Provide source that is understood by one of Node's translators. + * @param {URL['href']} url The URL/path of the module to be loaded + * @param {object} [context] Metadata about the module + * @returns {Promise<{ format: ModuleFormat, source: ModuleSource }>} + */ + load(url, context) { + return hooksProxy.makeAsyncRequest('load', undefined, url, context); + } - validateOutput(hookErrIdentifier, resolution); + importMetaInitialize(meta, context, loader) { + hooksProxy.importMetaInitialize(meta, context, loader); + } - if (resolution?.shortCircuit === true) { meta.shortCircuited = true; } + forceLoadHooks() { + hooksProxy.waitForWorker(); + } +} - if (!meta.chainFinished && !meta.shortCircuited) { - throw new ERR_LOADER_CHAIN_INCOMPLETE(hookErrIdentifier); +let emittedLoaderFlagWarning = false; +/** + * A loader instance is used as the main entry point for loading ES modules. Currently, this is a singleton; there is + * only one used for loading the main module and everything in its dependency graph, though separate instances of this + * class might be instantiated as part of bootstrap for other purposes. + * @param {boolean} useCustomLoadersIfPresent If the user has provided loaders via the --loader flag, use them. + * @returns {ModuleLoader} + */ +function createModuleLoader(useCustomLoadersIfPresent = true) { + let customizations = null; + if (useCustomLoadersIfPresent && + // Don't spawn a new worker if we're already in a worker thread created by instantiating CustomizedModuleLoader; + // doing so would cause an infinite loop. + !require('internal/modules/esm/utils').isLoaderWorker()) { + const userLoaderPaths = getOptionValue('--experimental-loader'); + if (userLoaderPaths.length > 0) { + if (!emittedLoaderFlagWarning) { + const readableURIEncode = (string) => ArrayPrototypeReduce( + [ + [/'/g, '%27'], // We need to URL-encode the single quote as it's the delimiter for the --import flag. + [/%22/g, '"'], // We can decode the double quotes to improve readability. + [/%2F/ig, '/'], // We can decode the slashes to improve readability. + ], + (str, { 0: regex, 1: replacement }) => RegExpPrototypeSymbolReplace(hardenRegExp(regex), str, replacement), + encodeURIComponent(string)); + process.emitWarning( + '`--experimental-loader` may be removed in the future; instead use `register()`:\n' + + `--import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; ${ArrayPrototypeJoin( + ArrayPrototypeMap(userLoaderPaths, (loader) => `register(${readableURIEncode(JSONStringify(loader))}, pathToFileURL("./"))`), + '; ', + )};'`, + 'ExperimentalWarning', + ); + emittedLoaderFlagWarning = true; + } + customizations = new CustomizedModuleLoader(); } + } - const { - format, - url, - } = resolution; + return new ModuleLoader(customizations); +} - if ( - format != null && - typeof format !== 'string' // [2] - ) { - throw new ERR_INVALID_RETURN_PROPERTY_VALUE( - 'a string', - hookErrIdentifier, - 'format', - format, - ); - } - if (typeof url !== 'string') { - // non-strings can be coerced to a url string - // validateString() throws a less-specific error - throw new ERR_INVALID_RETURN_PROPERTY_VALUE( - 'a url string', - hookErrIdentifier, - 'url', - url, - ); - } +/** + * Get the HooksProxy instance. If it is not defined, then create a new one. + * @returns {HooksProxy} + */ +function getHooksProxy() { + if (!hooksProxy) { + const { HooksProxy } = require('internal/modules/esm/hooks'); + hooksProxy = new HooksProxy(); + } - // Try to avoid expensive URL instantiation for known-good urls - if (!this.moduleMap.has(url)) { - try { - new URL(url); - } catch { - throw new ERR_INVALID_RETURN_PROPERTY_VALUE( - 'a url string', - hookErrIdentifier, - 'url', - url, - ); - } - } + return hooksProxy; +} - return { - __proto__: null, - format, - url, - }; +/** + * Register a single loader programmatically. + * @param {string|import('url').URL} specifier + * @param {string|import('url').URL} [parentURL] Base to use when resolving `specifier`; optional if + * `specifier` is absolute. Same as `options.parentUrl`, just inline + * @param {object} [options] Additional options to apply, described below. + * @param {string|import('url').URL} [options.parentURL] Base to use when resolving `specifier` + * @param {any} [options.data] Arbitrary data passed to the loader's `initialize` hook + * @param {any[]} [options.transferList] Objects in `data` that are changing ownership + * @returns {void} We want to reserve the return value for potential future extension of the API. + * @example + * ```js + * register('./myLoader.js'); + * register('ts-node/esm', { parentURL: import.meta.url }); + * register('./myLoader.js', { parentURL: import.meta.url }); + * register('ts-node/esm', import.meta.url); + * register('./myLoader.js', import.meta.url); + * register(new URL('./myLoader.js', import.meta.url)); + * register('./myLoader.js', { + * parentURL: import.meta.url, + * data: { banana: 'tasty' }, + * }); + * register('./myLoader.js', { + * parentURL: import.meta.url, + * data: someArrayBuffer, + * transferList: [someArrayBuffer], + * }); + * ``` + */ +function register(specifier, parentURL = undefined, options) { + const moduleLoader = require('internal/process/esm_loader').esmLoader; + if (parentURL != null && typeof parentURL === 'object' && !isURL(parentURL)) { + options = parentURL; + parentURL = options.parentURL; } + moduleLoader.register( + specifier, + parentURL ?? 'data:', + options?.data, + options?.transferList, + ); } -ObjectSetPrototypeOf(ESMLoader.prototype, null); - -exports.ESMLoader = ESMLoader; +module.exports = { + createModuleLoader, + getHooksProxy, + register, +}; diff --git a/lib/internal/modules/esm/module_job.js b/lib/internal/modules/esm/module_job.js index f1fe73eec6edb6..3bc327a39c7e67 100644 --- a/lib/internal/modules/esm/module_job.js +++ b/lib/internal/modules/esm/module_job.js @@ -5,7 +5,6 @@ const { ArrayPrototypePush, ArrayPrototypeSome, FunctionPrototype, - ObjectCreate, ObjectSetPrototypeOf, PromiseResolve, PromisePrototypeThen, @@ -22,7 +21,7 @@ const { const { ModuleWrap } = internalBinding('module_wrap'); -const { decorateErrorStack } = require('internal/util'); +const { decorateErrorStack, kEmptyObject } = require('internal/util'); const { getSourceMapsEnabled, } = require('internal/source_map/source_map_cache'); @@ -51,10 +50,10 @@ const isCommonJSGlobalLikeNotDefinedError = (errorMessage) => class ModuleJob { // `loader` is the Loader instance used for loading dependencies. // `moduleProvider` is a function - constructor(loader, url, importAssertions = ObjectCreate(null), + constructor(loader, url, importAttributes = { __proto__: null }, moduleProvider, isMain, inspectBrk) { this.loader = loader; - this.importAssertions = importAssertions; + this.importAttributes = importAttributes; this.isMain = isMain; this.inspectBrk = inspectBrk; @@ -73,15 +72,15 @@ class ModuleJob { // so that circular dependencies can't cause a deadlock by two of // these `link` callbacks depending on each other. const dependencyJobs = []; - const promises = this.module.link(async (specifier, assertions) => { - const jobPromise = this.loader.getModuleJob(specifier, url, assertions); - ArrayPrototypePush(dependencyJobs, jobPromise); - const job = await jobPromise; + const promises = this.module.link(async (specifier, attributes) => { + const job = await this.loader.getModuleJob(specifier, url, attributes); + ArrayPrototypePush(dependencyJobs, job); return job.modulePromise; }); - if (promises !== undefined) + if (promises !== undefined) { await SafePromiseAllReturnVoid(promises); + } return SafePromiseAllReturnArrayLike(dependencyJobs); }; @@ -142,12 +141,14 @@ class ModuleJob { /module '(.*)' does not provide an export named '(.+)'/, e.message); const { url: childFileURL } = await this.loader.resolve( - childSpecifier, parentFileUrl, + childSpecifier, + parentFileUrl, + kEmptyObject, ); let format; try { // This might throw for non-CommonJS modules because we aren't passing - // in the import assertions and some formats require them; but we only + // in the import attributes and some formats require them; but we only // care about CommonJS for the purposes of this error message. ({ format } = await this.loader.load(childFileURL)); diff --git a/lib/internal/modules/esm/module_map.js b/lib/internal/modules/esm/module_map.js index df02ebd708517f..595e251048b900 100644 --- a/lib/internal/modules/esm/module_map.js +++ b/lib/internal/modules/esm/module_map.js @@ -1,19 +1,93 @@ 'use strict'; -const ModuleJob = require('internal/modules/esm/module_job'); -const { kImplicitAssertType } = require('internal/modules/esm/assert'); const { + ArrayPrototypeJoin, + ArrayPrototypeMap, + ArrayPrototypeSort, + JSONStringify, ObjectCreate, + ObjectKeys, SafeMap, } = primordials; +const { kImplicitAssertType } = require('internal/modules/esm/assert'); let debug = require('internal/util/debuglog').debuglog('esm', (fn) => { debug = fn; }); const { ERR_INVALID_ARG_TYPE } = require('internal/errors').codes; const { validateString } = require('internal/validators'); -// Tracks the state of the loader-level module cache -class ModuleMap extends SafeMap { +/** + * Cache the results of the `resolve` step of the module resolution and loading process. + * Future resolutions of the same input (specifier, parent URL and import attributes) + * must return the same result if the first attempt was successful, per + * https://tc39.es/ecma262/#sec-HostLoadImportedModule. + * This cache is *not* used when custom loaders are registered. + */ +class ResolveCache extends SafeMap { + constructor(i) { super(i); } // eslint-disable-line no-useless-constructor + + /** + * Generates the internal serialized cache key and returns it along the actual cache object. + * + * It is exposed to allow more efficient read and overwrite a cache entry. + * @param {string} specifier + * @param {Record} importAttributes + * @returns {string} + */ + serializeKey(specifier, importAttributes) { + // To serialize the ModuleRequest (specifier + list of import attributes), + // we need to sort the attributes by key, then stringifying, + // so that different import statements with the same attributes are always treated + // as identical. + const keys = ObjectKeys(importAttributes); + + if (keys.length === 0) { + return specifier + '::'; + } + + return specifier + '::' + ArrayPrototypeJoin( + ArrayPrototypeMap( + ArrayPrototypeSort(keys), + (key) => JSONStringify(key) + JSONStringify(importAttributes[key])), + ','); + } + + #getModuleCachedImports(parentURL) { + let internalCache = super.get(parentURL); + if (internalCache == null) { + super.set(parentURL, internalCache = { __proto__: null }); + } + return internalCache; + } + + /** + * @param {string} serializedKey + * @param {string} parentURL + * @returns {import('./loader').ModuleExports | Promise} + */ + get(serializedKey, parentURL) { + return this.#getModuleCachedImports(parentURL)[serializedKey]; + } + + /** + * @param {string} serializedKey + * @param {string} parentURL + * @param {{ format: string, url: URL['href'] }} result + */ + set(serializedKey, parentURL, result) { + this.#getModuleCachedImports(parentURL)[serializedKey] = result; + return this; + } + + has(serializedKey, parentURL) { + return serializedKey in this.#getModuleCachedImports(parentURL); + } +} + +/** + * Cache the results of the `load` step of the module resolution and loading process. + */ +class LoadCache extends SafeMap { constructor(i) { super(i); } // eslint-disable-line no-useless-constructor get(url, type = kImplicitAssertType) { validateString(url, 'url'); @@ -23,13 +97,15 @@ class ModuleMap extends SafeMap { set(url, type = kImplicitAssertType, job) { validateString(url, 'url'); validateString(type, 'type'); + + const ModuleJob = require('internal/modules/esm/module_job'); if (job instanceof ModuleJob !== true && typeof job !== 'function') { throw new ERR_INVALID_ARG_TYPE('job', 'ModuleJob', job); } debug(`Storing ${url} (${ type === kImplicitAssertType ? 'implicit type' : type - }) in ModuleMap`); + }) in ModuleLoadMap`); const cachedJobsForUrl = super.get(url) ?? ObjectCreate(null); cachedJobsForUrl[type] = job; return super.set(url, cachedJobsForUrl); @@ -40,4 +116,8 @@ class ModuleMap extends SafeMap { return super.get(url)?.[type] !== undefined; } } -module.exports = ModuleMap; + +module.exports = { + LoadCache, + ResolveCache, +}; diff --git a/lib/internal/modules/esm/package_config.js b/lib/internal/modules/esm/package_config.js index 1327bf1470d0eb..5da47764c9de2c 100644 --- a/lib/internal/modules/esm/package_config.js +++ b/lib/internal/modules/esm/package_config.js @@ -1,106 +1,29 @@ 'use strict'; const { - JSONParse, - ObjectPrototypeHasOwnProperty, - SafeMap, StringPrototypeEndsWith, } = primordials; const { URL, fileURLToPath } = require('internal/url'); -const { - ERR_INVALID_PACKAGE_CONFIG, -} = require('internal/errors').codes; - const packageJsonReader = require('internal/modules/package_json_reader'); -const { filterOwnProperties } = require('internal/util'); - /** - * @typedef {string | string[] | Record} Exports - * @typedef {'module' | 'commonjs'} PackageType - * @typedef {{ - * pjsonPath: string, - * exports?: ExportConfig, - * name?: string, - * main?: string, - * type?: PackageType, - * }} PackageConfig + * @typedef {object} PackageConfig + * @property {string} pjsonPath - The path to the package.json file. + * @property {boolean} exists - Whether the package.json file exists. + * @property {'none' | 'commonjs' | 'module'} type - The type of the package. + * @property {string} [name] - The name of the package. + * @property {string} [main] - The main entry point of the package. + * @property {PackageTarget} [exports] - The exports configuration of the package. + * @property {Record>} [imports] - The imports configuration of the package. */ - -/** @type {Map} */ -const packageJSONCache = new SafeMap(); - - /** - * @param {string} path - * @param {string} specifier - * @param {string | URL | undefined} base - * @returns {PackageConfig} + * @typedef {string | string[] | Record>} PackageTarget */ -function getPackageConfig(path, specifier, base) { - const existing = packageJSONCache.get(path); - if (existing !== undefined) { - return existing; - } - const source = packageJsonReader.read(path).string; - if (source === undefined) { - const packageConfig = { - pjsonPath: path, - exists: false, - main: undefined, - name: undefined, - type: 'none', - exports: undefined, - imports: undefined, - }; - packageJSONCache.set(path, packageConfig); - return packageConfig; - } - - let packageJSON; - try { - packageJSON = JSONParse(source); - } catch (error) { - throw new ERR_INVALID_PACKAGE_CONFIG( - path, - (base ? `"${specifier}" from ` : '') + fileURLToPath(base || specifier), - error.message, - ); - } - - let { imports, main, name, type } = filterOwnProperties(packageJSON, ['imports', 'main', 'name', 'type']); - const exports = ObjectPrototypeHasOwnProperty(packageJSON, 'exports') ? packageJSON.exports : undefined; - if (typeof imports !== 'object' || imports === null) { - imports = undefined; - } - if (typeof main !== 'string') { - main = undefined; - } - if (typeof name !== 'string') { - name = undefined; - } - // Ignore unknown types for forwards compatibility - if (type !== 'module' && type !== 'commonjs') { - type = 'none'; - } - - const packageConfig = { - pjsonPath: path, - exists: true, - main, - name, - type, - exports, - imports, - }; - packageJSONCache.set(path, packageConfig); - return packageConfig; -} - /** - * @param {URL | string} resolved - * @returns {PackageConfig} + * Returns the package configuration for the given resolved URL. + * @param {URL | string} resolved - The resolved URL. + * @returns {PackageConfig} - The package configuration. */ function getPackageScopeConfig(resolved) { let packageJSONUrl = new URL('./package.json', resolved); @@ -109,7 +32,11 @@ function getPackageScopeConfig(resolved) { if (StringPrototypeEndsWith(packageJSONPath, 'node_modules/package.json')) { break; } - const packageConfig = getPackageConfig(fileURLToPath(packageJSONUrl), resolved); + const packageConfig = packageJsonReader.read(fileURLToPath(packageJSONUrl), { + __proto__: null, + specifier: resolved, + isESM: true, + }); if (packageConfig.exists) { return packageConfig; } @@ -124,7 +51,8 @@ function getPackageScopeConfig(resolved) { } } const packageJSONPath = fileURLToPath(packageJSONUrl); - const packageConfig = { + return { + __proto__: null, pjsonPath: packageJSONPath, exists: false, main: undefined, @@ -133,12 +61,9 @@ function getPackageScopeConfig(resolved) { exports: undefined, imports: undefined, }; - packageJSONCache.set(packageJSONPath, packageConfig); - return packageConfig; } module.exports = { - getPackageConfig, getPackageScopeConfig, }; diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js index 7006887a6fe2ba..96dd20a86b076e 100644 --- a/lib/internal/modules/esm/resolve.js +++ b/lib/internal/modules/esm/resolve.js @@ -4,9 +4,7 @@ const { ArrayIsArray, ArrayPrototypeJoin, ArrayPrototypeShift, - JSONParse, JSONStringify, - ObjectFreeze, ObjectGetOwnPropertyNames, ObjectPrototypeHasOwnProperty, RegExp, @@ -25,28 +23,26 @@ const { StringPrototypeStartsWith, } = primordials; const internalFS = require('internal/fs/utils'); -const { BuiltinModule } = require('internal/bootstrap/loaders'); -const { - realpathSync, - statSync, - Stats, -} = require('fs'); +const { BuiltinModule } = require('internal/bootstrap/realm'); +const { realpathSync } = require('fs'); const { getOptionValue } = require('internal/options'); const pendingDeprecation = getOptionValue('--pending-deprecation'); // Do not eagerly grab .manifest, it may be in TDZ const policy = getOptionValue('--experimental-policy') ? require('internal/process/policy') : null; -const { sep, relative, resolve } = require('path'); +const { sep, relative, resolve, toNamespacedPath } = require('path'); const preserveSymlinks = getOptionValue('--preserve-symlinks'); const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main'); const experimentalNetworkImports = getOptionValue('--experimental-network-imports'); -const typeFlag = getOptionValue('--input-type'); -const { URL, pathToFileURL, fileURLToPath } = require('internal/url'); +const inputTypeFlag = getOptionValue('--input-type'); +const { URL, pathToFileURL, fileURLToPath, isURL, toPathIfFileURL } = require('internal/url'); +const { getCWDURL } = require('internal/util'); +const { canParse: URLCanParse } = internalBinding('url'); const { ERR_INPUT_TYPE_NOT_ALLOWED, - ERR_INVALID_ARG_VALUE, + ERR_INVALID_ARG_TYPE, ERR_INVALID_MODULE_SPECIFIER, ERR_INVALID_PACKAGE_CONFIG, ERR_INVALID_PACKAGE_TARGET, @@ -59,33 +55,28 @@ const { } = require('internal/errors').codes; const { Module: CJSModule } = require('internal/modules/cjs/loader'); +const { getPackageScopeConfig } = require('internal/modules/esm/package_config'); +const { getConditionsSet } = require('internal/modules/esm/utils'); const packageJsonReader = require('internal/modules/package_json_reader'); -const { getPackageConfig, getPackageScopeConfig } = require('internal/modules/esm/package_config'); +const { internalModuleStat } = internalBinding('fs'); /** * @typedef {import('internal/modules/esm/package_config.js').PackageConfig} PackageConfig */ -const userConditions = getOptionValue('--conditions'); -const noAddons = getOptionValue('--no-addons'); -const addonConditions = noAddons ? [] : ['node-addons']; - -const DEFAULT_CONDITIONS = ObjectFreeze([ - 'node', - 'import', - ...addonConditions, - ...userConditions, -]); - -const DEFAULT_CONDITIONS_SET = new SafeSet(DEFAULT_CONDITIONS); - const emittedPackageWarnings = new SafeSet(); +/** + * Emits a deprecation warning for the use of a deprecated trailing slash pattern mapping in the "exports" field + * module resolution of a package. + * @param {string} match - The deprecated trailing slash pattern mapping. + * @param {string} pjsonUrl - The URL of the package.json file. + * @param {string} base - The URL of the module that imported the package. + */ function emitTrailingSlashPatternDeprecation(match, pjsonUrl, base) { const pjsonPath = fileURLToPath(pjsonUrl); - if (emittedPackageWarnings.has(pjsonPath + '|' + match)) - return; + if (emittedPackageWarnings.has(pjsonPath + '|' + match)) { return; } emittedPackageWarnings.add(pjsonPath + '|' + match); process.emitWarning( `Use of deprecated trailing slash pattern mapping "${match}" in the ` + @@ -99,6 +90,16 @@ function emitTrailingSlashPatternDeprecation(match, pjsonUrl, base) { const doubleSlashRegEx = /[/\\][/\\]/; +/** + * Emits a deprecation warning for invalid segment in module resolution. + * @param {string} target - The target module. + * @param {string} request - The requested module. + * @param {string} match - The matched module. + * @param {string} pjsonUrl - The package.json URL. + * @param {boolean} internal - Whether the module is in the "imports" or "exports" field. + * @param {string} base - The base URL. + * @param {boolean} isTarget - Whether the target is a module. + */ function emitInvalidSegmentDeprecation(target, request, match, pjsonUrl, internal, base, isTarget) { if (!pendingDeprecation) { return; } const pjsonPath = fileURLToPath(pjsonUrl); @@ -115,16 +116,16 @@ function emitInvalidSegmentDeprecation(target, request, match, pjsonUrl, interna } /** - * @param {URL} url - * @param {URL} packageJSONUrl - * @param {string | URL | undefined} base - * @param {string} [main] - * @returns {void} + * Emits a deprecation warning if the given URL is a module and + * the package.json file does not define a "main" or "exports" field. + * @param {URL} url - The URL of the module being resolved. + * @param {URL} packageJSONUrl - The URL of the package.json file for the module. + * @param {string | URL} [base] - The base URL for the module being resolved. + * @param {string} [main] - The "main" field from the package.json file. */ function emitLegacyIndexDeprecation(url, packageJSONUrl, base, main) { const format = defaultGetFormatWithoutErrors(url); - if (format !== 'module') - return; + if (format !== 'module') { return; } const path = fileURLToPath(url); const pkgPath = fileURLToPath(new URL('.', packageJSONUrl)); const basePath = fileURLToPath(base); @@ -150,36 +151,14 @@ function emitLegacyIndexDeprecation(url, packageJSONUrl, base, main) { } } -/** - * @param {string[]} [conditions] - * @returns {Set} - */ -function getConditionsSet(conditions) { - if (conditions !== undefined && conditions !== DEFAULT_CONDITIONS) { - if (!ArrayIsArray(conditions)) { - throw new ERR_INVALID_ARG_VALUE('conditions', conditions, - 'expected an array'); - } - return new SafeSet(conditions); - } - return DEFAULT_CONDITIONS_SET; -} - const realpathCache = new SafeMap(); -/** - * @param {string | URL} path - * @returns {import('fs').Stats} - */ -const tryStatSync = - (path) => statSync(path, { throwIfNoEntry: false }) ?? new Stats(); - /** * @param {string | URL} url * @returns {boolean} */ function fileExists(url) { - return statSync(url, { throwIfNoEntry: false })?.isFile() ?? false; + return internalModuleStat(toNamespacedPath(toPathIfFileURL(url))) === 0; } /** @@ -198,22 +177,23 @@ function legacyMainResolve(packageJSONUrl, packageConfig, base) { let guess; if (packageConfig.main !== undefined) { // Note: fs check redundances will be handled by Descriptor cache here. - if (fileExists(guess = new URL(`./${packageConfig.main}`, - packageJSONUrl))) { + if (fileExists(guess = new URL(`./${packageConfig.main}`, packageJSONUrl))) { return guess; - } else if (fileExists(guess = new URL(`./${packageConfig.main}.js`, - packageJSONUrl))); - else if (fileExists(guess = new URL(`./${packageConfig.main}.json`, - packageJSONUrl))); - else if (fileExists(guess = new URL(`./${packageConfig.main}.node`, - packageJSONUrl))); - else if (fileExists(guess = new URL(`./${packageConfig.main}/index.js`, - packageJSONUrl))); - else if (fileExists(guess = new URL(`./${packageConfig.main}/index.json`, - packageJSONUrl))); - else if (fileExists(guess = new URL(`./${packageConfig.main}/index.node`, - packageJSONUrl))); - else guess = undefined; + } else if (fileExists(guess = new URL(`./${packageConfig.main}.js`, packageJSONUrl))) { + // Handled below. + } else if (fileExists(guess = new URL(`./${packageConfig.main}.json`, packageJSONUrl))) { + // Handled below. + } else if (fileExists(guess = new URL(`./${packageConfig.main}.node`, packageJSONUrl))) { + // Handled below. + } else if (fileExists(guess = new URL(`./${packageConfig.main}/index.js`, packageJSONUrl))) { + // Handled below. + } else if (fileExists(guess = new URL(`./${packageConfig.main}/index.json`, packageJSONUrl))) { + // Handled below. + } else if (fileExists(guess = new URL(`./${packageConfig.main}/index.node`, packageJSONUrl))) { + // Handled below. + } else { + guess = undefined; + } if (guess) { emitLegacyIndexDeprecation(guess, packageJSONUrl, base, packageConfig.main); @@ -221,11 +201,15 @@ function legacyMainResolve(packageJSONUrl, packageConfig, base) { } // Fallthrough. } - if (fileExists(guess = new URL('./index.js', packageJSONUrl))); - // So fs. - else if (fileExists(guess = new URL('./index.json', packageJSONUrl))); - else if (fileExists(guess = new URL('./index.node', packageJSONUrl))); - else guess = undefined; + if (fileExists(guess = new URL('./index.js', packageJSONUrl))) { + // Handled below. + } else if (fileExists(guess = new URL('./index.json', packageJSONUrl))) { + // Handled below. + } else if (fileExists(guess = new URL('./index.node', packageJSONUrl))) { + // Handled below. + } else { + guess = undefined; + } if (guess) { emitLegacyIndexDeprecation(guess, packageJSONUrl, base, packageConfig.main); return guess; @@ -240,7 +224,7 @@ function legacyMainResolve(packageJSONUrl, packageConfig, base) { * @returns {URL | undefined} */ function resolveExtensionsWithTryExactName(search) { - if (fileExists(search)) return search; + if (fileExists(search)) { return search; } return resolveExtensions(search); } @@ -254,7 +238,7 @@ function resolveExtensions(search) { for (let i = 0; i < extensions.length; i++) { const extension = extensions[i]; const guess = new URL(`${search.pathname}${extension}`, search); - if (fileExists(guess)) return guess; + if (fileExists(guess)) { return guess; } } return undefined; } @@ -268,8 +252,8 @@ function resolveDirectoryEntry(search) { const pkgJsonPath = resolve(dirPath, 'package.json'); if (fileExists(pkgJsonPath)) { const pkgJson = packageJsonReader.read(pkgJsonPath); - if (pkgJson.containsKeys) { - const { main } = JSONParse(pkgJson.string); + if (pkgJson.exists) { + const { main } = pkgJson; if (main != null) { const mainUrl = pathToFileURL(resolve(dirPath, main)); return resolveExtensionsWithTryExactName(mainUrl); @@ -281,18 +265,33 @@ function resolveDirectoryEntry(search) { const encodedSepRegEx = /%2F|%5C/i; /** - * @param {URL} resolved - * @param {string | URL | undefined} base - * @param {boolean} preserveSymlinks - * @returns {URL | undefined} + * Finalizes the resolution of a module specifier by checking if the resolved pathname contains encoded "/" or "\\" + * characters, checking if the resolved pathname is a directory or file, and resolving any symlinks if necessary. + * @param {URL} resolved - The resolved URL object. + * @param {string | URL | undefined} base - The base URL object. + * @param {boolean} preserveSymlinks - Whether to preserve symlinks or not. + * @returns {URL} - The finalized URL object. + * @throws {ERR_INVALID_MODULE_SPECIFIER} - If the resolved pathname contains encoded "/" or "\\" characters. + * @throws {ERR_UNSUPPORTED_DIR_IMPORT} - If the resolved pathname is a directory. + * @throws {ERR_MODULE_NOT_FOUND} - If the resolved pathname is not a file. */ function finalizeResolution(resolved, base, preserveSymlinks) { - if (RegExpPrototypeExec(encodedSepRegEx, resolved.pathname) !== null) + if (RegExpPrototypeExec(encodedSepRegEx, resolved.pathname) !== null) { throw new ERR_INVALID_MODULE_SPECIFIER( resolved.pathname, 'must not include encoded "/" or "\\" characters', fileURLToPath(base)); + } + + let path; + try { + path = fileURLToPath(resolved); + } catch (err) { + const { setOwnProperty } = require('internal/util'); + setOwnProperty(err, 'input', `${resolved}`); + setOwnProperty(err, 'module', `${base}`); + throw err; + } - let path = fileURLToPath(resolved); if (getOptionValue('--experimental-specifier-resolution') === 'node') { let file = resolveExtensionsWithTryExactName(resolved); @@ -301,7 +300,7 @@ function finalizeResolution(resolved, base, preserveSymlinks) { file = StringPrototypeEndsWith(path, '/') ? (resolveDirectoryEntry(resolved) || resolved) : resolveDirectoryEntry(new URL(`${resolved}/`)); - if (file === resolved) return file; + if (file === resolved) { return file; } if (file === undefined) { throw new ERR_MODULE_NOT_FOUND( @@ -314,18 +313,19 @@ function finalizeResolution(resolved, base, preserveSymlinks) { path = fileURLToPath(resolved); } - const stats = tryStatSync(StringPrototypeEndsWith(path, '/') ? - StringPrototypeSlice(path, -1) : path); - if (stats.isDirectory()) { - const err = new ERR_UNSUPPORTED_DIR_IMPORT(path, fileURLToPath(base)); - err.url = String(resolved); - throw err; - } else if (!stats.isFile()) { + const stats = internalModuleStat(toNamespacedPath(StringPrototypeEndsWith(path, '/') ? + StringPrototypeSlice(path, -1) : path)); + + // Check for stats.isDirectory() + if (stats === 1) { + throw new ERR_UNSUPPORTED_DIR_IMPORT(path, fileURLToPath(base), String(resolved)); + } else if (stats !== 0) { + // Check for !stats.isFile() if (process.env.WATCH_REPORT_DEPENDENCIES && process.send) { process.send({ 'watch:require': [path || resolved.pathname] }); } throw new ERR_MODULE_NOT_FOUND( - path || resolved.pathname, base && fileURLToPath(base), 'module'); + path || resolved.pathname, base && fileURLToPath(base), resolved); } if (!preserveSymlinks) { @@ -343,9 +343,11 @@ function finalizeResolution(resolved, base, preserveSymlinks) { } /** - * @param {string} specifier - * @param {URL} packageJSONUrl - * @param {string | URL | undefined} base + * Returns an error object indicating that the specified import is not defined. + * @param {string} specifier - The import specifier that is not defined. + * @param {URL} packageJSONUrl - The URL of the package.json file, or null if not available. + * @param {string | URL | undefined} base - The base URL to use for resolving relative URLs. + * @returns {ERR_PACKAGE_IMPORT_NOT_DEFINED} - The error object. */ function importNotDefined(specifier, packageJSONUrl, base) { return new ERR_PACKAGE_IMPORT_NOT_DEFINED( @@ -354,9 +356,11 @@ function importNotDefined(specifier, packageJSONUrl, base) { } /** - * @param {string} subpath - * @param {URL} packageJSONUrl - * @param {string | URL | undefined} base + * Returns an error object indicating that the specified subpath was not exported by the package. + * @param {string} subpath - The subpath that was not exported. + * @param {URL} packageJSONUrl - The URL of the package.json file. + * @param {string | URL | undefined} [base] - The base URL to use for resolving the subpath. + * @returns {ERR_PACKAGE_PATH_NOT_EXPORTED} - The error object. */ function exportsNotFound(subpath, packageJSONUrl, base) { return new ERR_PACKAGE_PATH_NOT_EXPORTED( @@ -365,12 +369,13 @@ function exportsNotFound(subpath, packageJSONUrl, base) { } /** - * - * @param {string} request - * @param {string} match - * @param {URL} packageJSONUrl - * @param {boolean} internal - * @param {string | URL | undefined} base + * Throws an error indicating that the given request is not a valid subpath match for the specified pattern. + * @param {string} request - The request that failed to match the pattern. + * @param {string} match - The pattern that the request was compared against. + * @param {URL} packageJSONUrl - The URL of the package.json file being resolved. + * @param {boolean} internal - Whether the resolution is for an "imports" or "exports" field in package.json. + * @param {string | URL | undefined} base - The base URL for the resolution. + * @throws {ERR_INVALID_MODULE_SPECIFIER} When the request is not a valid match for the pattern. */ function throwInvalidSubpath(request, match, packageJSONUrl, internal, base) { const reason = `request is not a valid match in pattern "${match}" for the "${ @@ -380,6 +385,15 @@ function throwInvalidSubpath(request, match, packageJSONUrl, internal, base) { base && fileURLToPath(base)); } +/** + * Creates an error object for an invalid package target. + * @param {string} subpath - The subpath. + * @param {import('internal/modules/esm/package_config.js').PackageTarget} target - The target. + * @param {URL} packageJSONUrl - The URL of the package.json file. + * @param {boolean} internal - Whether the package is internal. + * @param {string | URL | undefined} base - The base URL. + * @returns {ERR_INVALID_PACKAGE_TARGET} - The error object. + */ function invalidPackageTarget( subpath, target, packageJSONUrl, internal, base) { if (typeof target === 'object' && target !== null) { @@ -398,17 +412,19 @@ const invalidPackageNameRegEx = /^\.|%|\\/; const patternRegEx = /\*/g; /** - * - * @param {string} target - * @param {*} subpath - * @param {*} match - * @param {*} packageJSONUrl - * @param {*} base - * @param {*} pattern - * @param {*} internal - * @param {*} isPathMap - * @param {*} conditions - * @returns {URL} + * Resolves the package target string to a URL object. + * @param {string} target - The target string to resolve. + * @param {string} subpath - The subpath to append to the resolved URL. + * @param {RegExpMatchArray} match - The matched string array from the import statement. + * @param {string} packageJSONUrl - The URL of the package.json file. + * @param {string} base - The base URL to resolve the target against. + * @param {RegExp} pattern - The pattern to replace in the target string. + * @param {boolean} internal - Whether the target is internal to the package. + * @param {boolean} isPathMap - Whether the target is a path map. + * @param {string[]} conditions - The import conditions. + * @returns {URL} - The resolved URL object. + * @throws {ERR_INVALID_PACKAGE_TARGET} - If the target is invalid. + * @throws {ERR_INVALID_SUBPATH} - If the subpath is invalid. */ function resolvePackageTargetString( target, @@ -422,20 +438,15 @@ function resolvePackageTargetString( conditions, ) { - if (subpath !== '' && !pattern && target[target.length - 1] !== '/') + if (subpath !== '' && !pattern && target[target.length - 1] !== '/') { throw invalidPackageTarget(match, target, packageJSONUrl, internal, base); + } if (!StringPrototypeStartsWith(target, './')) { if (internal && !StringPrototypeStartsWith(target, '../') && !StringPrototypeStartsWith(target, '/')) { - let isURL = false; - try { - new URL(target); - isURL = true; - } catch { - // Continue regardless of error. - } - if (!isURL) { + // No need to convert target to string, since it's already presumed to be + if (!URLCanParse(target)) { const exportTarget = pattern ? RegExpPrototypeSymbolReplace(patternRegEx, target, () => subpath) : target + subpath; @@ -466,10 +477,11 @@ function resolvePackageTargetString( const resolvedPath = resolved.pathname; const packagePath = new URL('.', packageJSONUrl).pathname; - if (!StringPrototypeStartsWith(resolvedPath, packagePath)) + if (!StringPrototypeStartsWith(resolvedPath, packagePath)) { throw invalidPackageTarget(match, target, packageJSONUrl, internal, base); + } - if (subpath === '') return resolved; + if (subpath === '') { return resolved; } if (RegExpPrototypeExec(invalidSegmentRegEx, subpath) !== null) { const request = pattern ? StringPrototypeReplace(match, '*', () => subpath) : match + subpath; @@ -495,27 +507,28 @@ function resolvePackageTargetString( } /** - * @param {string} key - * @returns {boolean} + * Checks if the given key is a valid array index. + * @param {string} key - The key to check. + * @returns {boolean} - Returns `true` if the key is a valid array index, else `false`. */ function isArrayIndex(key) { const keyNum = +key; - if (`${keyNum}` !== key) return false; + if (`${keyNum}` !== key) { return false; } return keyNum >= 0 && keyNum < 0xFFFF_FFFF; } /** - * - * @param {*} packageJSONUrl - * @param {string|[string]} target - * @param {*} subpath - * @param {*} packageSubpath - * @param {*} base - * @param {*} pattern - * @param {*} internal - * @param {*} isPathMap - * @param {*} conditions - * @returns {URL|null} + * Resolves the target of a package based on the provided parameters. + * @param {string} packageJSONUrl - The URL of the package.json file. + * @param {import('internal/modules/esm/package_config.js').PackageTarget} target - The target to resolve. + * @param {string} subpath - The subpath to resolve. + * @param {string} packageSubpath - The subpath of the package to resolve. + * @param {string} base - The base path to resolve. + * @param {RegExp} pattern - The pattern to match. + * @param {boolean} internal - Whether the package is internal. + * @param {boolean} isPathMap - Whether the package is a path map. + * @param {Set} conditions - The conditions to match. + * @returns {URL | null | undefined} - The resolved target, or null if not found, or undefined if not resolvable. */ function resolvePackageTarget(packageJSONUrl, target, subpath, packageSubpath, base, pattern, internal, isPathMap, conditions) { @@ -552,8 +565,9 @@ function resolvePackageTarget(packageJSONUrl, target, subpath, packageSubpath, } return resolveResult; } - if (lastException === undefined || lastException === null) + if (lastException === undefined || lastException === null) { return lastException; + } throw lastException; } else if (typeof target === 'object' && target !== null) { const keys = ObjectGetOwnPropertyNames(target); @@ -572,8 +586,7 @@ function resolvePackageTarget(packageJSONUrl, target, subpath, packageSubpath, const resolveResult = resolvePackageTarget( packageJSONUrl, conditionalTarget, subpath, packageSubpath, base, pattern, internal, isPathMap, conditions); - if (resolveResult === undefined) - continue; + if (resolveResult === undefined) { continue; } return resolveResult; } } @@ -586,15 +599,14 @@ function resolvePackageTarget(packageJSONUrl, target, subpath, packageSubpath, } /** - * - * @param {import('internal/modules/esm/package_config.js').Exports} exports - * @param {URL} packageJSONUrl - * @param {string | URL | undefined} base - * @returns {boolean} + * Is the given exports object using the shorthand syntax? + * @param {import('internal/modules/esm/package_config.js').PackageConfig['exports']} exports + * @param {URL} packageJSONUrl The URL of the package.json file. + * @param {string | URL | undefined} base The base URL. */ function isConditionalExportsMainSugar(exports, packageJSONUrl, base) { - if (typeof exports === 'string' || ArrayIsArray(exports)) return true; - if (typeof exports !== 'object' || exports === null) return false; + if (typeof exports === 'string' || ArrayIsArray(exports)) { return true; } + if (typeof exports !== 'object' || exports === null) { return false; } const keys = ObjectGetOwnPropertyNames(exports); let isConditionalSugar = false; @@ -616,18 +628,20 @@ function isConditionalExportsMainSugar(exports, packageJSONUrl, base) { } /** - * @param {URL} packageJSONUrl - * @param {string} packageSubpath - * @param {PackageConfig} packageConfig - * @param {string | URL | undefined} base - * @param {Set} conditions - * @returns {URL} + * Resolves the exports of a package. + * @param {URL} packageJSONUrl - The URL of the package.json file. + * @param {string} packageSubpath - The subpath of the package to resolve. + * @param {import('internal/modules/esm/package_config.js').PackageConfig} packageConfig - The package metadata. + * @param {string | URL | undefined} base - The base path to resolve from. + * @param {Set} conditions - An array of conditions to match. + * @returns {URL} - The resolved package target. */ function packageExportsResolve( packageJSONUrl, packageSubpath, packageConfig, base, conditions) { let exports = packageConfig.exports; - if (isConditionalExportsMainSugar(exports, packageJSONUrl, base)) + if (isConditionalExportsMainSugar(exports, packageJSONUrl, base)) { exports = { '.': exports }; + } if (ObjectPrototypeHasOwnProperty(exports, packageSubpath) && !StringPrototypeIncludes(packageSubpath, '*') && @@ -660,9 +674,10 @@ function packageExportsResolve( // throwInvalidSubpath(packageSubpath) // // To match "imports" and the spec. - if (StringPrototypeEndsWith(packageSubpath, '/')) + if (StringPrototypeEndsWith(packageSubpath, '/')) { emitTrailingSlashPatternDeprecation(packageSubpath, packageJSONUrl, base); + } const patternTrailer = StringPrototypeSlice(key, patternIndex + 1); if (packageSubpath.length >= key.length && StringPrototypeEndsWith(packageSubpath, patternTrailer) && @@ -698,25 +713,35 @@ function packageExportsResolve( throw exportsNotFound(packageSubpath, packageJSONUrl, base); } +/** + * Compares two strings that may contain a wildcard character ('*') and returns a value indicating their order. + * @param {string} a - The first string to compare. + * @param {string} b - The second string to compare. + * @returns {number} - A negative number if `a` should come before `b`, a positive number if `a` should come after `b`, + * or 0 if they are equal. + */ function patternKeyCompare(a, b) { const aPatternIndex = StringPrototypeIndexOf(a, '*'); const bPatternIndex = StringPrototypeIndexOf(b, '*'); const baseLenA = aPatternIndex === -1 ? a.length : aPatternIndex + 1; const baseLenB = bPatternIndex === -1 ? b.length : bPatternIndex + 1; - if (baseLenA > baseLenB) return -1; - if (baseLenB > baseLenA) return 1; - if (aPatternIndex === -1) return 1; - if (bPatternIndex === -1) return -1; - if (a.length > b.length) return -1; - if (b.length > a.length) return 1; + if (baseLenA > baseLenB) { return -1; } + if (baseLenB > baseLenA) { return 1; } + if (aPatternIndex === -1) { return 1; } + if (bPatternIndex === -1) { return -1; } + if (a.length > b.length) { return -1; } + if (b.length > a.length) { return 1; } return 0; } /** - * @param {string} name - * @param {string | URL | undefined} base - * @param {Set} conditions - * @returns {URL} + * Resolves the given import name for a package. + * @param {string} name - The name of the import to resolve. + * @param {string | URL | undefined} base - The base URL to resolve the import from. + * @param {Set} conditions - An object containing the import conditions. + * @throws {ERR_INVALID_MODULE_SPECIFIER} If the import name is not valid. + * @throws {ERR_PACKAGE_IMPORT_NOT_DEFINED} If the import name cannot be resolved. + * @returns {URL} The resolved import URL. */ function packageImportsResolve(name, base, conditions) { if (name === '#' || StringPrototypeStartsWith(name, '#/') || @@ -779,8 +804,8 @@ function packageImportsResolve(name, base, conditions) { } /** - * @param {URL} url - * @returns {import('internal/modules/esm/package_config.js').PackageType} + * Returns the package type for a given URL. + * @param {URL} url - The URL to get the package type for. */ function getPackageType(url) { const packageConfig = getPackageScopeConfig(url); @@ -788,9 +813,9 @@ function getPackageType(url) { } /** - * @param {string} specifier - * @param {string | URL | undefined} base - * @returns {{ packageName: string, packageSubpath: string, isScoped: boolean }} + * Parse a package name from a specifier. + * @param {string} specifier - The import specifier. + * @param {string | URL | undefined} base - The parent URL. */ function parsePackageName(specifier, base) { let separatorIndex = StringPrototypeIndexOf(specifier, '/'); @@ -811,8 +836,9 @@ function parsePackageName(specifier, base) { // Package name cannot have leading . and cannot have percent-encoding or // \\ separators. - if (RegExpPrototypeExec(invalidPackageNameRegEx, packageName) !== null) + if (RegExpPrototypeExec(invalidPackageNameRegEx, packageName) !== null) { validPackageName = false; + } if (!validPackageName) { throw new ERR_INVALID_MODULE_SPECIFIER( @@ -826,14 +852,14 @@ function parsePackageName(specifier, base) { } /** - * @param {string} specifier - * @param {string | URL | undefined} base - * @param {Set} conditions - * @returns {resolved: URL, format? : string} + * Resolves a package specifier to a URL. + * @param {string} specifier - The package specifier to resolve. + * @param {string | URL | undefined} base - The base URL to use for resolution. + * @param {Set} conditions - An object containing the conditions for resolution. + * @returns {URL} - The resolved URL. */ function packageResolve(specifier, base, conditions) { - if (BuiltinModule.canBeRequiredByUsers(specifier) && - BuiltinModule.canBeRequiredWithoutScheme(specifier)) { + if (BuiltinModule.canBeRequiredWithoutScheme(specifier)) { return new URL('node:' + specifier); } @@ -844,8 +870,7 @@ function packageResolve(specifier, base, conditions) { const packageConfig = getPackageScopeConfig(base); if (packageConfig.exists) { const packageJSONUrl = pathToFileURL(packageConfig.pjsonPath); - if (packageConfig.name === packageName && - packageConfig.exports !== undefined && packageConfig.exports !== null) { + if (packageConfig.exports != null && packageConfig.name === packageName) { return packageExportsResolve( packageJSONUrl, packageSubpath, packageConfig, base, conditions); } @@ -856,9 +881,10 @@ function packageResolve(specifier, base, conditions) { let packageJSONPath = fileURLToPath(packageJSONUrl); let lastPath; do { - const stat = tryStatSync(StringPrototypeSlice(packageJSONPath, 0, - packageJSONPath.length - 13)); - if (!stat.isDirectory()) { + const stat = internalModuleStat(toNamespacedPath(StringPrototypeSlice(packageJSONPath, 0, + packageJSONPath.length - 13))); + // Check for !stat.isDirectory() + if (stat !== 1) { lastPath = packageJSONPath; packageJSONUrl = new URL((isScoped ? '../../../../node_modules/' : '../../../node_modules/') + @@ -868,8 +894,8 @@ function packageResolve(specifier, base, conditions) { } // Package match. - const packageConfig = getPackageConfig(packageJSONPath, specifier, base); - if (packageConfig.exports !== undefined && packageConfig.exports !== null) { + const packageConfig = packageJsonReader.read(packageJSONPath, { __proto__: null, specifier, base, isESM: true }); + if (packageConfig.exports != null) { return packageExportsResolve( packageJSONUrl, packageSubpath, packageConfig, base, conditions); } @@ -887,39 +913,47 @@ function packageResolve(specifier, base, conditions) { // eslint can't handle the above code. // eslint-disable-next-line no-unreachable - throw new ERR_MODULE_NOT_FOUND(packageName, fileURLToPath(base)); + throw new ERR_MODULE_NOT_FOUND(packageName, fileURLToPath(base), null); } /** - * @param {string} specifier - * @returns {boolean} + * Checks if a specifier is a bare specifier. + * @param {string} specifier - The specifier to check. */ function isBareSpecifier(specifier) { return specifier[0] && specifier[0] !== '/' && specifier[0] !== '.'; } +/** + * Determines whether a specifier is a relative path. + * @param {string} specifier - The specifier to check. + */ function isRelativeSpecifier(specifier) { if (specifier[0] === '.') { - if (specifier.length === 1 || specifier[1] === '/') return true; + if (specifier.length === 1 || specifier[1] === '/') { return true; } if (specifier[1] === '.') { - if (specifier.length === 2 || specifier[2] === '/') return true; + if (specifier.length === 2 || specifier[2] === '/') { return true; } } } return false; } +/** + * Determines whether a specifier should be treated as a relative or absolute path. + * @param {string} specifier - The specifier to check. + */ function shouldBeTreatedAsRelativeOrAbsolutePath(specifier) { - if (specifier === '') return false; - if (specifier[0] === '/') return true; + if (specifier === '') { return false; } + if (specifier[0] === '/') { return true; } return isRelativeSpecifier(specifier); } /** - * @param {string} specifier - * @param {string | URL | undefined} base - * @param {Set} conditions - * @param {boolean} preserveSymlinks - * @returns {url: URL, format?: string} + * Resolves a module specifier to a URL. + * @param {string} specifier - The module specifier to resolve. + * @param {string | URL | undefined} base - The base URL to resolve against. + * @param {Set} conditions - An object containing environment conditions. + * @param {boolean} preserveSymlinks - Whether to preserve symlinks in the resolved URL. */ function moduleResolve(specifier, base, conditions, preserveSymlinks) { const isRemote = base.protocol === 'http:' || @@ -947,10 +981,9 @@ function moduleResolve(specifier, base, conditions, preserveSymlinks) { } /** - * Try to resolve an import as a CommonJS module - * @param {string} specifier - * @param {string} parentURL - * @returns {boolean|string} + * Try to resolve an import as a CommonJS module. + * @param {string} specifier - The specifier to resolve. + * @param {string} parentURL - The base URL. */ function resolveAsCommonJS(specifier, parentURL) { try { @@ -992,7 +1025,14 @@ function resolveAsCommonJS(specifier, parentURL) { } } -// TODO(@JakobJingleheimer): de-dupe `specifier` & `parsed` +/** + * Throw an error if an import is not allowed. + * TODO(@JakobJingleheimer): de-dupe `specifier` & `parsed` + * @param {string} specifier - The import specifier. + * @param {URL} parsed - The parsed URL of the import specifier. + * @param {URL} parsedParentURL - The parsed URL of the parent module. + * @throws {ERR_NETWORK_IMPORT_DISALLOWED} - If the import is disallowed. + */ function checkIfDisallowedImport(specifier, parsed, parsedParentURL) { if (parsedParentURL) { // Avoid accessing the `protocol` property due to the lazy getters. @@ -1019,8 +1059,7 @@ function checkIfDisallowedImport(specifier, parsed, parsedParentURL) { return { url: parsed.href }; } - if (BuiltinModule.canBeRequiredByUsers(specifier) && - BuiltinModule.canBeRequiredWithoutScheme(specifier)) { + if (BuiltinModule.canBeRequiredWithoutScheme(specifier)) { throw new ERR_NETWORK_IMPORT_DISALLOWED( specifier, parsedParentURL, @@ -1037,9 +1076,31 @@ function checkIfDisallowedImport(specifier, parsed, parsedParentURL) { } } +/** + * Validate user-input in `context` supplied by a custom loader. + * @param {string | URL | undefined} parentURL - The parent URL. + */ +function throwIfInvalidParentURL(parentURL) { + if (parentURL === undefined) { + return; // Main entry point, so no parent + } + if (typeof parentURL !== 'string' && !isURL(parentURL)) { + throw new ERR_INVALID_ARG_TYPE('parentURL', ['string', 'URL'], parentURL); + } +} -async function defaultResolve(specifier, context = {}) { +/** + * Resolves the given specifier using the provided context, which includes the parent URL and conditions. + * Throws an error if the parent URL is invalid or if the resolution is disallowed by the policy manifest. + * Otherwise, attempts to resolve the specifier and returns the resulting URL and format. + * @param {string} specifier - The specifier to resolve. + * @param {object} [context={}] - The context object containing the parent URL and conditions. + * @param {string} [context.parentURL] - The URL of the parent module. + * @param {string[]} [context.conditions] - The conditions for resolving the specifier. + */ +function defaultResolve(specifier, context = {}) { let { parentURL, conditions } = context; + throwIfInvalidParentURL(parentURL); if (parentURL && policy?.manifest) { const redirects = policy.manifest.getDependencyMapper(parentURL); if (redirects) { @@ -1107,15 +1168,15 @@ async function defaultResolve(specifier, context = {}) { parsedParentURL, ); - if (maybeReturn) return maybeReturn; + if (maybeReturn) { return maybeReturn; } // This must come after checkIfDisallowedImport - if (parsed && parsed.protocol === 'node:') return { url: specifier }; + if (parsed && parsed.protocol === 'node:') { return { __proto__: null, url: specifier }; } const isMain = parentURL === undefined; if (isMain) { - parentURL = pathToFileURL(`${process.cwd()}/`).href; + parentURL = getCWDURL().href; // This is the initial entry point to the program, and --input-type has // been passed as an option; but --input-type can only be used with @@ -1123,7 +1184,7 @@ async function defaultResolve(specifier, context = {}) { // input, to avoid user confusion over how expansive the effect of the // flag should be (i.e. entry point only, package scope surrounding the // entry point, etc.). - if (typeFlag) throw new ERR_INPUT_TYPE_NOT_ALLOWED(); + if (inputTypeFlag) { throw new ERR_INPUT_TYPE_NOT_ALLOWED(); } } conditions = getConditionsSet(conditions); @@ -1143,17 +1204,7 @@ async function defaultResolve(specifier, context = {}) { if (StringPrototypeStartsWith(specifier, 'file://')) { specifier = fileURLToPath(specifier); } - const found = resolveAsCommonJS(specifier, parentURL); - if (found) { - // Modify the stack and message string to include the hint - const lines = StringPrototypeSplit(error.stack, '\n'); - const hint = `Did you mean to import ${found}?`; - error.stack = - ArrayPrototypeShift(lines) + '\n' + - hint + '\n' + - ArrayPrototypeJoin(lines, '\n'); - error.message += `\n${hint}`; - } + decorateErrorWithCommonJSHints(error, specifier, parentURL); } throw error; } @@ -1166,14 +1217,35 @@ async function defaultResolve(specifier, context = {}) { }; } +/** + * Decorates the given error with a hint for CommonJS modules. + * @param {Error} error - The error to decorate. + * @param {string} specifier - The specifier that was attempted to be imported. + * @param {string} parentURL - The URL of the parent module. + */ +function decorateErrorWithCommonJSHints(error, specifier, parentURL) { + const found = resolveAsCommonJS(specifier, parentURL); + if (found) { + // Modify the stack and message string to include the hint + const lines = StringPrototypeSplit(error.stack, '\n'); + const hint = `Did you mean to import ${found}?`; + error.stack = + ArrayPrototypeShift(lines) + '\n' + + hint + '\n' + + ArrayPrototypeJoin(lines, '\n'); + error.message += `\n${hint}`; + } +} + module.exports = { - DEFAULT_CONDITIONS, + decorateErrorWithCommonJSHints, defaultResolve, encodedSepRegEx, getPackageScopeConfig, getPackageType, packageExportsResolve, packageImportsResolve, + throwIfInvalidParentURL, }; // cycle @@ -1183,11 +1255,11 @@ const { if (policy) { const $defaultResolve = defaultResolve; - module.exports.defaultResolve = async function defaultResolve( + module.exports.defaultResolve = function defaultResolve( specifier, context, ) { - const ret = await $defaultResolve(specifier, context); + const ret = $defaultResolve(specifier, context); // This is a preflight check to avoid data exfiltration by query params etc. policy.manifest.mightAllow(ret.url, () => new ERR_MANIFEST_DEPENDENCY_MISSING( diff --git a/lib/internal/modules/esm/shared_constants.js b/lib/internal/modules/esm/shared_constants.js new file mode 100644 index 00000000000000..4200bc87367d14 --- /dev/null +++ b/lib/internal/modules/esm/shared_constants.js @@ -0,0 +1,25 @@ +// This file contains the definition for the constant values that must be +// available to both the main thread and the loader thread. + +'use strict'; + +/* +The shared memory area is divided in 1 32-bit long section. It has to be 32-bit long as +`Atomics.notify` only works with `Int32Array` objects. + +--32-bits-- + ^ + | + | +WORKER_TO_MAIN_THREAD_NOTIFICATION + +WORKER_TO_MAIN_THREAD_NOTIFICATION is only used to send notifications, its value is going to +increase every time the worker sends a notification to the main thread. + +*/ + +module.exports = { + WORKER_TO_MAIN_THREAD_NOTIFICATION: 0, + + SHARED_MEMORY_BYTE_LENGTH: 1 * 4, +}; diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js index a425749e82acd7..39af99c6c3b5b7 100644 --- a/lib/internal/modules/esm/translators.js +++ b/lib/internal/modules/esm/translators.js @@ -11,6 +11,7 @@ const { SafeArrayIterator, SafeMap, SafeSet, + StringPrototypeIncludes, StringPrototypeReplaceAll, StringPrototypeSlice, StringPrototypeStartsWith, @@ -18,9 +19,13 @@ const { globalThis: { WebAssembly }, } = primordials; +/** @type {import('internal/util/types')} */ let _TYPES = null; +/** + * Lazily loads and returns the internal/util/types module. + */ function lazyTypes() { - if (_TYPES !== null) return _TYPES; + if (_TYPES !== null) { return _TYPES; } return _TYPES = require('internal/util/types'); } @@ -30,15 +35,12 @@ const { hasEsmSyntax, loadBuiltinModule, stripBOM, -} = require('internal/modules/cjs/helpers'); +} = require('internal/modules/helpers'); const { Module: CJSModule, cjsParseCache, } = require('internal/modules/cjs/loader'); -const internalURLModule = require('internal/url'); -const createDynamicModule = require( - 'internal/modules/esm/create_dynamic_module'); -const { fileURLToPath, URL } = require('url'); +const { fileURLToPath, URL } = require('internal/url'); let debug = require('internal/util/debuglog').debuglog('esm', (fn) => { debug = fn; }); @@ -52,9 +54,14 @@ const moduleWrap = internalBinding('module_wrap'); const { ModuleWrap } = moduleWrap; const asyncESM = require('internal/process/esm_loader'); const { emitWarningSync } = require('internal/process/warning'); -const { TextDecoder } = require('internal/encoding'); +/** @type {import('deps/cjs-module-lexer/lexer.js').parse} */ let cjsParse; +/** + * Initializes the CommonJS module lexer parser. + * If WebAssembly is available, it uses the optimized version from the dist folder. + * Otherwise, it falls back to the JavaScript version from the lexer folder. + */ async function initCJSParse() { if (typeof WebAssembly === 'undefined') { cjsParse = require('internal/deps/cjs-module-lexer/lexer').parse; @@ -75,6 +82,14 @@ exports.translators = translators; exports.enrichCJSError = enrichCJSError; let DECODER = null; +/** + * Asserts that the given body is a buffer source (either a string, array buffer, or typed array). + * Throws an error if the body is not a buffer source. + * @param {string | ArrayBufferView | ArrayBuffer} body - The body to check. + * @param {boolean} allowString - Whether or not to allow a string as a valid buffer source. + * @param {string} hookName - The name of the hook being called. + * @throws {ERR_INVALID_RETURN_PROPERTY_VALUE} If the body is not a buffer source. + */ function assertBufferSource(body, allowString, hookName) { if (allowString && typeof body === 'string') { return; @@ -91,13 +106,23 @@ function assertBufferSource(body, allowString, hookName) { ); } +/** + * Converts a buffer or buffer-like object to a string. + * @param {string | ArrayBuffer | ArrayBufferView} body - The buffer or buffer-like object to convert to a string. + * @returns {string} The resulting string. + */ function stringify(body) { - if (typeof body === 'string') return body; + if (typeof body === 'string') { return body; } assertBufferSource(body, false, 'transformSource'); + const { TextDecoder } = require('internal/encoding'); DECODER = DECODER === null ? new TextDecoder() : DECODER; return DECODER.decode(body); } +/** + * Converts a URL to a file path if the URL protocol is 'file:'. + * @param {string} url - The URL to convert. + */ function errPath(url) { const parsed = new URL(url); if (parsed.protocol === 'file:') { @@ -106,8 +131,16 @@ function errPath(url) { return url; } -async function importModuleDynamically(specifier, { url }, assertions) { - return asyncESM.esmLoader.import(specifier, url, assertions); +/** + * Dynamically imports a module using the ESM loader. + * @param {string} specifier - The module specifier to import. + * @param {object} options - An object containing options for the import. + * @param {string} options.url - The URL of the module requesting the import. + * @param {Record} [attributes] - An object containing attributes for the import. + * @returns {Promise} The imported module. + */ +async function importModuleDynamically(specifier, { url }, attributes) { + return asyncESM.esmLoader.import(specifier, url, attributes); } // Strategy for loading a standard JavaScript module. @@ -117,7 +150,8 @@ translators.set('module', async function moduleStrategy(url, source, isMain) { maybeCacheSourceMap(url, source); debug(`Translating StandardModule ${url}`); const module = new ModuleWrap(url, undefined, source, 0, 0); - moduleWrap.callbackMap.set(module, { + const { setCallbackForWrap } = require('internal/modules/esm/utils'); + setCallbackForWrap(module, { initializeImportMeta: (meta, wrap) => this.importMetaInitialize(meta, { url }), importModuleDynamically, }); @@ -125,6 +159,7 @@ translators.set('module', async function moduleStrategy(url, source, isMain) { }); /** + * Provide a more informative error for CommonJS imports. * @param {Error | any} err * @param {string} [content] Content of the file, if known. * @param {string} [filename] Useful only if `content` is unknown. @@ -148,11 +183,9 @@ translators.set('commonjs', async function commonjsStrategy(url, source, isMain) { debug(`Translating CJSModule ${url}`); - let filename = internalURLModule.fileURLToPath(new URL(url)); - if (isWindows) - filename = StringPrototypeReplaceAll(filename, '/', '\\'); + const filename = fileURLToPath(new URL(url)); - if (!cjsParse) await initCJSParse(); + if (!cjsParse) { await initCJSParse(); } const { module, exportNames } = cjsPreparseModuleExports(filename); const namesWithDefault = exportNames.has('default') ? [...exportNames] : ['default', ...exportNames]; @@ -175,8 +208,9 @@ translators.set('commonjs', async function commonjsStrategy(url, source, for (const exportName of exportNames) { if (!ObjectPrototypeHasOwnProperty(exports, exportName) || - exportName === 'default') + exportName === 'default') { continue; + } // We might trigger a getter -> dont fail. let value; try { @@ -190,12 +224,17 @@ translators.set('commonjs', async function commonjsStrategy(url, source, }); }); +/** + * Pre-parses a CommonJS module's exports and re-exports. + * @param {string} filename - The filename of the module. + */ function cjsPreparseModuleExports(filename) { let module = CJSModule._cache[filename]; if (module) { const cached = cjsParseCache.get(module); - if (cached) + if (cached) { return { module, exportNames: cached.exportNames }; + } } const loaded = Boolean(module); if (!loaded) { @@ -240,8 +279,9 @@ function cjsPreparseModuleExports(filename) { if ((ext === '.js' || ext === '.cjs' || !CJSModule._extensions[ext]) && isAbsolute(resolved)) { const { exportNames: reexportNames } = cjsPreparseModuleExports(resolved); - for (const name of reexportNames) + for (const name of reexportNames) { exportNames.add(name); + } } }); @@ -269,9 +309,12 @@ translators.set('json', async function jsonStrategy(url, source) { debug(`Loading JSONModule ${url}`); const pathname = StringPrototypeStartsWith(url, 'file:') ? fileURLToPath(url) : null; + const shouldCheckAndPopulateCJSModuleCache = + // We want to involve the CJS loader cache only for `file:` URL with no search query and no hash. + pathname && !StringPrototypeIncludes(url, '?') && !StringPrototypeIncludes(url, '#'); let modulePath; let module; - if (pathname) { + if (shouldCheckAndPopulateCJSModuleCache) { modulePath = isWindows ? StringPrototypeReplaceAll(pathname, '/', '\\') : pathname; module = CJSModule._cache[modulePath]; @@ -283,7 +326,7 @@ translators.set('json', async function jsonStrategy(url, source) { } } source = stringify(source); - if (pathname) { + if (shouldCheckAndPopulateCJSModuleCache) { // A require call could have been called on the same file during loading and // that resolves synchronously. To make sure we always return the identical // export, we have to check again if the module already exists or not. @@ -309,7 +352,7 @@ translators.set('json', async function jsonStrategy(url, source) { err.message = errPath(url) + ': ' + err.message; throw err; } - if (pathname) { + if (shouldCheckAndPopulateCJSModuleCache) { CJSModule._cache[modulePath] = module; } return new ModuleWrap(url, undefined, ['default'], function() { @@ -341,9 +384,12 @@ translators.set('wasm', async function(url, source) { ArrayPrototypeMap(WebAssembly.Module.exports(compiled), ({ name }) => name); + const createDynamicModule = require( + 'internal/modules/esm/create_dynamic_module'); return createDynamicModule(imports, exports, url, (reflect) => { const { exports } = new WebAssembly.Instance(compiled, reflect.imports); - for (const expt of ObjectKeys(exports)) + for (const expt of ObjectKeys(exports)) { reflect.exports[expt].set(exports[expt]); + } }).module; }); diff --git a/lib/internal/modules/esm/utils.js b/lib/internal/modules/esm/utils.js index bf3edc86518b4c..df729ef96c7172 100644 --- a/lib/internal/modules/esm/utils.js +++ b/lib/internal/modules/esm/utils.js @@ -1,4 +1,5 @@ 'use strict'; + const { ArrayIsArray, SafeSet, @@ -10,9 +11,12 @@ const { ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING, ERR_INVALID_ARG_VALUE, } = require('internal/errors').codes; - const { getOptionValue } = require('internal/options'); - +const { + loadPreloadModules, + initializeFrozenIntrinsics, +} = require('internal/process/pre_execution'); +const { getCWDURL } = require('internal/util'); const { setImportModuleDynamicallyCallback, setInitializeImportMetaObjectCallback, @@ -28,18 +32,28 @@ function setCallbackForWrap(wrap, data) { } let defaultConditions; +/** + * Returns the default conditions for ES module loading. + */ function getDefaultConditions() { assert(defaultConditions !== undefined); return defaultConditions; } +/** @type {Set} */ let defaultConditionsSet; +/** + * Returns the default conditions for ES module loading, as a Set. + */ function getDefaultConditionsSet() { assert(defaultConditionsSet !== undefined); return defaultConditionsSet; } -// This function is called during pre-execution, before any user code is run. +/** + * Initializes the default conditions for ESM module loading. + * This function is called during pre-execution, before any user code is run. + */ function initializeDefaultConditions() { const userConditions = getOptionValue('--conditions'); const noAddons = getOptionValue('--no-addons'); @@ -69,27 +83,48 @@ function getConditionsSet(conditions) { return getDefaultConditionsSet(); } +/** + * Defines the `import.meta` object for a given module. + * @param {object} wrap - Reference to the module. + * @param {Record} meta - The import.meta object to initialize. + */ function initializeImportMetaObject(wrap, meta) { if (callbackMap.has(wrap)) { const { initializeImportMeta } = callbackMap.get(wrap); if (initializeImportMeta !== undefined) { - initializeImportMeta(meta, getModuleFromWrap(wrap) || wrap); + meta = initializeImportMeta(meta, getModuleFromWrap(wrap) || wrap); } } } -async function importModuleDynamicallyCallback(wrap, specifier, assertions) { +/** + * Asynchronously imports a module dynamically using a callback function. The native callback. + * @param {object} wrap - Reference to the module. + * @param {string} specifier - The module specifier string. + * @param {Record} attributes - The import attributes object. + * @returns {Promise} - The imported module object. + * @throws {ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING} - If the callback function is missing. + */ +async function importModuleDynamicallyCallback(wrap, specifier, attributes) { if (callbackMap.has(wrap)) { const { importModuleDynamically } = callbackMap.get(wrap); if (importModuleDynamically !== undefined) { return importModuleDynamically( - specifier, getModuleFromWrap(wrap) || wrap, assertions); + specifier, getModuleFromWrap(wrap) || wrap, attributes); } } throw new ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING(); } -function initializeESM() { +let _isLoaderWorker = false; +/** + * Initializes handling of ES modules. + * This is configured during pre-execution. Specifically it's set to true for + * the loader worker in internal/main/worker_thread.js. + * @param {boolean} [isLoaderWorker=false] - A boolean indicating whether the loader is a worker or not. + */ +function initializeESM(isLoaderWorker = false) { + _isLoaderWorker = isLoaderWorker; initializeDefaultConditions(); // Setup per-isolate callbacks that locate data or callbacks that we keep // track of for different ESM modules. @@ -97,9 +132,55 @@ function initializeESM() { setImportModuleDynamicallyCallback(importModuleDynamicallyCallback); } +/** + * Determine whether the current process is a loader worker. + * @returns {boolean} Whether the current process is a loader worker. + */ +function isLoaderWorker() { + return _isLoaderWorker; +} + +/** + * Register module customization hooks. + */ +async function initializeHooks() { + const customLoaderURLs = getOptionValue('--experimental-loader'); + + const { Hooks } = require('internal/modules/esm/hooks'); + const esmLoader = require('internal/process/esm_loader').esmLoader; + + const hooks = new Hooks(); + esmLoader.setCustomizations(hooks); + + // We need the loader customizations to be set _before_ we start invoking + // `--require`, otherwise loops can happen because a `--require` script + // might call `register(...)` before we've installed ourselves. These + // global values are magically set in `setupUserModules` just for us and + // we call them in the correct order. + // N.B. This block appears here specifically in order to ensure that + // `--require` calls occur before `--loader` ones do. + loadPreloadModules(); + initializeFrozenIntrinsics(); + + const parentURL = getCWDURL().href; + for (let i = 0; i < customLoaderURLs.length; i++) { + await hooks.register( + customLoaderURLs[i], + parentURL, + ); + } + + const preloadScripts = hooks.initializeGlobalPreload(); + + return { __proto__: null, hooks, preloadScripts }; +} + module.exports = { setCallbackForWrap, initializeESM, + initializeHooks, getDefaultConditions, getConditionsSet, + loaderWorkerId: 'internal/modules/esm/worker', + isLoaderWorker, }; diff --git a/lib/internal/modules/esm/worker.js b/lib/internal/modules/esm/worker.js new file mode 100644 index 00000000000000..7b295973abe7a4 --- /dev/null +++ b/lib/internal/modules/esm/worker.js @@ -0,0 +1,261 @@ +'use strict'; + +const { + DataViewPrototypeGetBuffer, + Int32Array, + PromisePrototypeThen, + ReflectApply, + SafeSet, + TypedArrayPrototypeGetBuffer, + globalThis: { + Atomics: { + add: AtomicsAdd, + notify: AtomicsNotify, + }, + }, +} = primordials; +const assert = require('internal/assert'); +const { clearImmediate, setImmediate } = require('timers'); +const { + hasUncaughtExceptionCaptureCallback, +} = require('internal/process/execution'); +const { + isArrayBuffer, + isDataView, + isTypedArray, +} = require('util/types'); + +const { receiveMessageOnPort } = require('internal/worker/io'); +const { + WORKER_TO_MAIN_THREAD_NOTIFICATION, +} = require('internal/modules/esm/shared_constants'); +const { initializeHooks } = require('internal/modules/esm/utils'); + + +/** + * Transfers an ArrayBuffer, TypedArray, or DataView to a worker thread. + * @param {boolean} hasError - Whether an error occurred during transfer. + * @param {ArrayBuffer | TypedArray | DataView} source - The data to transfer. + */ +function transferArrayBuffer(hasError, source) { + if (hasError || source == null) { return; } + if (isArrayBuffer(source)) { return [source]; } + if (isTypedArray(source)) { return [TypedArrayPrototypeGetBuffer(source)]; } + if (isDataView(source)) { return [DataViewPrototypeGetBuffer(source)]; } +} + +/** + * Wraps a message with a status and body, and serializes the body if necessary. + * @param {string} status - The status of the message. + * @param {unknown} body - The body of the message. + */ +function wrapMessage(status, body) { + if (status === 'success' || body === null || + (typeof body !== 'object' && + typeof body !== 'function' && + typeof body !== 'symbol')) { + return { status, body }; + } + + let serialized; + let serializationFailed; + try { + const { serializeError } = require('internal/error_serdes'); + serialized = serializeError(body); + } catch { + serializationFailed = true; + } + + return { + status, + body: { + serialized, + serializationFailed, + }, + }; +} + +/** + * Initializes a worker thread for a customized module loader. + * @param {SharedArrayBuffer} lock - The lock used to synchronize communication between the worker and the main thread. + * @param {MessagePort} syncCommPort - The message port used for synchronous communication between the worker and the + * main thread. + * @param {(err: Error, origin?: string) => void} errorHandler - The function to use for uncaught exceptions. + * @returns {Promise} A promise that resolves when the worker thread has been initialized. + */ +async function customizedModuleWorker(lock, syncCommPort, errorHandler) { + let hooks, preloadScripts, initializationError; + let hasInitializationError = false; + + { + // If a custom hook is calling `process.exit`, we should wake up the main thread + // so it can detect the exit event. + const { exit } = process; + process.exit = function(code) { + syncCommPort.postMessage(wrapMessage('exit', code ?? process.exitCode)); + AtomicsAdd(lock, WORKER_TO_MAIN_THREAD_NOTIFICATION, 1); + AtomicsNotify(lock, WORKER_TO_MAIN_THREAD_NOTIFICATION); + return ReflectApply(exit, this, arguments); + }; + } + + + try { + const initResult = await initializeHooks(); + hooks = initResult.hooks; + preloadScripts = initResult.preloadScripts; + } catch (exception) { + // If there was an error while parsing and executing a user loader, for example if because a + // loader contained a syntax error, then we need to send the error to the main thread so it can + // be thrown and printed. + hasInitializationError = true; + initializationError = exception; + } + + syncCommPort.on('message', handleMessage); + + if (hasInitializationError) { + syncCommPort.postMessage(wrapMessage('error', initializationError)); + } else { + syncCommPort.postMessage(wrapMessage('success', { preloadScripts }), preloadScripts.map(({ port }) => port)); + } + + // We're ready, so unlock the main thread. + AtomicsAdd(lock, WORKER_TO_MAIN_THREAD_NOTIFICATION, 1); + AtomicsNotify(lock, WORKER_TO_MAIN_THREAD_NOTIFICATION); + + let immediate; + /** + * Checks for messages on the syncCommPort and handles them asynchronously. + */ + function checkForMessages() { + immediate = setImmediate(checkForMessages).unref(); + // We need to let the event loop tick a few times to give the main thread a chance to send + // follow-up messages. + const response = receiveMessageOnPort(syncCommPort); + + if (response !== undefined) { + PromisePrototypeThen(handleMessage(response.message), undefined, errorHandler); + } + } + + const unsettledResponsePorts = new SafeSet(); + + process.on('beforeExit', () => { + for (const port of unsettledResponsePorts) { + port.postMessage(wrapMessage('never-settle')); + } + unsettledResponsePorts.clear(); + + AtomicsAdd(lock, WORKER_TO_MAIN_THREAD_NOTIFICATION, 1); + AtomicsNotify(lock, WORKER_TO_MAIN_THREAD_NOTIFICATION); + + // Attach back the event handler. + syncCommPort.on('message', handleMessage); + // Also check synchronously for a message, in case it's already there. + clearImmediate(immediate); + checkForMessages(); + // We don't need the sync check after this tick, as we already have added the event handler. + clearImmediate(immediate); + // Add some work for next tick so the worker cannot exit. + setImmediate(() => {}); + }); + + /** + * Handles incoming messages from the main thread or other workers. + * @param {object} options - The options object. + * @param {string} options.method - The name of the hook. + * @param {Array} options.args - The arguments to pass to the method. + * @param {MessagePort} options.port - The message port to use for communication. + */ + async function handleMessage({ method, args, port }) { + // Each potential exception needs to be caught individually so that the correct error is sent to + // the main thread. + let hasError = false; + let shouldRemoveGlobalErrorHandler = false; + assert(typeof hooks[method] === 'function'); + if (port == null && !hasUncaughtExceptionCaptureCallback()) { + // When receiving sync messages, we want to unlock the main thread when there's an exception. + process.on('uncaughtException', errorHandler); + shouldRemoveGlobalErrorHandler = true; + } + + // We are about to yield the execution with `await ReflectApply` below. In case the code + // following the `await` never runs, we remove the message handler so the `beforeExit` event + // can be triggered. + syncCommPort.off('message', handleMessage); + + // We keep checking for new messages to not miss any. + clearImmediate(immediate); + immediate = setImmediate(checkForMessages).unref(); + + unsettledResponsePorts.add(port ?? syncCommPort); + + let response; + try { + response = await ReflectApply(hooks[method], hooks, args); + } catch (exception) { + hasError = true; + response = exception; + } + + unsettledResponsePorts.delete(port ?? syncCommPort); + + // Send the method response (or exception) to the main thread. + try { + (port ?? syncCommPort).postMessage( + wrapMessage(hasError ? 'error' : 'success', response), + transferArrayBuffer(hasError, response?.source), + ); + } catch (exception) { + // Or send the exception thrown when trying to send the response. + (port ?? syncCommPort).postMessage(wrapMessage('error', exception)); + } + + AtomicsAdd(lock, WORKER_TO_MAIN_THREAD_NOTIFICATION, 1); + AtomicsNotify(lock, WORKER_TO_MAIN_THREAD_NOTIFICATION); + if (shouldRemoveGlobalErrorHandler) { + process.off('uncaughtException', errorHandler); + } + + syncCommPort.off('message', handleMessage); + // We keep checking for new messages to not miss any. + clearImmediate(immediate); + immediate = setImmediate(checkForMessages).unref(); + } +} + +/** + * Initializes a worker thread for a module with customized hooks. + * ! Run everything possible within this function so errors get reported. + * @param {{lock: SharedArrayBuffer}} workerData - The lock used to synchronize with the main thread. + * @param {MessagePort} syncCommPort - The communication port used to communicate with the main thread. + */ +module.exports = function setupModuleWorker(workerData, syncCommPort) { + const lock = new Int32Array(workerData.lock); + + /** + * Handles errors that occur in the worker thread. + * @param {Error} err - The error that occurred. + * @param {string} [origin='unhandledRejection'] - The origin of the error. + */ + function errorHandler(err, origin = 'unhandledRejection') { + AtomicsAdd(lock, WORKER_TO_MAIN_THREAD_NOTIFICATION, 1); + AtomicsNotify(lock, WORKER_TO_MAIN_THREAD_NOTIFICATION); + process.off('uncaughtException', errorHandler); + if (hasUncaughtExceptionCaptureCallback()) { + process._fatalException(err); + return; + } + internalBinding('errors').triggerUncaughtException( + err, + origin === 'unhandledRejection', + ); + } + + return PromisePrototypeThen( + customizedModuleWorker(lock, syncCommPort, errorHandler), + undefined, + errorHandler, + ); +}; diff --git a/lib/internal/modules/helpers.js b/lib/internal/modules/helpers.js new file mode 100644 index 00000000000000..7f2959cc469dc1 --- /dev/null +++ b/lib/internal/modules/helpers.js @@ -0,0 +1,333 @@ +'use strict'; + +const { + ArrayPrototypeForEach, + ArrayPrototypeJoin, + ArrayPrototypeSome, + ObjectDefineProperty, + ObjectPrototypeHasOwnProperty, + SafeMap, + SafeSet, + StringPrototypeCharCodeAt, + StringPrototypeIncludes, + StringPrototypeSlice, + StringPrototypeStartsWith, +} = primordials; +const { + ERR_INVALID_ARG_TYPE, + ERR_MANIFEST_DEPENDENCY_MISSING, + ERR_UNKNOWN_BUILTIN_MODULE, +} = require('internal/errors').codes; +const { BuiltinModule } = require('internal/bootstrap/realm'); + +const { validateString } = require('internal/validators'); +const fs = require('fs'); // Import all of `fs` so that it can be monkey-patched. +const internalFS = require('internal/fs/utils'); +const path = require('path'); +const { pathToFileURL, fileURLToPath, URL } = require('internal/url'); + +const { getOptionValue } = require('internal/options'); +const { setOwnProperty } = require('internal/util'); + +const { + privateSymbols: { + require_private_symbol, + }, +} = internalBinding('util'); + +let debug = require('internal/util/debuglog').debuglog('module', (fn) => { + debug = fn; +}); + +/** @typedef {import('internal/modules/cjs/loader.js').Module} Module */ + +/** + * Cache for storing resolved real paths of modules. + * In order to minimize unnecessary lstat() calls, this cache is a list of known-real paths. + * Set to an empty Map to reset. + * @type {Map} + */ +const realpathCache = new SafeMap(); +/** + * Resolves the path of a given `require` specifier, following symlinks. + * @param {string} requestPath The `require` specifier + */ +function toRealPath(requestPath) { + return fs.realpathSync(requestPath, { + [internalFS.realpathCacheKey]: realpathCache, + }); +} + +/** @type {Set} */ +let cjsConditions; +/** + * Define the conditions that apply to the CommonJS loader. + */ +function initializeCjsConditions() { + const userConditions = getOptionValue('--conditions'); + const noAddons = getOptionValue('--no-addons'); + const addonConditions = noAddons ? [] : ['node-addons']; + // TODO: Use this set when resolving pkg#exports conditions in loader.js. + cjsConditions = new SafeSet([ + 'require', + 'node', + ...addonConditions, + ...userConditions, + ]); +} + +/** + * Get the conditions that apply to the CommonJS loader. + */ +function getCjsConditions() { + if (cjsConditions === undefined) { + initializeCjsConditions(); + } + return cjsConditions; +} + +/** + * Provide one of Node.js' public modules to user code. + * @param {string} id - The identifier/specifier of the builtin module to load + * @param {string} request - The module requiring or importing the builtin module + */ +function loadBuiltinModule(id, request) { + if (!BuiltinModule.canBeRequiredByUsers(id)) { + return; + } + /** @type {import('internal/bootstrap/realm.js').BuiltinModule} */ + const mod = BuiltinModule.map.get(id); + debug('load built-in module %s', request); + // compileForPublicLoader() throws if canBeRequiredByUsers is false: + mod.compileForPublicLoader(); + return mod; +} + +/** @type {Module} */ +let $Module = null; +/** + * Import the Module class on first use. + */ +function lazyModule() { + $Module = $Module || require('internal/modules/cjs/loader').Module; + return $Module; +} + +/** + * Invoke with `makeRequireFunction(module)` where `module` is the `Module` object to use as the context for the + * `require()` function. + * Use redirects to set up a mapping from a policy and restrict dependencies. + */ +const urlToFileCache = new SafeMap(); +/** + * Create the module-scoped `require` function to pass into CommonJS modules. + * @param {Module} mod - The module to create the `require` function for. + * @param {ReturnType} redirects + * @typedef {(specifier: string) => unknown} RequireFunction + */ +function makeRequireFunction(mod, redirects) { + // lazy due to cycle + const Module = lazyModule(); + if (mod instanceof Module !== true) { + throw new ERR_INVALID_ARG_TYPE('mod', 'Module', mod); + } + + /** @type {RequireFunction} */ + let require; + if (redirects) { + const id = mod.filename || mod.id; + const conditions = getCjsConditions(); + const { resolve, reaction } = redirects; + require = function require(specifier) { + let missing = true; + const destination = resolve(specifier, conditions); + if (destination === true) { + missing = false; + } else if (destination) { + const { href, protocol } = destination; + if (protocol === 'node:') { + const specifier = destination.pathname; + + if (BuiltinModule.canBeRequiredByUsers(specifier)) { + const mod = loadBuiltinModule(specifier, href); + return mod.exports; + } + throw new ERR_UNKNOWN_BUILTIN_MODULE(specifier); + } else if (protocol === 'file:') { + let filepath = urlToFileCache.get(href); + if (!filepath) { + filepath = fileURLToPath(destination); + urlToFileCache.set(href, filepath); + } + return mod[require_private_symbol](mod, filepath); + } + } + if (missing) { + reaction(new ERR_MANIFEST_DEPENDENCY_MISSING( + id, + specifier, + ArrayPrototypeJoin([...conditions], ', '), + )); + } + return mod[require_private_symbol](mod, specifier); + }; + } else { + require = function require(path) { + // When no policy manifest, the original prototype.require is sustained + return mod.require(path); + }; + } + + /** + * The `resolve` method that gets attached to module-scope `require`. + * @param {string} request + * @param {Parameters[3]} options + */ + function resolve(request, options) { + validateString(request, 'request'); + return Module._resolveFilename(request, mod, false, options); + } + + require.resolve = resolve; + + /** + * The `paths` method that gets attached to module-scope `require`. + * @param {string} request + */ + function paths(request) { + validateString(request, 'request'); + return Module._resolveLookupPaths(request, mod); + } + + resolve.paths = paths; + + setOwnProperty(require, 'main', process.mainModule); + + // Enable support to add extra extension types. + require.extensions = Module._extensions; + + require.cache = Module._cache; + + return require; +} + +/** + * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) + * because the buffer-to-string conversion in `fs.readFileSync()` + * translates it to FEFF, the UTF-16 BOM. + * @param {string} content + */ +function stripBOM(content) { + if (StringPrototypeCharCodeAt(content) === 0xFEFF) { + content = StringPrototypeSlice(content, 1); + } + return content; +} + +/** + * Add built-in modules to a global or REPL scope object. + * @param {Record} object - The object such as `globalThis` to add the built-in modules to. + * @param {string} dummyModuleName - The label representing the set of built-in modules to add. + */ +function addBuiltinLibsToObject(object, dummyModuleName) { + // Make built-in modules available directly (loaded lazily). + const Module = require('internal/modules/cjs/loader').Module; + const { builtinModules } = Module; + + // To require built-in modules in user-land and ignore modules whose + // `canBeRequiredByUsers` is false. So we create a dummy module object and not + // use `require()` directly. + const dummyModule = new Module(dummyModuleName); + + ArrayPrototypeForEach(builtinModules, (name) => { + // Neither add underscored modules, nor ones that contain slashes (e.g., + // 'fs/promises') or ones that are already defined. + if (StringPrototypeStartsWith(name, '_') || + StringPrototypeIncludes(name, '/') || + ObjectPrototypeHasOwnProperty(object, name)) { + return; + } + // Goals of this mechanism are: + // - Lazy loading of built-in modules + // - Having all built-in modules available as non-enumerable properties + // - Allowing the user to re-assign these variables as if there were no + // pre-existing globals with the same name. + + const setReal = (val) => { + // Deleting the property before re-assigning it disables the + // getter/setter mechanism. + delete object[name]; + object[name] = val; + }; + + ObjectDefineProperty(object, name, { + __proto__: null, + get: () => { + const lib = dummyModule.require(name); + + try { + // Override the current getter/setter and set up a new + // non-enumerable property. + ObjectDefineProperty(object, name, { + __proto__: null, + get: () => lib, + set: setReal, + configurable: true, + enumerable: false, + }); + } catch { + // If the property is no longer configurable, ignore the error. + } + + return lib; + }, + set: setReal, + configurable: true, + enumerable: false, + }); + }); +} + +/** + * If a referrer is an URL instance or absolute path, convert it into an URL string. + * @param {string | URL} referrer + */ +function normalizeReferrerURL(referrer) { + if (typeof referrer === 'string' && path.isAbsolute(referrer)) { + return pathToFileURL(referrer).href; + } + return new URL(referrer).href; +} + +/** + * For error messages only, check if ESM syntax is in use. + * @param {string} code + */ +function hasEsmSyntax(code) { + debug('Checking for ESM syntax'); + const parser = require('internal/deps/acorn/acorn/dist/acorn').Parser; + let root; + try { + root = parser.parse(code, { sourceType: 'module', ecmaVersion: 'latest' }); + } catch { + return false; + } + + return ArrayPrototypeSome(root.body, (stmt) => + stmt.type === 'ExportDefaultDeclaration' || + stmt.type === 'ExportNamedDeclaration' || + stmt.type === 'ImportDeclaration' || + stmt.type === 'ExportAllDeclaration'); +} + +module.exports = { + addBuiltinLibsToObject, + getCjsConditions, + initializeCjsConditions, + hasEsmSyntax, + loadBuiltinModule, + makeRequireFunction, + normalizeReferrerURL, + stripBOM, + toRealPath, +}; diff --git a/lib/internal/modules/package_json_reader.js b/lib/internal/modules/package_json_reader.js index bb175d0df54c04..1968960576013c 100644 --- a/lib/internal/modules/package_json_reader.js +++ b/lib/internal/modules/package_json_reader.js @@ -1,30 +1,124 @@ 'use strict'; -const { SafeMap } = primordials; +const { + JSONParse, + ObjectPrototypeHasOwnProperty, + SafeMap, + StringPrototypeEndsWith, + StringPrototypeIndexOf, + StringPrototypeLastIndexOf, + StringPrototypeSlice, +} = primordials; +const { + ERR_INVALID_PACKAGE_CONFIG, +} = require('internal/errors').codes; const { internalModuleReadJSON } = internalBinding('fs'); -const { pathToFileURL } = require('url'); -const { toNamespacedPath } = require('path'); +const { resolve, sep, toNamespacedPath } = require('path'); +const { kEmptyObject } = require('internal/util'); + +const { fileURLToPath, pathToFileURL } = require('internal/url'); const cache = new SafeMap(); +const isAIX = process.platform === 'aix'; let manifest; /** - * + * @typedef {{ + * exists: boolean, + * pjsonPath: string, + * exports?: string | string[] | Record, + * imports?: string | string[] | Record, + * name?: string, + * main?: string, + * type: 'commonjs' | 'module' | 'none', + * }} PackageConfig + */ + +/** * @param {string} jsonPath + * @param {{ + * base?: string, + * specifier: string, + * isESM: boolean, + * }} options + * @returns {PackageConfig} */ -function read(jsonPath) { +function read(jsonPath, { base, specifier, isESM } = kEmptyObject) { if (cache.has(jsonPath)) { return cache.get(jsonPath); } - const { 0: string, 1: containsKeys } = internalModuleReadJSON( + const { + 0: string, + 1: containsKeys, + } = internalModuleReadJSON( toNamespacedPath(jsonPath), ); - const result = { string, containsKeys }; - const { getOptionValue } = require('internal/options'); - if (string !== undefined) { + const result = { + __proto__: null, + exists: false, + pjsonPath: jsonPath, + main: undefined, + name: undefined, + type: 'none', // Ignore unknown types for forwards compatibility + exports: undefined, + imports: undefined, + }; + + // Folder read operation succeeds in AIX. + // For libuv change, see https://github.com/libuv/libuv/pull/2025. + // https://github.com/nodejs/node/pull/48477#issuecomment-1604586650 + // TODO(anonrig): Follow-up on this change and remove it since it is a + // semver-major change. + const isResultValid = isAIX && !isESM ? containsKeys : string !== undefined; + + if (isResultValid) { + let parsed; + try { + parsed = JSONParse(string); + } catch (error) { + if (isESM) { + throw new ERR_INVALID_PACKAGE_CONFIG( + jsonPath, + (base ? `"${specifier}" from ` : '') + fileURLToPath(base || specifier), + error.message, + ); + } else { + // For backward compat, we modify the error returned by JSON.parse rather than creating a new one. + // TODO(aduh95): make it throw ERR_INVALID_PACKAGE_CONFIG in a semver-major with original error as cause + error.message = 'Error parsing ' + jsonPath + ': ' + error.message; + error.path = jsonPath; + throw error; + } + } + + result.exists = true; + + // ObjectPrototypeHasOwnProperty is used to avoid prototype pollution. + if (ObjectPrototypeHasOwnProperty(parsed, 'name') && typeof parsed.name === 'string') { + result.name = parsed.name; + } + + if (ObjectPrototypeHasOwnProperty(parsed, 'main') && typeof parsed.main === 'string') { + result.main = parsed.main; + } + + if (ObjectPrototypeHasOwnProperty(parsed, 'exports')) { + result.exports = parsed.exports; + } + + if (ObjectPrototypeHasOwnProperty(parsed, 'imports')) { + result.imports = parsed.imports; + } + + // Ignore unknown types for forwards compatibility + if (ObjectPrototypeHasOwnProperty(parsed, 'type') && (parsed.type === 'commonjs' || parsed.type === 'module')) { + result.type = parsed.type; + } + if (manifest === undefined) { + const { getOptionValue } = require('internal/options'); manifest = getOptionValue('--experimental-policy') ? require('internal/process/policy').manifest : null; @@ -38,4 +132,41 @@ function read(jsonPath) { return result; } -module.exports = { read }; +/** + * @param {string} requestPath + * @return {PackageConfig} + */ +function readPackage(requestPath) { + return read(resolve(requestPath, 'package.json')); +} + +/** + * Get the nearest parent package.json file from a given path. + * Return the package.json data and the path to the package.json file, or false. + * @param {string} checkPath The path to start searching from. + */ +function readPackageScope(checkPath) { + const rootSeparatorIndex = StringPrototypeIndexOf(checkPath, sep); + let separatorIndex; + do { + separatorIndex = StringPrototypeLastIndexOf(checkPath, sep); + checkPath = StringPrototypeSlice(checkPath, 0, separatorIndex); + if (StringPrototypeEndsWith(checkPath, sep + 'node_modules')) { + return false; + } + const pjson = readPackage(checkPath + sep); + if (pjson.exists) { + return { + data: pjson, + path: checkPath, + }; + } + } while (separatorIndex > rootSeparatorIndex); + return false; +} + +module.exports = { + read, + readPackage, + readPackageScope, +}; diff --git a/lib/internal/modules/run_main.js b/lib/internal/modules/run_main.js index daaa153516c424..287f3ed91b1d7b 100644 --- a/lib/internal/modules/run_main.js +++ b/lib/internal/modules/run_main.js @@ -1,33 +1,56 @@ 'use strict'; const { - ObjectCreate, StringPrototypeEndsWith, } = primordials; -const CJSLoader = require('internal/modules/cjs/loader'); -const { Module, toRealPath, readPackageScope } = CJSLoader; + const { getOptionValue } = require('internal/options'); const path = require('path'); -const { - handleProcessExit, -} = require('internal/modules/esm/handle_process_exit'); +/** + * Get the absolute path to the main entry point. + * @param {string} main - Entry point path + */ function resolveMainPath(main) { - // Note extension resolution for the main entry point can be deprecated in a - // future major. - // Module._findPath is monkey-patchable here. - let mainPath = Module._findPath(path.resolve(main), null, true); - if (!mainPath) - return; + const defaultType = getOptionValue('--experimental-default-type'); + /** @type {string} */ + let mainPath; + if (defaultType === 'module') { + if (getOptionValue('--preserve-symlinks-main')) { return; } + mainPath = path.resolve(main); + } else { + // Extension searching for the main entry point is supported only in legacy mode. + // Module._findPath is monkey-patchable here. + const { Module } = require('internal/modules/cjs/loader'); + mainPath = Module._findPath(path.resolve(main), null, true); + } + if (!mainPath) { return; } const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main'); - if (!preserveSymlinksMain) - mainPath = toRealPath(mainPath); + if (!preserveSymlinksMain) { + const { toRealPath } = require('internal/modules/helpers'); + try { + mainPath = toRealPath(mainPath); + } catch (err) { + if (defaultType === 'module' && err?.code === 'ENOENT') { + const { decorateErrorWithCommonJSHints } = require('internal/modules/esm/resolve'); + const { getCWDURL } = require('internal/util'); + decorateErrorWithCommonJSHints(err, mainPath, getCWDURL()); + } + throw err; + } + } return mainPath; } +/** + * Determine whether the main entry point should be loaded through the ESM Loader. + * @param {string} mainPath - Absolute path to the main entry point + */ function shouldUseESMLoader(mainPath) { + if (getOptionValue('--experimental-default-type') === 'module') { return true; } + /** * @type {string[]} userLoaders A list of custom loaders registered by the user * (or an empty list when none have been registered). @@ -38,33 +61,46 @@ function shouldUseESMLoader(mainPath) { * (or an empty list when none have been registered). */ const userImports = getOptionValue('--import'); - if (userLoaders.length > 0 || userImports.length > 0) + if (userLoaders.length > 0 || userImports.length > 0) { return true; + } const esModuleSpecifierResolution = getOptionValue('--experimental-specifier-resolution'); - if (esModuleSpecifierResolution === 'node') - return true; - // Determine the module format of the main - if (mainPath && StringPrototypeEndsWith(mainPath, '.mjs')) + if (esModuleSpecifierResolution === 'node') { return true; - if (!mainPath || StringPrototypeEndsWith(mainPath, '.cjs')) - return false; + } + // Determine the module format of the entry point. + if (mainPath && StringPrototypeEndsWith(mainPath, '.mjs')) { return true; } + if (!mainPath || StringPrototypeEndsWith(mainPath, '.cjs')) { return false; } + + const { readPackageScope } = require('internal/modules/package_json_reader'); const pkg = readPackageScope(mainPath); - return pkg && pkg.data.type === 'module'; + // No need to guard `pkg` as it can only be an object or `false`. + return pkg.data?.type === 'module' || getOptionValue('--experimental-default-type') === 'module'; } +/** + * Run the main entry point through the ESM Loader. + * @param {string} mainPath - Absolute path for the main entry point + */ function runMainESM(mainPath) { const { loadESM } = require('internal/process/esm_loader'); const { pathToFileURL } = require('internal/url'); + const main = pathToFileURL(mainPath).href; handleMainPromise(loadESM((esmLoader) => { - const main = path.isAbsolute(mainPath) ? - pathToFileURL(mainPath).href : mainPath; - return esmLoader.import(main, undefined, ObjectCreate(null)); + return esmLoader.import(main, undefined, { __proto__: null }); })); } +/** + * Handle process exit events around the main entry point promise. + * @param {Promise} promise - Main entry point promise + */ async function handleMainPromise(promise) { + const { + handleProcessExit, + } = require('internal/modules/esm/handle_process_exit'); process.on('exit', handleProcessExit); try { return await promise; @@ -73,9 +109,14 @@ async function handleMainPromise(promise) { } } -// For backwards compatibility, we have to run a bunch of -// monkey-patchable code that belongs to the CJS loader (exposed by -// `require('module')`) even when the entry point is ESM. +/** + * Parse the CLI main entry point string and run it. + * For backwards compatibility, we have to run a bunch of monkey-patchable code that belongs to the CJS loader (exposed + * by `require('module')`) even when the entry point is ESM. + * This monkey-patchable code is bypassed under `--experimental-default-type=module`. + * Because of backwards compatibility, this function is exposed publicly via `import { runMain } from 'node:module'`. + * @param {string} main - First positional CLI argument, such as `'entry.js'` from `node entry.js` + */ function executeUserEntryPoint(main = process.argv[1]) { const resolvedMain = resolveMainPath(main); const useESMLoader = shouldUseESMLoader(resolvedMain); @@ -83,6 +124,7 @@ function executeUserEntryPoint(main = process.argv[1]) { runMainESM(resolvedMain || main); } else { // Module._load is the monkey-patchable CJS module loader. + const { Module } = require('internal/modules/cjs/loader'); Module._load(main, null, true); } } diff --git a/lib/internal/perf/performance.js b/lib/internal/perf/performance.js index 130613c5635fa4..6b619c3ecc13f7 100644 --- a/lib/internal/perf/performance.js +++ b/lib/internal/perf/performance.js @@ -206,15 +206,24 @@ ObjectDefineProperties(Performance.prototype, { enumerable: false, value: timerify, }, - // This would be updated during pre-execution in case - // the process is launched from a snapshot. - // TODO(joyeecheung): we may want to warn about access to - // this during snapshot building. timeOrigin: { __proto__: null, configurable: true, enumerable: true, - value: getTimeOriginTimestamp(), + get() { + const value = getTimeOriginTimestamp(); + ObjectDefineProperty(Performance.prototype, 'timeOrigin', { + __proto__: null, + value, + }); + return value; + }, + set(value) { + ObjectDefineProperty(Performance.prototype, 'timeOrigin', { + __proto__: null, + value, + }); + }, }, toJSON: { __proto__: null, @@ -224,15 +233,6 @@ ObjectDefineProperties(Performance.prototype, { }, }); -function refreshTimeOrigin() { - ObjectDefineProperty(Performance.prototype, 'timeOrigin', { - __proto__: null, - configurable: true, - enumerable: true, - value: getTimeOriginTimestamp(), - }); -} - const performance = new InternalPerformance(); function dispatchBufferFull(type) { @@ -246,5 +246,4 @@ setDispatchBufferFull(dispatchBufferFull); module.exports = { Performance, performance, - refreshTimeOrigin, }; diff --git a/lib/internal/process/esm_loader.js b/lib/internal/process/esm_loader.js index bb621d2aa255c3..a3451ddab307f2 100644 --- a/lib/internal/process/esm_loader.js +++ b/lib/internal/process/esm_loader.js @@ -1,113 +1,46 @@ 'use strict'; const { - ArrayIsArray, - ObjectCreate, + SafePromiseAllReturnVoid, } = primordials; -const { - ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING, -} = require('internal/errors').codes; -const { ESMLoader } = require('internal/modules/esm/loader'); +const { createModuleLoader } = require('internal/modules/esm/loader'); +const { getOptionValue } = require('internal/options'); const { hasUncaughtExceptionCaptureCallback, } = require('internal/process/execution'); -const { pathToFileURL } = require('internal/url'); -const { - getModuleFromWrap, -} = require('internal/vm/module'); - -exports.initializeImportMetaObject = function(wrap, meta) { - const { callbackMap } = internalBinding('module_wrap'); - if (callbackMap.has(wrap)) { - const { initializeImportMeta } = callbackMap.get(wrap); - if (initializeImportMeta !== undefined) { - initializeImportMeta(meta, getModuleFromWrap(wrap) || wrap); - } - } -}; - -exports.importModuleDynamicallyCallback = -async function importModuleDynamicallyCallback(wrap, specifier, assertions) { - const { callbackMap } = internalBinding('module_wrap'); - if (callbackMap.has(wrap)) { - const { importModuleDynamically } = callbackMap.get(wrap); - if (importModuleDynamically !== undefined) { - return importModuleDynamically( - specifier, getModuleFromWrap(wrap) || wrap, assertions); - } - } - throw new ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING(); -}; - -const esmLoader = new ESMLoader(); -exports.esmLoader = esmLoader; - -// Module.runMain() causes loadESM() to re-run (which it should do); however, this should NOT cause -// ESM to be re-initialised; doing so causes duplicate custom loaders to be added to the public -// esmLoader. -let isESMInitialized = false; - -/** - * Causes side-effects: user-defined loader hooks are added to esmLoader. - * @returns {void} - */ -async function initializeLoader() { - if (isESMInitialized) { return; } - - const { getOptionValue } = require('internal/options'); - const customLoaders = getOptionValue('--experimental-loader'); - const preloadModules = getOptionValue('--import'); - const loaders = await loadModulesInIsolation(customLoaders); - - // Hooks must then be added to external/public loader - // (so they're triggered in userland) - esmLoader.addCustomLoaders(loaders); - - // Preload after loaders are added so they can be used - if (preloadModules?.length) { - await loadModulesInIsolation(preloadModules, loaders); - } - - isESMInitialized = true; -} - -function loadModulesInIsolation(specifiers, loaders = []) { - if (!ArrayIsArray(specifiers) || specifiers.length === 0) { return; } - - let cwd; - try { - cwd = process.cwd() + '/'; - } catch { - cwd = 'file:///'; - } - - // A separate loader instance is necessary to avoid cross-contamination - // between internal Node.js and userland. For example, a module with internal - // state (such as a counter) should be independent. - const internalEsmLoader = new ESMLoader(); - internalEsmLoader.addCustomLoaders(loaders); - - // Importation must be handled by internal loader to avoid poluting userland - return internalEsmLoader.import( - specifiers, - pathToFileURL(cwd).href, - ObjectCreate(null), - ); -} - -exports.loadESM = async function loadESM(callback) { - try { - await initializeLoader(); - await callback(esmLoader); - } catch (err) { - if (hasUncaughtExceptionCaptureCallback()) { - process._fatalException(err); - return; +const { kEmptyObject, getCWDURL } = require('internal/util'); + +let esmLoader; + +module.exports = { + get esmLoader() { + return esmLoader ??= createModuleLoader(true); + }, + async loadESM(callback) { + esmLoader ??= createModuleLoader(true); + try { + const userImports = getOptionValue('--import'); + if (userImports.length > 0) { + const parentURL = getCWDURL().href; + await SafePromiseAllReturnVoid(userImports, (specifier) => esmLoader.import( + specifier, + parentURL, + kEmptyObject, + )); + } else { + esmLoader.forceLoadHooks(); + } + await callback(esmLoader); + } catch (err) { + if (hasUncaughtExceptionCaptureCallback()) { + process._fatalException(err); + return; + } + internalBinding('errors').triggerUncaughtException( + err, + true, /* fromPromise */ + ); } - internalBinding('errors').triggerUncaughtException( - err, - true, /* fromPromise */ - ); - } + }, }; diff --git a/lib/internal/process/execution.js b/lib/internal/process/execution.js index 7379db357bdcc4..c3a63f63d1d613 100644 --- a/lib/internal/process/execution.js +++ b/lib/internal/process/execution.js @@ -83,9 +83,9 @@ function evalScript(name, body, breakFirstLine, print, shouldLoadESM = false) { filename: name, displayErrors: true, [kVmBreakFirstLineSymbol]: !!breakFirstLine, - importModuleDynamically(specifier, _, importAssertions) { + importModuleDynamically(specifier, _, importAttributes) { const loader = asyncESM.esmLoader; - return loader.import(specifier, baseUrl, importAssertions); + return loader.import(specifier, baseUrl, importAttributes); }, })); if (print) { diff --git a/lib/internal/process/per_thread.js b/lib/internal/process/per_thread.js index d3f9ff479cdeb9..22362e420b28b2 100644 --- a/lib/internal/process/per_thread.js +++ b/lib/internal/process/per_thread.js @@ -49,10 +49,6 @@ const { } = require('internal/validators'); const constants = internalBinding('constants').os.signals; -const { - handleProcessExit, -} = require('internal/modules/esm/handle_process_exit'); - const kInternal = Symbol('internal properties'); function assert(x, msg) { @@ -182,6 +178,9 @@ function wrapProcessMethods(binding) { memoryUsage.rss = rss; function exit(code) { + const { + handleProcessExit, + } = require('internal/modules/esm/handle_process_exit'); process.off('exit', handleProcessExit); if (code || code === 0) diff --git a/lib/internal/process/pre_execution.js b/lib/internal/process/pre_execution.js index b4a24bbffb6c43..4795be82e74b6c 100644 --- a/lib/internal/process/pre_execution.js +++ b/lib/internal/process/pre_execution.js @@ -4,9 +4,7 @@ const { NumberParseInt, ObjectDefineProperties, ObjectDefineProperty, - ObjectGetOwnPropertyDescriptor, SafeMap, - SafeWeakMap, StringPrototypeStartsWith, Symbol, SymbolDispose, @@ -16,13 +14,14 @@ const { const { getOptionValue, - getEmbedderOptions, refreshOptions, } = require('internal/options'); const { reconnectZeroFillToggle } = require('internal/buffer'); const { defineOperation, exposeInterface, + exposeLazyInterfaces, + defineReplaceableLazyAttribute, setupCoverageHooks, } = require('internal/util'); @@ -30,14 +29,15 @@ const { ERR_MANIFEST_ASSERT_INTEGRITY, } = require('internal/errors').codes; const assert = require('internal/assert'); - const { - addSerializeCallback, - isBuildingSnapshot, -} = require('v8').startupSnapshot; + namespace: { + addSerializeCallback, + isBuildingSnapshot, + }, +} = require('internal/v8/startup_snapshot'); function prepareMainThreadExecution(expandArgv1 = false, initializeModules = true) { - prepareExecution({ + return prepareExecution({ expandArgv1, initializeModules, isMainThread: true, @@ -58,8 +58,8 @@ function prepareExecution(options) { refreshRuntimeOptions(); reconnectZeroFillToggle(); - // Patch the process object with legacy properties and normalizations - patchProcessObject(expandArgv1); + // Patch the process object and get the resolved main entry point. + const mainEntry = patchProcessObject(expandArgv1); setupTraceCategoryState(); setupPerfHooks(); setupInspectorHooks(); @@ -73,6 +73,7 @@ function prepareExecution(options) { initializeReport(); initializeSourceMapsHandlers(); initializeDeprecations(); + require('internal/dns/utils').initializeDns(); setupSymbolDisposePolyfill(); @@ -112,21 +113,44 @@ function prepareExecution(options) { if (initializeModules) { setupUserModules(); } + + return mainEntry; } function setupSymbolDisposePolyfill() { // TODO(MoLow): Remove this polyfill once Symbol.dispose and Symbol.asyncDispose are available in V8. // eslint-disable-next-line node-core/prefer-primordials - Symbol.dispose ??= SymbolDispose; + if (typeof Symbol.dispose !== 'symbol') { + ObjectDefineProperty(Symbol, 'dispose', { + __proto__: null, + configurable: false, + enumerable: false, + value: SymbolDispose, + writable: false, + }); + } + // eslint-disable-next-line node-core/prefer-primordials - Symbol.asyncDispose ??= SymbolAsyncDispose; + if (typeof Symbol.asyncDispose !== 'symbol') { + ObjectDefineProperty(Symbol, 'asyncDispose', { + __proto__: null, + configurable: false, + enumerable: false, + value: SymbolAsyncDispose, + writable: false, + }); + } } -function setupUserModules() { +function setupUserModules(isLoaderWorker = false) { initializeCJSLoader(); - initializeESMLoader(); + initializeESMLoader(isLoaderWorker); const CJSLoader = require('internal/modules/cjs/loader'); assert(!CJSLoader.hasLoadedAnyUserCJSModule); + // Loader workers are responsible for doing this themselves. + if (isLoaderWorker) { + return; + } loadPreloadModules(); // Need to be done after --require setup. initializeFrozenIntrinsics(); @@ -136,12 +160,20 @@ function refreshRuntimeOptions() { refreshOptions(); } +/** + * Patch the process object with legacy properties and normalizations. + * Replace `process.argv[0]` with `process.execPath`, preserving the original `argv[0]` value as `process.argv0`. + * Replace `process.argv[1]` with the resolved absolute file path of the entry point, if found. + * @param {boolean} expandArgv1 - Whether to replace `process.argv[1]` with the resolved absolute file path of + * the main entry point. + */ function patchProcessObject(expandArgv1) { const binding = internalBinding('process_methods'); binding.patchProcessObject(process); require('internal/process/per_thread').refreshHrtimeBuffer(); + // Since we replace process.argv[0] below, preserve the original value in case the user needs it. ObjectDefineProperty(process, 'argv0', { __proto__: null, enumerable: true, @@ -154,12 +186,17 @@ function patchProcessObject(expandArgv1) { process._exiting = false; process.argv[0] = process.execPath; + /** @type {string} */ + let mainEntry; + // If requested, update process.argv[1] to replace whatever the user provided with the resolved absolute file path of + // the entry point. if (expandArgv1 && process.argv[1] && !StringPrototypeStartsWith(process.argv[1], '-')) { // Expand process.argv[1] into a full path. const path = require('path'); try { - process.argv[1] = path.resolve(process.argv[1]); + mainEntry = path.resolve(process.argv[1]); + process.argv[1] = mainEntry; } catch { // Continue regardless of error. } @@ -186,6 +223,8 @@ function patchProcessObject(expandArgv1) { addReadOnlyProcessAlias('traceDeprecation', '--trace-deprecation'); addReadOnlyProcessAlias('_breakFirstLine', '--inspect-brk', false); addReadOnlyProcessAlias('_breakNodeFirstLine', '--inspect-brk-node', false); + + return mainEntry; } function addReadOnlyProcessAlias(name, option, enumerable = true) { @@ -265,8 +304,9 @@ function setupFetch() { }); // The WebAssembly Web API: https://webassembly.github.io/spec/web-api - const { wasmStreamingCallback } = require('internal/wasm_web_api'); - internalBinding('wasm_web_api').setImplementation(wasmStreamingCallback); + internalBinding('wasm_web_api').setImplementation((streamState, source) => { + require('internal/wasm_web_api').wasmStreamingCallback(streamState, source); + }); } // TODO(aduh95): move this to internal/bootstrap/browser when the CLI flag is @@ -277,19 +317,14 @@ function setupWebCrypto() { return; } - let webcrypto; - ObjectDefineProperty(globalThis, 'crypto', - { __proto__: null, ...ObjectGetOwnPropertyDescriptor({ - get crypto() { - webcrypto ??= require('internal/crypto/webcrypto'); - return webcrypto.crypto; - }, - }, 'crypto') }); if (internalBinding('config').hasOpenSSL) { - webcrypto ??= require('internal/crypto/webcrypto'); - exposeInterface(globalThis, 'Crypto', webcrypto.Crypto); - exposeInterface(globalThis, 'CryptoKey', webcrypto.CryptoKey); - exposeInterface(globalThis, 'SubtleCrypto', webcrypto.SubtleCrypto); + defineReplaceableLazyAttribute( + globalThis, 'internal/crypto/webcrypto', ['crypto'], false, + ); + exposeLazyInterfaces( + globalThis, 'internal/crypto/webcrypto', + ['Crypto', 'CryptoKey', 'SubtleCrypto'], + ); } } @@ -328,12 +363,12 @@ function setupStacktracePrinterOnSigint() { } function initializeReport() { - const { report } = require('internal/process/report'); ObjectDefineProperty(process, 'report', { __proto__: null, enumerable: true, configurable: true, get() { + const { report } = require('internal/process/report'); return report; }, }); @@ -342,15 +377,16 @@ function initializeReport() { function setupDebugEnv() { require('internal/util/debuglog').initializeDebugEnv(process.env.NODE_DEBUG); if (getOptionValue('--expose-internals')) { - require('internal/bootstrap/loaders').BuiltinModule.exposeInternals(); + require('internal/bootstrap/realm').BuiltinModule.exposeInternals(); } } // This has to be called after initializeReport() is called function initializeReportSignalHandlers() { - const { addSignalHandler } = require('internal/process/report'); - - addSignalHandler(); + if (getOptionValue('--report-on-signal')) { + const { addSignalHandler } = require('internal/process/report'); + addSignalHandler(); + } } function initializeHeapSnapshotSignalHandlers() { @@ -383,7 +419,6 @@ function setupTraceCategoryState() { } function setupPerfHooks() { - require('internal/perf/performance').refreshTimeOrigin(); require('internal/perf/utils').refreshTimeOrigin(); } @@ -504,7 +539,7 @@ function readPolicyFromDisk() { // no bare specifiers for now let manifestURL; if (require('path').isAbsolute(experimentalPolicy)) { - manifestURL = new URL(`file://${experimentalPolicy}`); + manifestURL = pathToFileURL(experimentalPolicy); } else { const cwdURL = pathToFileURL(process.cwd()); cwdURL.pathname += '/'; @@ -545,30 +580,13 @@ function readPolicyFromDisk() { } function initializeCJSLoader() { - const CJSLoader = require('internal/modules/cjs/loader'); - if (!getEmbedderOptions().noGlobalSearchPaths) { - CJSLoader.Module._initPaths(); - } - // TODO(joyeecheung): deprecate this in favor of a proper hook? - CJSLoader.Module.runMain = - require('internal/modules/run_main').executeUserEntryPoint; + const { initializeCJS } = require('internal/modules/cjs/loader'); + initializeCJS(); } -function initializeESMLoader() { - // Create this WeakMap in js-land because V8 has no C++ API for WeakMap. - internalBinding('module_wrap').callbackMap = new SafeWeakMap(); - - if (getEmbedderOptions().shouldNotRegisterESMLoader) return; - - const { - setImportModuleDynamicallyCallback, - setInitializeImportMetaObjectCallback, - } = internalBinding('module_wrap'); - const esm = require('internal/process/esm_loader'); - // Setup per-isolate callbacks that locate data or callbacks that we keep - // track of for different ESM modules. - setInitializeImportMetaObjectCallback(esm.initializeImportMetaObject); - setImportModuleDynamicallyCallback(esm.importModuleDynamicallyCallback); +function initializeESMLoader(isLoaderWorker) { + const { initializeESM } = require('internal/modules/esm/utils'); + initializeESM(isLoaderWorker); // Patch the vm module when --experimental-vm-modules is on. // Please update the comments in vm.js when this block changes. @@ -584,11 +602,10 @@ function initializeESMLoader() { } function initializeSourceMapsHandlers() { - const { setSourceMapsEnabled, getSourceMapsEnabled } = - require('internal/source_map/source_map_cache'); - process.setSourceMapsEnabled = setSourceMapsEnabled; - // Initialize the environment flag of source maps. - getSourceMapsEnabled(); + const { + setSourceMapsEnabled, + } = require('internal/source_map/source_map_cache'); + setSourceMapsEnabled(getOptionValue('--enable-source-maps')); } function initializeFrozenIntrinsics() { @@ -621,4 +638,6 @@ module.exports = { prepareMainThreadExecution, prepareWorkerThreadExecution, markBootstrapComplete, + loadPreloadModules, + initializeFrozenIntrinsics, }; diff --git a/lib/internal/process/warning.js b/lib/internal/process/warning.js index 9c2a98af058957..3ce00004dab476 100644 --- a/lib/internal/process/warning.js +++ b/lib/internal/process/warning.js @@ -166,8 +166,8 @@ function emitWarning(warning, type, code, ctor) { process.nextTick(doEmitWarning, warning); } -function emitWarningSync(warning) { - process.emit('warning', createWarningObject(warning)); +function emitWarningSync(warning, type, code, ctor) { + process.emit('warning', createWarningObject(warning, type, code, ctor)); } function createWarningObject(warning, type, code, ctor, detail) { diff --git a/lib/internal/readline/utils.js b/lib/internal/readline/utils.js index a546516d76b66c..124a5382a0ddae 100644 --- a/lib/internal/readline/utils.js +++ b/lib/internal/readline/utils.js @@ -148,8 +148,10 @@ function* emitKeys(stream) { * * - `;5` part is optional, e.g. it could be `\x1b[24~` * - first part can contain one or two digits + * - there is also special case when there can be 3 digits + * but without modifier. They are the case of paste bracket mode * - * So the generic regexp is like /^\d\d?(;\d)?[~^$]$/ + * So the generic regexp is like /^(?:\d\d?(;\d)?[~^$]|\d{3}~)$/ * * * 2. `\x1b[1;5H` should be parsed as { code: '[H', modifier: 5 } @@ -170,6 +172,10 @@ function* emitKeys(stream) { if (ch >= '0' && ch <= '9') { s += (ch = yield); + + if (ch >= '0' && ch <= '9') { + s += (ch = yield); + } } } @@ -189,9 +195,13 @@ function* emitKeys(stream) { const cmd = StringPrototypeSlice(s, cmdStart); let match; - if ((match = RegExpPrototypeExec(/^(\d\d?)(;(\d))?([~^$])$/, cmd))) { - code += match[1] + match[4]; - modifier = (match[3] || 1) - 1; + if ((match = RegExpPrototypeExec(/^(?:(\d\d?)(?:;(\d))?([~^$])|(\d{3}~))$/, cmd))) { + if (match[4]) { + code += match[4]; + } else { + code += match[1] + match[3]; + modifier = (match[2] || 1) - 1; + } } else if ( (match = RegExpPrototypeExec(/^((\d;)?(\d))?([A-Za-z])$/, cmd)) ) { @@ -228,6 +238,10 @@ function* emitKeys(stream) { case '[13~': key.name = 'f3'; break; case '[14~': key.name = 'f4'; break; + /* paste bracket mode */ + case '[200~': key.name = 'paste-start'; break; + case '[201~': key.name = 'paste-end'; break; + /* from Cygwin and used in libuv */ case '[[A': key.name = 'f1'; break; case '[[B': key.name = 'f2'; break; diff --git a/lib/internal/source_map/source_map_cache.js b/lib/internal/source_map/source_map_cache.js index f51f97d4420363..560b51eb6d658b 100644 --- a/lib/internal/source_map/source_map_cache.js +++ b/lib/internal/source_map/source_map_cache.js @@ -23,19 +23,22 @@ const { Buffer } = require('buffer'); let debug = require('internal/util/debuglog').debuglog('source_map', (fn) => { debug = fn; }); -const fs = require('fs'); -const { getOptionValue } = require('internal/options'); -const { IterableWeakMap } = require('internal/util/iterable_weak_map'); -const { - normalizeReferrerURL, -} = require('internal/modules/cjs/helpers'); + const { validateBoolean } = require('internal/validators'); -const { setMaybeCacheGeneratedSourceMap } = internalBinding('errors'); +const { + setSourceMapsEnabled: setSourceMapsNative, + setPrepareStackTraceCallback, +} = internalBinding('errors'); +const { getLazy } = require('internal/util'); // Since the CJS module cache is mutable, which leads to memory leaks when // modules are deleted, we use a WeakMap so that the source map cache will // be purged automatically: -const cjsSourceMapCache = new IterableWeakMap(); +const getCjsSourceMapCache = getLazy(() => { + const { IterableWeakMap } = require('internal/util/iterable_weak_map'); + return new IterableWeakMap(); +}); + // The esm cache is not mutable, so we can use a Map without memory concerns: const esmSourceMapCache = new SafeMap(); // The generated sources is not mutable, so we can use a Map without memory concerns: @@ -45,24 +48,19 @@ const kSourceMappingURLMagicComment = /\/[*/]#\s+sourceMappingURL=(?[^\s]+)/g; const { fileURLToPath, pathToFileURL, URL } = require('internal/url'); + let SourceMap; -let sourceMapsEnabled; +// This is configured with --enable-source-maps during pre-execution. +let sourceMapsEnabled = false; function getSourceMapsEnabled() { - if (sourceMapsEnabled === undefined) { - setSourceMapsEnabled(getOptionValue('--enable-source-maps')); - } return sourceMapsEnabled; } function setSourceMapsEnabled(val) { validateBoolean(val, 'val'); - const { - setSourceMapsEnabled, - setPrepareStackTraceCallback, - } = internalBinding('errors'); - setSourceMapsEnabled(val); + setSourceMapsNative(val); if (val) { const { prepareStackTrace, @@ -115,6 +113,7 @@ function maybeCacheSourceMap(filename, content, cjsModuleInstance, isGeneratedSo const sourceMapsEnabled = getSourceMapsEnabled(); if (!(process.env.NODE_V8_COVERAGE || sourceMapsEnabled)) return; try { + const { normalizeReferrerURL } = require('internal/modules/helpers'); filename = normalizeReferrerURL(filename); } catch (err) { // This is most likely an invalid filename in sourceURL of [eval]-wrapper. @@ -138,7 +137,7 @@ function maybeCacheSourceMap(filename, content, cjsModuleInstance, isGeneratedSo const data = dataFromUrl(filename, sourceMapURL); const url = data ? null : sourceMapURL; if (cjsModuleInstance) { - cjsSourceMapCache.set(cjsModuleInstance, { + getCjsSourceMapCache().set(cjsModuleInstance, { filename, lineLengths: lineLengths(content), data, @@ -188,7 +187,6 @@ function maybeCacheGeneratedSourceMap(content) { debug(err); } } -setMaybeCacheGeneratedSourceMap(maybeCacheGeneratedSourceMap); function dataFromUrl(sourceURL, sourceMappingURL) { try { @@ -222,6 +220,7 @@ function lineLengths(content) { function sourceMapFromFile(mapURL) { try { + const fs = require('fs'); const content = fs.readFileSync(fileURLToPath(mapURL), 'utf8'); const data = JSONParse(content); return sourcesToAbsolute(mapURL, data); @@ -291,7 +290,7 @@ function sourceMapCacheToObject() { } function appendCJSCache(obj) { - for (const value of cjsSourceMapCache) { + for (const value of getCjsSourceMapCache()) { obj[ObjectGetValueSafe(value, 'filename')] = { lineLengths: ObjectGetValueSafe(value, 'lineLengths'), data: ObjectGetValueSafe(value, 'data'), @@ -309,7 +308,7 @@ function findSourceMap(sourceURL) { } let sourceMap = esmSourceMapCache.get(sourceURL) ?? generatedSourceMapCache.get(sourceURL); if (sourceMap === undefined) { - for (const value of cjsSourceMapCache) { + for (const value of getCjsSourceMapCache()) { const filename = ObjectGetValueSafe(value, 'filename'); const cachedSourceURL = ObjectGetValueSafe(value, 'sourceURL'); if (sourceURL === filename || sourceURL === cachedSourceURL) { @@ -330,5 +329,6 @@ module.exports = { getSourceMapsEnabled, setSourceMapsEnabled, maybeCacheSourceMap, + maybeCacheGeneratedSourceMap, sourceMapCacheToObject, }; diff --git a/lib/internal/streams/operators.js b/lib/internal/streams/operators.js index 47208136e0916d..b8dde2a5b9ee8c 100644 --- a/lib/internal/streams/operators.js +++ b/lib/internal/streams/operators.js @@ -33,6 +33,7 @@ const { NumberIsNaN, Promise, PromiseReject, + PromiseResolve, PromisePrototypeThen, Symbol, } = primordials; @@ -82,7 +83,15 @@ function map(fn, options) { concurrency = MathFloor(options.concurrency); } - validateInteger(concurrency, 'concurrency', 1); + let highWaterMark = concurrency - 1; + if (options?.highWaterMark != null) { + highWaterMark = MathFloor(options.highWaterMark); + } + + validateInteger(concurrency, 'options.concurrency', 1); + validateInteger(highWaterMark, 'options.highWaterMark', 0); + + highWaterMark += concurrency; return async function* map() { const signal = AbortSignal.any([options?.signal].filter(Boolean)); @@ -93,9 +102,28 @@ function map(fn, options) { let next; let resume; let done = false; + let cnt = 0; - function onDone() { + function onCatch() { done = true; + afterItemProcessed(); + } + + function afterItemProcessed() { + cnt -= 1; + maybeResume(); + } + + function maybeResume() { + if ( + resume && + !done && + cnt < concurrency && + queue.length < highWaterMark + ) { + resume(); + resume = null; + } } async function pump() { @@ -111,17 +139,19 @@ function map(fn, options) { try { val = fn(val, signalOpt); + + if (val === kEmpty) { + continue; + } + + val = PromiseResolve(val); } catch (err) { val = PromiseReject(err); } - if (val === kEmpty) { - continue; - } + cnt += 1; - if (typeof val?.catch === 'function') { - val.catch(onDone); - } + PromisePrototypeThen(val, afterItemProcessed, onCatch); queue.push(val); if (next) { @@ -129,7 +159,7 @@ function map(fn, options) { next = null; } - if (!done && queue.length && queue.length >= concurrency) { + if (!done && (queue.length >= highWaterMark || cnt >= concurrency)) { await new Promise((resolve) => { resume = resolve; }); @@ -138,7 +168,7 @@ function map(fn, options) { queue.push(kEof); } catch (err) { const val = PromiseReject(err); - PromisePrototypeThen(val, undefined, onDone); + PromisePrototypeThen(val, afterItemProcessed, onCatch); queue.push(val); } finally { done = true; @@ -169,10 +199,7 @@ function map(fn, options) { } queue.shift(); - if (resume) { - resume(); - resume = null; - } + maybeResume(); } await new Promise((resolve) => { diff --git a/lib/internal/streams/readable.js b/lib/internal/streams/readable.js index a32dbaee167fcc..092f8a750caa66 100644 --- a/lib/internal/streams/readable.js +++ b/lib/internal/streams/readable.js @@ -82,6 +82,75 @@ const nop = () => {}; const { errorOrDestroy } = destroyImpl; +const kObjectMode = 1 << 0; +const kEnded = 1 << 1; +const kEndEmitted = 1 << 2; +const kReading = 1 << 3; +const kConstructed = 1 << 4; +const kSync = 1 << 5; +const kNeedReadable = 1 << 6; +const kEmittedReadable = 1 << 7; +const kReadableListening = 1 << 8; +const kResumeScheduled = 1 << 9; +const kErrorEmitted = 1 << 10; +const kEmitClose = 1 << 11; +const kAutoDestroy = 1 << 12; +const kDestroyed = 1 << 13; +const kClosed = 1 << 14; +const kCloseEmitted = 1 << 15; +const kMultiAwaitDrain = 1 << 16; +const kReadingMore = 1 << 17; +const kDataEmitted = 1 << 18; + +// TODO(benjamingr) it is likely slower to do it this way than with free functions +function makeBitMapDescriptor(bit) { + return { + enumerable: false, + get() { return (this.state & bit) !== 0; }, + set(value) { + if (value) this.state |= bit; + else this.state &= ~bit; + }, + }; +} +ObjectDefineProperties(ReadableState.prototype, { + objectMode: makeBitMapDescriptor(kObjectMode), + ended: makeBitMapDescriptor(kEnded), + endEmitted: makeBitMapDescriptor(kEndEmitted), + reading: makeBitMapDescriptor(kReading), + // Stream is still being constructed and cannot be + // destroyed until construction finished or failed. + // Async construction is opt in, therefore we start as + // constructed. + constructed: makeBitMapDescriptor(kConstructed), + // A flag to be able to tell if the event 'readable'/'data' is emitted + // immediately, or on a later tick. We set this to true at first, because + // any actions that shouldn't happen until "later" should generally also + // not happen before the first read call. + sync: makeBitMapDescriptor(kSync), + // Whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + needReadable: makeBitMapDescriptor(kNeedReadable), + emittedReadable: makeBitMapDescriptor(kEmittedReadable), + readableListening: makeBitMapDescriptor(kReadableListening), + resumeScheduled: makeBitMapDescriptor(kResumeScheduled), + // True if the error was already emitted and should not be thrown again. + errorEmitted: makeBitMapDescriptor(kErrorEmitted), + emitClose: makeBitMapDescriptor(kEmitClose), + autoDestroy: makeBitMapDescriptor(kAutoDestroy), + // Has it been destroyed. + destroyed: makeBitMapDescriptor(kDestroyed), + // Indicates whether the stream has finished destroying. + closed: makeBitMapDescriptor(kClosed), + // True if close has been emitted or would have been emitted + // depending on emitClose. + closeEmitted: makeBitMapDescriptor(kCloseEmitted), + multiAwaitDrain: makeBitMapDescriptor(kMultiAwaitDrain), + // If true, a maybeReadMore has been scheduled. + readingMore: makeBitMapDescriptor(kReadingMore), + dataEmitted: makeBitMapDescriptor(kDataEmitted), +}); + function ReadableState(options, stream, isDuplex) { // Duplex streams are both readable and writable, but share // the same options object. @@ -91,13 +160,15 @@ function ReadableState(options, stream, isDuplex) { if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof Stream.Duplex; + // Bit map field to store ReadableState more effciently with 1 bit per field + // instead of a V8 slot per field. + this.state = kEmitClose | kAutoDestroy | kConstructed | kSync; // Object stream flag. Used to make read(n) ignore n and to // make all the buffer merging and length checks go away. - this.objectMode = !!(options && options.objectMode); + if (options && options.objectMode) this.state |= kObjectMode; - if (isDuplex) - this.objectMode = this.objectMode || - !!(options && options.readableObjectMode); + if (isDuplex && options && options.readableObjectMode) + this.state |= kObjectMode; // The point at which it stops calling _read() to fill the buffer // Note: 0 is a valid value, means "don't call _read preemptively ever" @@ -112,41 +183,15 @@ function ReadableState(options, stream, isDuplex) { this.length = 0; this.pipes = []; this.flowing = null; - this.ended = false; - this.endEmitted = false; - this.reading = false; - - // Stream is still being constructed and cannot be - // destroyed until construction finished or failed. - // Async construction is opt in, therefore we start as - // constructed. - this.constructed = true; - // A flag to be able to tell if the event 'readable'/'data' is emitted - // immediately, or on a later tick. We set this to true at first, because - // any actions that shouldn't happen until "later" should generally also - // not happen before the first read call. - this.sync = true; - - // Whenever we return null, then we set a flag to say - // that we're awaiting a 'readable' event emission. - this.needReadable = false; - this.emittedReadable = false; - this.readableListening = false; - this.resumeScheduled = false; this[kPaused] = null; - // True if the error was already emitted and should not be thrown again. - this.errorEmitted = false; - // Should close be emitted on destroy. Defaults to true. - this.emitClose = !options || options.emitClose !== false; + if (options && options.emitClose === false) this.state &= ~kEmitClose; // Should .destroy() be called after 'end' (and potentially 'finish'). - this.autoDestroy = !options || options.autoDestroy !== false; + if (options && options.autoDestroy === false) this.state &= ~kAutoDestroy; - // Has it been destroyed. - this.destroyed = false; // Indicates whether the stream has errored. When true no further // _read calls, 'data' or 'readable' events should occur. This is needed @@ -154,12 +199,6 @@ function ReadableState(options, stream, isDuplex) { // stream has failed. this.errored = null; - // Indicates whether the stream has finished destroying. - this.closed = false; - - // True if close has been emitted or would have been emitted - // depending on emitClose. - this.closeEmitted = false; // Crypto is kind of old and crusty. Historically, its default string // encoding is 'binary' so we have to make this configurable. @@ -169,12 +208,6 @@ function ReadableState(options, stream, isDuplex) { // Ref the piped dest which we need a drain event on it // type: null | Writable | Set. this.awaitDrainWriters = null; - this.multiAwaitDrain = false; - - // If true, a maybeReadMore has been scheduled. - this.readingMore = false; - - this.dataEmitted = false; this.decoder = null; this.encoding = null; @@ -255,7 +288,7 @@ function readableAddChunk(stream, chunk, encoding, addToFront) { const state = stream._readableState; let err; - if (!state.objectMode) { + if ((state.state & kObjectMode) === 0) { if (typeof chunk === 'string') { encoding = encoding || state.defaultEncoding; if (state.encoding !== encoding) { @@ -282,11 +315,11 @@ function readableAddChunk(stream, chunk, encoding, addToFront) { if (err) { errorOrDestroy(stream, err); } else if (chunk === null) { - state.reading = false; + state.state &= ~kReading; onEofChunk(stream, state); - } else if (state.objectMode || (chunk && chunk.length > 0)) { + } else if (((state.state & kObjectMode) !== 0) || (chunk && chunk.length > 0)) { if (addToFront) { - if (state.endEmitted) + if ((state.state & kEndEmitted) !== 0) errorOrDestroy(stream, new ERR_STREAM_UNSHIFT_AFTER_END_EVENT()); else if (state.destroyed || state.errored) return false; @@ -297,7 +330,7 @@ function readableAddChunk(stream, chunk, encoding, addToFront) { } else if (state.destroyed || state.errored) { return false; } else { - state.reading = false; + state.state &= ~kReading; if (state.decoder && !encoding) { chunk = state.decoder.write(chunk); if (state.objectMode || chunk.length !== 0) @@ -309,7 +342,7 @@ function readableAddChunk(stream, chunk, encoding, addToFront) { } } } else if (!addToFront) { - state.reading = false; + state.state &= ~kReading; maybeReadMore(stream, state); } @@ -325,7 +358,7 @@ function addChunk(stream, state, chunk, addToFront) { stream.listenerCount('data') > 0) { // Use the guard to avoid creating `Set()` repeatedly // when we have multiple pipes. - if (state.multiAwaitDrain) { + if ((state.state & kMultiAwaitDrain) !== 0) { state.awaitDrainWriters.clear(); } else { state.awaitDrainWriters = null; @@ -341,7 +374,7 @@ function addChunk(stream, state, chunk, addToFront) { else state.buffer.push(chunk); - if (state.needReadable) + if ((state.state & kNeedReadable) !== 0) emitReadable(stream); } maybeReadMore(stream, state); @@ -396,7 +429,7 @@ function computeNewHighWaterMark(n) { function howMuchToRead(n, state) { if (n <= 0 || (state.length === 0 && state.ended)) return 0; - if (state.objectMode) + if ((state.state & kObjectMode) !== 0) return 1; if (NumberIsNaN(n)) { // Only flow one buffer at a time. @@ -427,7 +460,7 @@ Readable.prototype.read = function(n) { state.highWaterMark = computeNewHighWaterMark(n); if (n !== 0) - state.emittedReadable = false; + state.state &= ~kEmittedReadable; // If we're doing read(0) to trigger a readable event, but we // already have a bunch of data in the buffer, then just trigger @@ -478,7 +511,7 @@ Readable.prototype.read = function(n) { // 3. Actually pull the requested chunks out of the buffer and return. // if we need a readable event, then we need to do some reading. - let doRead = state.needReadable; + let doRead = (state.state & kNeedReadable) !== 0; debug('need readable', doRead); // If we currently have less than the highWaterMark, then also read some. @@ -496,11 +529,10 @@ Readable.prototype.read = function(n) { debug('reading, ended or constructing', doRead); } else if (doRead) { debug('do read'); - state.reading = true; - state.sync = true; + state.state |= kReading | kSync; // If the length is currently zero, then we *need* a readable event. if (state.length === 0) - state.needReadable = true; + state.state |= kNeedReadable; // Call internal read method try { @@ -508,8 +540,8 @@ Readable.prototype.read = function(n) { } catch (err) { errorOrDestroy(this, err); } + state.state &= ~kSync; - state.sync = false; // If _read pushed data synchronously, then `reading` will be false, // and we need to re-evaluate how much data we can return to the user. if (!state.reading) diff --git a/lib/internal/test_runner/coverage.js b/lib/internal/test_runner/coverage.js index a20055fa91b601..e85913c26db54f 100644 --- a/lib/internal/test_runner/coverage.js +++ b/lib/internal/test_runner/coverage.js @@ -250,7 +250,7 @@ class TestCoverage { let dir; try { - mkdirSync(this.originalCoverageDirectory, { recursive: true }); + mkdirSync(this.originalCoverageDirectory, { __proto__: null, recursive: true }); dir = opendirSync(this.coverageDirectory); for (let entry; (entry = dir.readSync()) !== null;) { @@ -313,7 +313,7 @@ function mapRangeToLines(range, lines) { mid = MathFloor((start + end) / 2); let line = lines[mid]; - if (startOffset >= line.startOffset && startOffset <= line.endOffset) { + if (startOffset >= line?.startOffset && startOffset <= line?.endOffset) { while (endOffset > line?.startOffset) { // If the range is not covered, and the range covers the entire line, // then mark that line as not covered. @@ -333,7 +333,7 @@ function mapRangeToLines(range, lines) { } break; - } else if (startOffset >= line.endOffset) { + } else if (startOffset >= line?.endOffset) { start = mid + 1; } else { end = mid - 1; @@ -508,4 +508,4 @@ function doesRangeContainOtherRange(range, otherRange) { range.endOffset >= otherRange.endOffset; } -module.exports = { setupCoverage }; +module.exports = { setupCoverage, TestCoverage }; diff --git a/lib/internal/test_runner/harness.js b/lib/internal/test_runner/harness.js index f29d5c95cc6084..6d11583c42b39c 100644 --- a/lib/internal/test_runner/harness.js +++ b/lib/internal/test_runner/harness.js @@ -5,6 +5,7 @@ const { PromiseResolve, SafeMap, } = primordials; +const { getCallerLocation } = internalBinding('util'); const { createHook, executionAsyncId, @@ -18,12 +19,15 @@ const { kEmptyObject } = require('internal/util'); const { kCancelledByParent, Test, Suite } = require('internal/test_runner/test'); const { parseCommandLine, + reporterScope, setupTestReporters, } = require('internal/test_runner/utils'); const { bigint: hrtime } = process.hrtime; const testResources = new SafeMap(); +testResources.set(reporterScope.asyncId(), reporterScope); + function createTestTree(options = kEmptyObject) { return setup(new Test({ __proto__: null, ...options, name: '' })); } @@ -37,9 +41,14 @@ function createProcessEventHandler(eventName, rootTest) { throw err; } - // Check if this error is coming from a test. If it is, fail the test. const test = testResources.get(executionAsyncId()); + // Check if this error is coming from a reporter. If it is, throw it. + if (test === reporterScope) { + throw err; + } + + // Check if this error is coming from a test. If it is, fail the test. if (!test || test.finished) { // If the test is already finished or the resource that created the error // is not mapped to a Test, report this as a top level diagnostic. @@ -114,6 +123,7 @@ function setup(root) { const globalOptions = parseCommandLine(); const hook = createHook({ + __proto__: null, init(asyncId, type, triggerAsyncId, resource) { if (resource instanceof Test) { testResources.set(asyncId, resource); @@ -138,8 +148,8 @@ function setup(root) { const rejectionHandler = createProcessEventHandler('unhandledRejection', root); const coverage = configureCoverage(root, globalOptions); - const exitHandler = async () => { - await root.run(new ERR_TEST_FAILURE( + const exitHandler = () => { + root.postRun(new ERR_TEST_FAILURE( 'Promise resolution is still pending but the event loop has already resolved', kCancelledByParent)); @@ -148,8 +158,8 @@ function setup(root) { process.removeListener('uncaughtException', exceptionHandler); }; - const terminationHandler = async () => { - await exitHandler(); + const terminationHandler = () => { + exitHandler(); process.exit(); }; @@ -188,8 +198,10 @@ let reportersSetup; function getGlobalRoot() { if (!globalRoot) { globalRoot = createTestTree(); - globalRoot.reporter.once('test:fail', () => { - process.exitCode = 1; + globalRoot.reporter.on('test:fail', (data) => { + if (data.todo === undefined || data.todo === false) { + process.exitCode = 1; + } }); reportersSetup = setupTestReporters(globalRoot); } @@ -212,9 +224,24 @@ function runInParentContext(Factory) { return PromiseResolve(); } - const test = (name, options, fn) => run(name, options, fn); + const test = (name, options, fn) => { + const overrides = { + __proto__: null, + loc: getCallerLocation(), + }; + + return run(name, options, fn, overrides); + }; ArrayPrototypeForEach(['skip', 'todo', 'only'], (keyword) => { - test[keyword] = (name, options, fn) => run(name, options, fn, { [keyword]: true }); + test[keyword] = (name, options, fn) => { + const overrides = { + __proto__: null, + [keyword]: true, + loc: getCallerLocation(), + }; + + return run(name, options, fn, overrides); + }; }); return test; } @@ -222,7 +249,13 @@ function runInParentContext(Factory) { function hook(hook) { return (fn, options) => { const parent = testResources.get(executionAsyncId()) || getGlobalRoot(); - parent.createHook(hook, fn, options); + parent.createHook(hook, fn, { + __proto__: null, + ...options, + parent, + hookType: hook, + loc: getCallerLocation(), + }); }; } diff --git a/lib/internal/test_runner/mock.js b/lib/internal/test_runner/mock.js deleted file mode 100644 index aa3014a7bc40c6..00000000000000 --- a/lib/internal/test_runner/mock.js +++ /dev/null @@ -1,373 +0,0 @@ -'use strict'; -const { - ArrayPrototypePush, - ArrayPrototypeSlice, - Error, - FunctionPrototypeCall, - ObjectDefineProperty, - ObjectGetOwnPropertyDescriptor, - ObjectGetPrototypeOf, - Proxy, - ReflectApply, - ReflectConstruct, - ReflectGet, - SafeMap, -} = primordials; -const { - codes: { - ERR_INVALID_ARG_TYPE, - ERR_INVALID_ARG_VALUE, - }, -} = require('internal/errors'); -const { kEmptyObject } = require('internal/util'); -const { - validateBoolean, - validateFunction, - validateInteger, - validateObject, -} = require('internal/validators'); - -function kDefaultFunction() {} - -class MockFunctionContext { - #calls; - #mocks; - #implementation; - #restore; - #times; - - constructor(implementation, restore, times) { - this.#calls = []; - this.#mocks = new SafeMap(); - this.#implementation = implementation; - this.#restore = restore; - this.#times = times; - } - - get calls() { - return ArrayPrototypeSlice(this.#calls, 0); - } - - callCount() { - return this.#calls.length; - } - - mockImplementation(implementation) { - validateFunction(implementation, 'implementation'); - this.#implementation = implementation; - } - - mockImplementationOnce(implementation, onCall) { - validateFunction(implementation, 'implementation'); - const nextCall = this.#calls.length; - const call = onCall ?? nextCall; - validateInteger(call, 'onCall', nextCall); - this.#mocks.set(call, implementation); - } - - restore() { - const { descriptor, object, original, methodName } = this.#restore; - - if (typeof methodName === 'string') { - // This is an object method spy. - ObjectDefineProperty(object, methodName, descriptor); - } else { - // This is a bare function spy. There isn't much to do here but make - // the mock call the original function. - this.#implementation = original; - } - } - - resetCalls() { - this.#calls = []; - } - - trackCall(call) { - ArrayPrototypePush(this.#calls, call); - } - - nextImpl() { - const nextCall = this.#calls.length; - const mock = this.#mocks.get(nextCall); - const impl = mock ?? this.#implementation; - - if (nextCall + 1 === this.#times) { - this.restore(); - } - - this.#mocks.delete(nextCall); - return impl; - } -} - -const { nextImpl, restore, trackCall } = MockFunctionContext.prototype; -delete MockFunctionContext.prototype.trackCall; -delete MockFunctionContext.prototype.nextImpl; - -class MockTracker { - #mocks = []; - - fn( - original = function() {}, - implementation = original, - options = kEmptyObject, - ) { - if (original !== null && typeof original === 'object') { - options = original; - original = function() {}; - implementation = original; - } else if (implementation !== null && typeof implementation === 'object') { - options = implementation; - implementation = original; - } - - validateFunction(original, 'original'); - validateFunction(implementation, 'implementation'); - validateObject(options, 'options'); - const { times = Infinity } = options; - validateTimes(times, 'options.times'); - const ctx = new MockFunctionContext(implementation, { original }, times); - return this.#setupMock(ctx, original); - } - - method( - objectOrFunction, - methodName, - implementation = kDefaultFunction, - options = kEmptyObject, - ) { - validateStringOrSymbol(methodName, 'methodName'); - if (typeof objectOrFunction !== 'function') { - validateObject(objectOrFunction, 'object'); - } - - if (implementation !== null && typeof implementation === 'object') { - options = implementation; - implementation = kDefaultFunction; - } - - validateFunction(implementation, 'implementation'); - validateObject(options, 'options'); - - const { - getter = false, - setter = false, - times = Infinity, - } = options; - - validateBoolean(getter, 'options.getter'); - validateBoolean(setter, 'options.setter'); - validateTimes(times, 'options.times'); - - if (setter && getter) { - throw new ERR_INVALID_ARG_VALUE( - 'options.setter', setter, "cannot be used with 'options.getter'", - ); - } - const descriptor = findMethodOnPrototypeChain(objectOrFunction, methodName); - - let original; - - if (getter) { - original = descriptor?.get; - } else if (setter) { - original = descriptor?.set; - } else { - original = descriptor?.value; - } - - if (typeof original !== 'function') { - throw new ERR_INVALID_ARG_VALUE( - 'methodName', original, 'must be a method', - ); - } - - const restore = { descriptor, object: objectOrFunction, methodName }; - const impl = implementation === kDefaultFunction ? - original : implementation; - const ctx = new MockFunctionContext(impl, restore, times); - const mock = this.#setupMock(ctx, original); - const mockDescriptor = { - __proto__: null, - configurable: descriptor.configurable, - enumerable: descriptor.enumerable, - }; - - if (getter) { - mockDescriptor.get = mock; - mockDescriptor.set = descriptor.set; - } else if (setter) { - mockDescriptor.get = descriptor.get; - mockDescriptor.set = mock; - } else { - mockDescriptor.writable = descriptor.writable; - mockDescriptor.value = mock; - } - - ObjectDefineProperty(objectOrFunction, methodName, mockDescriptor); - - return mock; - } - - getter( - object, - methodName, - implementation = kDefaultFunction, - options = kEmptyObject, - ) { - if (implementation !== null && typeof implementation === 'object') { - options = implementation; - implementation = kDefaultFunction; - } else { - validateObject(options, 'options'); - } - - const { getter = true } = options; - - if (getter === false) { - throw new ERR_INVALID_ARG_VALUE( - 'options.getter', getter, 'cannot be false', - ); - } - - return this.method(object, methodName, implementation, { - ...options, - getter, - }); - } - - setter( - object, - methodName, - implementation = kDefaultFunction, - options = kEmptyObject, - ) { - if (implementation !== null && typeof implementation === 'object') { - options = implementation; - implementation = kDefaultFunction; - } else { - validateObject(options, 'options'); - } - - const { setter = true } = options; - - if (setter === false) { - throw new ERR_INVALID_ARG_VALUE( - 'options.setter', setter, 'cannot be false', - ); - } - - return this.method(object, methodName, implementation, { - ...options, - setter, - }); - } - - reset() { - this.restoreAll(); - this.#mocks = []; - } - - restoreAll() { - for (let i = 0; i < this.#mocks.length; i++) { - FunctionPrototypeCall(restore, this.#mocks[i]); - } - } - - #setupMock(ctx, fnToMatch) { - const mock = new Proxy(fnToMatch, { - __proto__: null, - apply(_fn, thisArg, argList) { - const fn = FunctionPrototypeCall(nextImpl, ctx); - let result; - let error; - - try { - result = ReflectApply(fn, thisArg, argList); - } catch (err) { - error = err; - throw err; - } finally { - FunctionPrototypeCall(trackCall, ctx, { - arguments: argList, - error, - result, - // eslint-disable-next-line no-restricted-syntax - stack: new Error(), - target: undefined, - this: thisArg, - }); - } - - return result; - }, - construct(target, argList, newTarget) { - const realTarget = FunctionPrototypeCall(nextImpl, ctx); - let result; - let error; - - try { - result = ReflectConstruct(realTarget, argList, newTarget); - } catch (err) { - error = err; - throw err; - } finally { - FunctionPrototypeCall(trackCall, ctx, { - arguments: argList, - error, - result, - // eslint-disable-next-line no-restricted-syntax - stack: new Error(), - target, - this: result, - }); - } - - return result; - }, - get(target, property, receiver) { - if (property === 'mock') { - return ctx; - } - - return ReflectGet(target, property, receiver); - }, - }); - - ArrayPrototypePush(this.#mocks, ctx); - return mock; - } -} - -function validateStringOrSymbol(value, name) { - if (typeof value !== 'string' && typeof value !== 'symbol') { - throw new ERR_INVALID_ARG_TYPE(name, ['string', 'symbol'], value); - } -} - -function validateTimes(value, name) { - if (value === Infinity) { - return; - } - - validateInteger(value, name, 1); -} - -function findMethodOnPrototypeChain(instance, methodName) { - let host = instance; - let descriptor; - - while (host !== null) { - descriptor = ObjectGetOwnPropertyDescriptor(host, methodName); - - if (descriptor) { - break; - } - - host = ObjectGetPrototypeOf(host); - } - - return descriptor; -} - -module.exports = { MockTracker }; diff --git a/lib/internal/test_runner/mock/mock.js b/lib/internal/test_runner/mock/mock.js new file mode 100644 index 00000000000000..838a530ddd4902 --- /dev/null +++ b/lib/internal/test_runner/mock/mock.js @@ -0,0 +1,469 @@ +'use strict'; +const { + ArrayPrototypePush, + ArrayPrototypeSlice, + Error, + FunctionPrototypeCall, + ObjectDefineProperty, + ObjectGetOwnPropertyDescriptor, + ObjectGetPrototypeOf, + Proxy, + ReflectApply, + ReflectConstruct, + ReflectGet, + SafeMap, +} = primordials; +const { + codes: { + ERR_INVALID_ARG_TYPE, + ERR_INVALID_ARG_VALUE, + }, +} = require('internal/errors'); +const { kEmptyObject } = require('internal/util'); +const { + validateBoolean, + validateFunction, + validateInteger, + validateObject, +} = require('internal/validators'); +const { MockTimers } = require('internal/test_runner/mock/mock_timers'); + +function kDefaultFunction() {} + +class MockFunctionContext { + #calls; + #mocks; + #implementation; + #restore; + #times; + + constructor(implementation, restore, times) { + this.#calls = []; + this.#mocks = new SafeMap(); + this.#implementation = implementation; + this.#restore = restore; + this.#times = times; + } + + /** + * Gets an array of recorded calls made to the mock function. + * @returns {Array} An array of recorded calls. + */ + get calls() { + return ArrayPrototypeSlice(this.#calls, 0); + } + + /** + * Retrieves the number of times the mock function has been called. + * @returns {number} The call count. + */ + callCount() { + return this.#calls.length; + } + + /** + * Sets a new implementation for the mock function. + * @param {Function} implementation - The new implementation for the mock function. + */ + mockImplementation(implementation) { + validateFunction(implementation, 'implementation'); + this.#implementation = implementation; + } + + /** + * Replaces the implementation of the function only once. + * @param {Function} implementation - The substitute function. + * @param {number} [onCall] - The call index to be replaced. + */ + mockImplementationOnce(implementation, onCall) { + validateFunction(implementation, 'implementation'); + const nextCall = this.#calls.length; + const call = onCall ?? nextCall; + validateInteger(call, 'onCall', nextCall); + this.#mocks.set(call, implementation); + } + + /** + * Restores the original function that was mocked. + */ + restore() { + const { descriptor, object, original, methodName } = this.#restore; + + if (typeof methodName === 'string') { + // This is an object method spy. + ObjectDefineProperty(object, methodName, descriptor); + } else { + // This is a bare function spy. There isn't much to do here but make + // the mock call the original function. + this.#implementation = original; + } + } + + /** + * Resets the recorded calls to the mock function + */ + resetCalls() { + this.#calls = []; + } + + /** + * Tracks a call made to the mock function. + * @param {object} call - The call details. + */ + trackCall(call) { + ArrayPrototypePush(this.#calls, call); + } + + /** + * Gets the next implementation to use for the mock function. + * @returns {Function} The next implementation. + */ + nextImpl() { + const nextCall = this.#calls.length; + const mock = this.#mocks.get(nextCall); + const impl = mock ?? this.#implementation; + + if (nextCall + 1 === this.#times) { + this.restore(); + } + + this.#mocks.delete(nextCall); + return impl; + } +} + +const { nextImpl, restore, trackCall } = MockFunctionContext.prototype; +delete MockFunctionContext.prototype.trackCall; +delete MockFunctionContext.prototype.nextImpl; + +class MockTracker { + #mocks = []; + #timers; + + /** + * Returns the mock timers of this MockTracker instance. + * @returns {MockTimers} The mock timers instance. + */ + get timers() { + this.#timers ??= new MockTimers(); + return this.#timers; + } + + /** + * Creates a mock function tracker. + * @param {Function} [original] - The original function to be tracked. + * @param {Function} [implementation] - An optional replacement function for the original one. + * @param {object} [options] - Additional tracking options. + * @param {number} [options.times=Infinity] - The maximum number of times the mock function can be called. + * @returns {ProxyConstructor} The mock function tracker. + */ + fn( + original = function() {}, + implementation = original, + options = kEmptyObject, + ) { + if (original !== null && typeof original === 'object') { + options = original; + original = function() {}; + implementation = original; + } else if (implementation !== null && typeof implementation === 'object') { + options = implementation; + implementation = original; + } + + validateFunction(original, 'original'); + validateFunction(implementation, 'implementation'); + validateObject(options, 'options'); + const { times = Infinity } = options; + validateTimes(times, 'options.times'); + const ctx = new MockFunctionContext(implementation, { __proto__: null, original }, times); + return this.#setupMock(ctx, original); + } + + /** + * Creates a method tracker for a specified object or function. + * @param {(object | Function)} objectOrFunction - The object or function containing the method to be tracked. + * @param {string} methodName - The name of the method to be tracked. + * @param {Function} [implementation] - An optional replacement function for the original method. + * @param {object} [options] - Additional tracking options. + * @param {boolean} [options.getter=false] - Indicates whether this is a getter method. + * @param {boolean} [options.setter=false] - Indicates whether this is a setter method. + * @param {number} [options.times=Infinity] - The maximum number of times the mock method can be called. + * @returns {ProxyConstructor} The mock method tracker. + */ + method( + objectOrFunction, + methodName, + implementation = kDefaultFunction, + options = kEmptyObject, + ) { + validateStringOrSymbol(methodName, 'methodName'); + if (typeof objectOrFunction !== 'function') { + validateObject(objectOrFunction, 'object'); + } + + if (implementation !== null && typeof implementation === 'object') { + options = implementation; + implementation = kDefaultFunction; + } + + validateFunction(implementation, 'implementation'); + validateObject(options, 'options'); + + const { + getter = false, + setter = false, + times = Infinity, + } = options; + + validateBoolean(getter, 'options.getter'); + validateBoolean(setter, 'options.setter'); + validateTimes(times, 'options.times'); + + if (setter && getter) { + throw new ERR_INVALID_ARG_VALUE( + 'options.setter', setter, "cannot be used with 'options.getter'", + ); + } + const descriptor = findMethodOnPrototypeChain(objectOrFunction, methodName); + + let original; + + if (getter) { + original = descriptor?.get; + } else if (setter) { + original = descriptor?.set; + } else { + original = descriptor?.value; + } + + if (typeof original !== 'function') { + throw new ERR_INVALID_ARG_VALUE( + 'methodName', original, 'must be a method', + ); + } + + const restore = { __proto__: null, descriptor, object: objectOrFunction, methodName }; + const impl = implementation === kDefaultFunction ? + original : implementation; + const ctx = new MockFunctionContext(impl, restore, times); + const mock = this.#setupMock(ctx, original); + const mockDescriptor = { + __proto__: null, + configurable: descriptor.configurable, + enumerable: descriptor.enumerable, + }; + + if (getter) { + mockDescriptor.get = mock; + mockDescriptor.set = descriptor.set; + } else if (setter) { + mockDescriptor.get = descriptor.get; + mockDescriptor.set = mock; + } else { + mockDescriptor.writable = descriptor.writable; + mockDescriptor.value = mock; + } + + ObjectDefineProperty(objectOrFunction, methodName, mockDescriptor); + + return mock; + } + + /** + * Mocks a getter method of an object. + * This is a syntax sugar for the MockTracker.method with options.getter set to true + * @param {object} object - The target object. + * @param {string} methodName - The name of the getter method to be mocked. + * @param {Function} [implementation] - An optional replacement function for the targeted method. + * @param {object} [options] - Additional tracking options. + * @param {boolean} [options.getter=true] - Indicates whether this is a getter method. + * @param {boolean} [options.setter=false] - Indicates whether this is a setter method. + * @param {number} [options.times=Infinity] - The maximum number of times the mock method can be called. + * @returns {ProxyConstructor} The mock method tracker. + */ + getter( + object, + methodName, + implementation = kDefaultFunction, + options = kEmptyObject, + ) { + if (implementation !== null && typeof implementation === 'object') { + options = implementation; + implementation = kDefaultFunction; + } else { + validateObject(options, 'options'); + } + + const { getter = true } = options; + + if (getter === false) { + throw new ERR_INVALID_ARG_VALUE( + 'options.getter', getter, 'cannot be false', + ); + } + + return this.method(object, methodName, implementation, { + __proto__: null, + ...options, + getter, + }); + } + + /** + * Mocks a setter method of an object. + * This function is a syntax sugar for MockTracker.method with options.setter set to true. + * @param {object} object - The target object. + * @param {string} methodName - The setter method to be mocked. + * @param {Function} [implementation] - An optional replacement function for the targeted method. + * @param {object} [options] - Additional tracking options. + * @param {boolean} [options.getter=false] - Indicates whether this is a getter method. + * @param {boolean} [options.setter=true] - Indicates whether this is a setter method. + * @param {number} [options.times=Infinity] - The maximum number of times the mock method can be called. + * @returns {ProxyConstructor} The mock method tracker. + */ + setter( + object, + methodName, + implementation = kDefaultFunction, + options = kEmptyObject, + ) { + if (implementation !== null && typeof implementation === 'object') { + options = implementation; + implementation = kDefaultFunction; + } else { + validateObject(options, 'options'); + } + + const { setter = true } = options; + + if (setter === false) { + throw new ERR_INVALID_ARG_VALUE( + 'options.setter', setter, 'cannot be false', + ); + } + + return this.method(object, methodName, implementation, { + __proto__: null, + ...options, + setter, + }); + } + + /** + * Resets the mock tracker, restoring all mocks and clearing timers. + */ + reset() { + this.restoreAll(); + this.#timers?.reset(); + this.#mocks = []; + } + + /** + * Restore all mocks created by this MockTracker instance. + */ + restoreAll() { + for (let i = 0; i < this.#mocks.length; i++) { + FunctionPrototypeCall(restore, this.#mocks[i]); + } + } + + #setupMock(ctx, fnToMatch) { + const mock = new Proxy(fnToMatch, { + __proto__: null, + apply(_fn, thisArg, argList) { + const fn = FunctionPrototypeCall(nextImpl, ctx); + let result; + let error; + + try { + result = ReflectApply(fn, thisArg, argList); + } catch (err) { + error = err; + throw err; + } finally { + FunctionPrototypeCall(trackCall, ctx, { + __proto__: null, + arguments: argList, + error, + result, + // eslint-disable-next-line no-restricted-syntax + stack: new Error(), + target: undefined, + this: thisArg, + }); + } + + return result; + }, + construct(target, argList, newTarget) { + const realTarget = FunctionPrototypeCall(nextImpl, ctx); + let result; + let error; + + try { + result = ReflectConstruct(realTarget, argList, newTarget); + } catch (err) { + error = err; + throw err; + } finally { + FunctionPrototypeCall(trackCall, ctx, { + __proto__: null, + arguments: argList, + error, + result, + // eslint-disable-next-line no-restricted-syntax + stack: new Error(), + target, + this: result, + }); + } + + return result; + }, + get(target, property, receiver) { + if (property === 'mock') { + return ctx; + } + + return ReflectGet(target, property, receiver); + }, + }); + + ArrayPrototypePush(this.#mocks, ctx); + return mock; + } +} + +function validateStringOrSymbol(value, name) { + if (typeof value !== 'string' && typeof value !== 'symbol') { + throw new ERR_INVALID_ARG_TYPE(name, ['string', 'symbol'], value); + } +} + +function validateTimes(value, name) { + if (value === Infinity) { + return; + } + + validateInteger(value, name, 1); +} + +function findMethodOnPrototypeChain(instance, methodName) { + let host = instance; + let descriptor; + + while (host !== null) { + descriptor = ObjectGetOwnPropertyDescriptor(host, methodName); + + if (descriptor) { + break; + } + + host = ObjectGetPrototypeOf(host); + } + + return descriptor; +} + +module.exports = { MockTracker }; diff --git a/lib/internal/test_runner/mock/mock_timers.js b/lib/internal/test_runner/mock/mock_timers.js new file mode 100644 index 00000000000000..27f553af147cd5 --- /dev/null +++ b/lib/internal/test_runner/mock/mock_timers.js @@ -0,0 +1,568 @@ +'use strict'; + +const { + emitExperimentalWarning, +} = require('internal/util'); + +const { + ArrayPrototypeForEach, + ArrayPrototypeIncludes, + DateNow, + FunctionPrototypeApply, + FunctionPrototypeBind, + ObjectDefineProperty, + ObjectGetOwnPropertyDescriptor, + Promise, + SymbolAsyncIterator, + SymbolDispose, + globalThis, +} = primordials; +const { + validateAbortSignal, + validateArray, +} = require('internal/validators'); + +const { + AbortError, + codes: { + ERR_INVALID_STATE, + ERR_INVALID_ARG_VALUE, + }, +} = require('internal/errors'); + +const PriorityQueue = require('internal/priority_queue'); +const nodeTimers = require('timers'); +const nodeTimersPromises = require('timers/promises'); +const EventEmitter = require('events'); + +let kResistStopPropagation; + +function compareTimersLists(a, b) { + return (a.runAt - b.runAt) || (a.id - b.id); +} + +function setPosition(node, pos) { + node.priorityQueuePosition = pos; +} + +function abortIt(signal) { + return new AbortError(undefined, { __proto__: null, cause: signal.reason }); +} + +const SUPPORTED_TIMERS = ['setTimeout', 'setInterval', 'setImmediate']; +const TIMERS_DEFAULT_INTERVAL = { + __proto__: null, + setImmediate: -1, +}; + +class MockTimers { + #realSetTimeout; + #realClearTimeout; + #realSetInterval; + #realClearInterval; + #realSetImmediate; + #realClearImmediate; + + #realPromisifiedSetTimeout; + #realPromisifiedSetInterval; + + #realTimersSetTimeout; + #realTimersClearTimeout; + #realTimersSetInterval; + #realTimersClearInterval; + #realTimersSetImmediate; + #realTimersClearImmediate; + #realPromisifiedSetImmediate; + + #timersInContext = []; + #isEnabled = false; + #currentTimer = 1; + #now = DateNow(); + + #executionQueue = new PriorityQueue(compareTimersLists, setPosition); + + #setTimeout = FunctionPrototypeBind(this.#createTimer, this, false); + #clearTimeout = FunctionPrototypeBind(this.#clearTimer, this); + #setInterval = FunctionPrototypeBind(this.#createTimer, this, true); + #clearInterval = FunctionPrototypeBind(this.#clearTimer, this); + + #setImmediate = (callback, ...args) => { + return this.#createTimer( + false, + callback, + TIMERS_DEFAULT_INTERVAL.setImmediate, + ...args, + ); + }; + + #clearImmediate = FunctionPrototypeBind(this.#clearTimer, this); + constructor() { + emitExperimentalWarning('The MockTimers API'); + } + + #createTimer(isInterval, callback, delay, ...args) { + const timerId = this.#currentTimer++; + this.#executionQueue.insert({ + __proto__: null, + id: timerId, + callback, + runAt: this.#now + delay, + interval: isInterval, + args, + }); + + return timerId; + } + + #clearTimer(position) { + this.#executionQueue.removeAt(position); + } + + async * #setIntervalPromisified(interval, startTime, options) { + const context = this; + const emitter = new EventEmitter(); + if (options?.signal) { + validateAbortSignal(options.signal, 'options.signal'); + + if (options.signal.aborted) { + throw abortIt(options.signal); + } + + const onAbort = (reason) => { + emitter.emit('data', { __proto__: null, aborted: true, reason }); + }; + + kResistStopPropagation ??= require('internal/event_target').kResistStopPropagation; + options.signal.addEventListener('abort', onAbort, { + __proto__: null, + once: true, + [kResistStopPropagation]: true, + }); + } + + const eventIt = EventEmitter.on(emitter, 'data'); + const callback = () => { + startTime += interval; + emitter.emit('data', startTime); + }; + + const timerId = this.#createTimer(true, callback, interval, options); + const clearListeners = () => { + emitter.removeAllListeners(); + context.#clearTimer(timerId); + }; + const iterator = { + __proto__: null, + [SymbolAsyncIterator]() { + return this; + }, + async next() { + const result = await eventIt.next(); + const value = result.value[0]; + if (value?.aborted) { + iterator.return(); + throw abortIt(options.signal); + } + + return { + __proto__: null, + done: result.done, + value, + }; + }, + async return() { + clearListeners(); + return eventIt.return(); + }, + }; + yield* iterator; + } + + #promisifyTimer({ timerFn, clearFn, ms, result, options }) { + return new Promise((resolve, reject) => { + if (options?.signal) { + try { + validateAbortSignal(options.signal, 'options.signal'); + } catch (err) { + return reject(err); + } + + if (options.signal.aborted) { + return reject(abortIt(options.signal)); + } + } + + const onabort = () => { + clearFn(id); + return reject(abortIt(options.signal)); + }; + + const id = timerFn(() => { + return resolve(result); + }, ms); + + if (options?.signal) { + kResistStopPropagation ??= require('internal/event_target').kResistStopPropagation; + options.signal.addEventListener('abort', onabort, { + __proto__: null, + once: true, + [kResistStopPropagation]: true, + }); + } + }); + } + + #setImmediatePromisified(result, options) { + return this.#promisifyTimer({ + __proto__: null, + timerFn: FunctionPrototypeBind(this.#setImmediate, this), + clearFn: FunctionPrototypeBind(this.#clearImmediate, this), + ms: TIMERS_DEFAULT_INTERVAL.setImmediate, + result, + options, + }); + } + + #setTimeoutPromisified(ms, result, options) { + return this.#promisifyTimer({ + __proto__: null, + timerFn: FunctionPrototypeBind(this.#setTimeout, this), + clearFn: FunctionPrototypeBind(this.#clearTimeout, this), + ms, + result, + options, + }); + } + + #toggleEnableTimers(activate) { + const options = { + __proto__: null, + toFake: { + __proto__: null, + setTimeout: () => { + this.#storeOriginalSetTimeout(); + + globalThis.setTimeout = this.#setTimeout; + globalThis.clearTimeout = this.#clearTimeout; + + nodeTimers.setTimeout = this.#setTimeout; + nodeTimers.clearTimeout = this.#clearTimeout; + + nodeTimersPromises.setTimeout = FunctionPrototypeBind( + this.#setTimeoutPromisified, + this, + ); + }, + setInterval: () => { + this.#storeOriginalSetInterval(); + + globalThis.setInterval = this.#setInterval; + globalThis.clearInterval = this.#clearInterval; + + nodeTimers.setInterval = this.#setInterval; + nodeTimers.clearInterval = this.#clearInterval; + + nodeTimersPromises.setInterval = FunctionPrototypeBind( + this.#setIntervalPromisified, + this, + ); + }, + setImmediate: () => { + this.#storeOriginalSetImmediate(); + + globalThis.setImmediate = this.#setImmediate; + globalThis.clearImmediate = this.#clearImmediate; + + nodeTimers.setImmediate = this.#setImmediate; + nodeTimers.clearImmediate = this.#clearImmediate; + + nodeTimersPromises.setImmediate = FunctionPrototypeBind( + this.#setImmediatePromisified, + this, + ); + }, + }, + toReal: { + __proto__: null, + setTimeout: () => { + this.#restoreOriginalSetTimeout(); + }, + setInterval: () => { + this.#restoreOriginalSetInterval(); + }, + setImmediate: () => { + this.#restoreSetImmediate(); + }, + }, + }; + + const target = activate ? options.toFake : options.toReal; + ArrayPrototypeForEach(this.#timersInContext, (timer) => target[timer]()); + this.#isEnabled = activate; + } + + #restoreSetImmediate() { + ObjectDefineProperty( + globalThis, + 'setImmediate', + this.#realSetImmediate, + ); + ObjectDefineProperty( + globalThis, + 'clearImmediate', + this.#realClearImmediate, + ); + ObjectDefineProperty( + nodeTimers, + 'setImmediate', + this.#realTimersSetImmediate, + ); + ObjectDefineProperty( + nodeTimers, + 'clearImmediate', + this.#realTimersClearImmediate, + ); + ObjectDefineProperty( + nodeTimersPromises, + 'setImmediate', + this.#realPromisifiedSetImmediate, + ); + } + + #restoreOriginalSetInterval() { + ObjectDefineProperty( + globalThis, + 'setInterval', + this.#realSetInterval, + ); + ObjectDefineProperty( + globalThis, + 'clearInterval', + this.#realClearInterval, + ); + ObjectDefineProperty( + nodeTimers, + 'setInterval', + this.#realTimersSetInterval, + ); + ObjectDefineProperty( + nodeTimers, + 'clearInterval', + this.#realTimersClearInterval, + ); + ObjectDefineProperty( + nodeTimersPromises, + 'setInterval', + this.#realPromisifiedSetInterval, + ); + } + + #restoreOriginalSetTimeout() { + ObjectDefineProperty( + globalThis, + 'setTimeout', + this.#realSetTimeout, + ); + ObjectDefineProperty( + globalThis, + 'clearTimeout', + this.#realClearTimeout, + ); + ObjectDefineProperty( + nodeTimers, + 'setTimeout', + this.#realTimersSetTimeout, + ); + ObjectDefineProperty( + nodeTimers, + 'clearTimeout', + this.#realTimersClearTimeout, + ); + ObjectDefineProperty( + nodeTimersPromises, + 'setTimeout', + this.#realPromisifiedSetTimeout, + ); + } + + #storeOriginalSetImmediate() { + this.#realSetImmediate = ObjectGetOwnPropertyDescriptor( + globalThis, + 'setImmediate', + ); + this.#realClearImmediate = ObjectGetOwnPropertyDescriptor( + globalThis, + 'clearImmediate', + ); + this.#realTimersSetImmediate = ObjectGetOwnPropertyDescriptor( + nodeTimers, + 'setImmediate', + ); + this.#realTimersClearImmediate = ObjectGetOwnPropertyDescriptor( + nodeTimers, + 'clearImmediate', + ); + this.#realPromisifiedSetImmediate = ObjectGetOwnPropertyDescriptor( + nodeTimersPromises, + 'setImmediate', + ); + } + + #storeOriginalSetInterval() { + this.#realSetInterval = ObjectGetOwnPropertyDescriptor( + globalThis, + 'setInterval', + ); + this.#realClearInterval = ObjectGetOwnPropertyDescriptor( + globalThis, + 'clearInterval', + ); + this.#realTimersSetInterval = ObjectGetOwnPropertyDescriptor( + nodeTimers, + 'setInterval', + ); + this.#realTimersClearInterval = ObjectGetOwnPropertyDescriptor( + nodeTimers, + 'clearInterval', + ); + this.#realPromisifiedSetInterval = ObjectGetOwnPropertyDescriptor( + nodeTimersPromises, + 'setInterval', + ); + } + + #storeOriginalSetTimeout() { + this.#realSetTimeout = ObjectGetOwnPropertyDescriptor( + globalThis, + 'setTimeout', + ); + this.#realClearTimeout = ObjectGetOwnPropertyDescriptor( + globalThis, + 'clearTimeout', + ); + this.#realTimersSetTimeout = ObjectGetOwnPropertyDescriptor( + nodeTimers, + 'setTimeout', + ); + this.#realTimersClearTimeout = ObjectGetOwnPropertyDescriptor( + nodeTimers, + 'clearTimeout', + ); + this.#realPromisifiedSetTimeout = ObjectGetOwnPropertyDescriptor( + nodeTimersPromises, + 'setTimeout', + ); + } + + /** + * Advances the virtual time of MockTimers by the specified duration (in milliseconds). + * This method simulates the passage of time and triggers any scheduled timers that are due. + * @param {number} [time=1] - The amount of time (in milliseconds) to advance the virtual time. + * @throws {ERR_INVALID_STATE} If MockTimers are not enabled. + * @throws {ERR_INVALID_ARG_VALUE} If a negative time value is provided. + */ + tick(time = 1) { + if (!this.#isEnabled) { + throw new ERR_INVALID_STATE( + 'You should enable MockTimers first by calling the .enable function', + ); + } + + if (time < 0) { + throw new ERR_INVALID_ARG_VALUE( + 'time', + 'positive integer', + time, + ); + } + + this.#now += time; + let timer = this.#executionQueue.peek(); + while (timer) { + if (timer.runAt > this.#now) break; + FunctionPrototypeApply(timer.callback, undefined, timer.args); + + this.#executionQueue.shift(); + + if (timer.interval) { + timer.runAt += timer.interval; + this.#executionQueue.insert(timer); + return; + } + + timer = this.#executionQueue.peek(); + } + } + + /** + * Enables MockTimers for the specified timers. + * @param {string[]} timers - An array of timer types to enable, e.g., ['setTimeout', 'setInterval']. + * @throws {ERR_INVALID_STATE} If MockTimers are already enabled. + * @throws {ERR_INVALID_ARG_VALUE} If an unsupported timer type is specified. + */ + enable(timers = SUPPORTED_TIMERS) { + if (this.#isEnabled) { + throw new ERR_INVALID_STATE( + 'MockTimers is already enabled!', + ); + } + + validateArray(timers, 'timers'); + + // Check that the timers passed are supported + ArrayPrototypeForEach(timers, (timer) => { + if (!ArrayPrototypeIncludes(SUPPORTED_TIMERS, timer)) { + throw new ERR_INVALID_ARG_VALUE( + 'timers', + timer, + `option ${timer} is not supported`, + ); + } + }); + + this.#timersInContext = timers; + this.#now = DateNow(); + this.#toggleEnableTimers(true); + } + + /** + * An alias for `this.reset()`, allowing the disposal of the `MockTimers` instance. + */ + [SymbolDispose]() { + this.reset(); + } + + /** + * Resets MockTimers, disabling any enabled timers and clearing the execution queue. + * Does nothing if MockTimers are not enabled. + */ + reset() { + // Ignore if not enabled + if (!this.#isEnabled) return; + + this.#toggleEnableTimers(false); + this.#timersInContext = []; + + let timer = this.#executionQueue.peek(); + while (timer) { + this.#executionQueue.shift(); + timer = this.#executionQueue.peek(); + } + } + + /** + * Runs all scheduled timers until there are no more pending timers. + * @throws {ERR_INVALID_STATE} If MockTimers are not enabled. + */ + runAll() { + if (!this.#isEnabled) { + throw new ERR_INVALID_STATE( + 'You should enable MockTimers first by calling the .enable function', + ); + } + + this.tick(Infinity); + } +} + +module.exports = { MockTimers }; diff --git a/lib/internal/test_runner/reporter/junit.js b/lib/internal/test_runner/reporter/junit.js new file mode 100644 index 00000000000000..b45c233861c000 --- /dev/null +++ b/lib/internal/test_runner/reporter/junit.js @@ -0,0 +1,158 @@ +'use strict'; +const { + ArrayPrototypeFilter, + ArrayPrototypeMap, + ArrayPrototypeJoin, + ArrayPrototypePush, + ArrayPrototypeSome, + NumberPrototypeToFixed, + ObjectEntries, + RegExpPrototypeSymbolReplace, + String, + StringPrototypeRepeat, +} = primordials; + +const { inspectWithNoCustomRetry } = require('internal/errors'); +const { hostname } = require('os'); + +const inspectOptions = { __proto__: null, colors: false, breakLength: Infinity }; +const HOSTNAME = hostname(); + +function escapeAttribute(s = '') { + return escapeContent(RegExpPrototypeSymbolReplace(/"/g, RegExpPrototypeSymbolReplace(/\n/g, s, ''), '"')); +} + +function escapeContent(s = '') { + return RegExpPrototypeSymbolReplace(/\n`; + } + const attrsString = ArrayPrototypeJoin(ArrayPrototypeMap(ObjectEntries(attrs) + , ({ 0: key, 1: value }) => `${key}="${escapeAttribute(String(value))}"`) + , ' '); + if (!children?.length) { + return `${indent}<${tag} ${attrsString}/>\n`; + } + const childrenString = ArrayPrototypeJoin(ArrayPrototypeMap(children ?? [], treeToXML), ''); + return `${indent}<${tag} ${attrsString}>\n${childrenString}${indent}\n`; +} + +function isFailure(node) { + return (node?.children && ArrayPrototypeSome(node.children, (c) => c.tag === 'failure')) || node?.attrs?.failures; +} + +function isSkipped(node) { + return (node?.children && ArrayPrototypeSome(node.children, (c) => c.tag === 'skipped')) || node?.attrs?.failures; +} + +module.exports = async function* junitReporter(source) { + yield '\n'; + yield '\n'; + let currentSuite = null; + const roots = []; + + function startTest(event) { + const originalSuite = currentSuite; + currentSuite = { + __proto__: null, + attrs: { __proto__: null, name: event.data.name }, + nesting: event.data.nesting, + parent: currentSuite, + children: [], + }; + if (originalSuite?.children) { + ArrayPrototypePush(originalSuite.children, currentSuite); + } + if (!currentSuite.parent) { + ArrayPrototypePush(roots, currentSuite); + } + } + + for await (const event of source) { + switch (event.type) { + case 'test:start': { + startTest(event); + break; + } + case 'test:pass': + case 'test:fail': { + if (!currentSuite) { + startTest({ __proto__: null, data: { __proto__: null, name: 'root', nesting: 0 } }); + } + if (currentSuite.attrs.name !== event.data.name || + currentSuite.nesting !== event.data.nesting) { + startTest(event); + } + const currentTest = currentSuite; + if (currentSuite?.nesting === event.data.nesting) { + currentSuite = currentSuite.parent; + } + currentTest.attrs.time = NumberPrototypeToFixed(event.data.details.duration_ms / 1000, 6); + const nonCommentChildren = ArrayPrototypeFilter(currentTest.children, (c) => c.comment == null); + if (nonCommentChildren.length > 0) { + currentTest.tag = 'testsuite'; + currentTest.attrs.disabled = 0; + currentTest.attrs.errors = 0; + currentTest.attrs.tests = nonCommentChildren.length; + currentTest.attrs.failures = ArrayPrototypeFilter(currentTest.children, isFailure).length; + currentTest.attrs.skipped = ArrayPrototypeFilter(currentTest.children, isSkipped).length; + currentTest.attrs.hostname = HOSTNAME; + } else { + currentTest.tag = 'testcase'; + currentTest.attrs.classname = event.data.classname ?? 'test'; + if (event.data.skip) { + ArrayPrototypePush(currentTest.children, { + __proto__: null, nesting: event.data.nesting + 1, tag: 'skipped', + attrs: { __proto__: null, type: 'skipped', message: event.data.skip }, + }); + } + if (event.data.todo) { + ArrayPrototypePush(currentTest.children, { + __proto__: null, nesting: event.data.nesting + 1, tag: 'skipped', + attrs: { __proto__: null, type: 'todo', message: event.data.todo }, + }); + } + if (event.type === 'test:fail') { + const error = event.data.details?.error; + currentTest.children.push({ + __proto__: null, + nesting: event.data.nesting + 1, + tag: 'failure', + attrs: { __proto__: null, type: error?.failureType || error?.code, message: error?.message ?? '' }, + children: [inspectWithNoCustomRetry(error, inspectOptions)], + }); + currentTest.failures = 1; + currentTest.attrs.failure = error?.message ?? ''; + } + } + break; + } + case 'test:diagnostic': { + const parent = currentSuite?.children ?? roots; + ArrayPrototypePush(parent, { + __proto__: null, nesting: event.data.nesting, comment: event.data.message, + }); + break; + } default: + break; + } + } + for (const suite of roots) { + yield treeToXML(suite); + } + yield '\n'; +}; diff --git a/lib/internal/test_runner/reporter/spec.js b/lib/internal/test_runner/reporter/spec.js index 16cbdf1d5aa901..0c5a3e95c7c75a 100644 --- a/lib/internal/test_runner/reporter/spec.js +++ b/lib/internal/test_runner/reporter/spec.js @@ -17,6 +17,7 @@ const { inspectWithNoCustomRetry } = require('internal/errors'); const { green, blue, red, white, gray, shouldColorize } = require('internal/util/colors'); const { kSubtestsFailed } = require('internal/test_runner/test'); const { getCoverageReport } = require('internal/test_runner/utils'); +const { relative } = require('path'); const inspectOptions = { __proto__: null, colors: shouldColorize(process.stdout), breakLength: Infinity }; @@ -40,9 +41,10 @@ class SpecReporter extends Transform { #reported = []; #indentMemo = new SafeMap(); #failedTests = []; + #cwd = process.cwd(); constructor() { - super({ writableObjectMode: true }); + super({ __proto__: null, writableObjectMode: true }); } #indent(nesting) { @@ -64,17 +66,24 @@ class SpecReporter extends Transform { ), `\n${indent} `); return `\n${indent} ${message}\n`; } - #formatTestReport(type, data, prefix = '', indent = '', hasChildren = false, skippedSubtest = false) { + #formatTestReport(type, data, prefix = '', indent = '', hasChildren = false) { let color = colors[type] ?? white; let symbol = symbols[type] ?? ' '; + const { skip, todo } = data; const duration_ms = data.details?.duration_ms ? ` ${gray}(${data.details.duration_ms}ms)${white}` : ''; - const title = `${data.name}${duration_ms}${skippedSubtest ? ' # SKIP' : ''}`; + let title = `${data.name}${duration_ms}`; + + if (skip !== undefined) { + title += ` # ${typeof skip === 'string' && skip.length ? skip : 'SKIP'}`; + } else if (todo !== undefined) { + title += ` # ${typeof todo === 'string' && todo.length ? todo : 'TODO'}`; + } if (hasChildren) { // If this test has had children - it was already reported, so slightly modify the output return `${prefix}${indent}${color}${symbols['arrow:right']}${white}${title}\n`; } const error = this.#formatError(data.details?.error, indent); - if (skippedSubtest) { + if (skip !== undefined) { color = gray; symbol = symbols['hyphen:minus']; } @@ -101,9 +110,8 @@ class SpecReporter extends Transform { ArrayPrototypeShift(this.#reported); hasChildren = true; } - const skippedSubtest = subtest && data.skip && data.skip !== undefined; const indent = this.#indent(data.nesting); - return `${this.#formatTestReport(type, data, prefix, indent, hasChildren, skippedSubtest)}\n`; + return `${this.#formatTestReport(type, data, prefix, indent, hasChildren)}\n`; } #handleEvent({ type, data }) { switch (type) { @@ -127,7 +135,7 @@ class SpecReporter extends Transform { } } _transform({ type, data }, encoding, callback) { - callback(null, this.#handleEvent({ type, data })); + callback(null, this.#handleEvent({ __proto__: null, type, data })); } _flush(callback) { if (this.#failedTests.length === 0) { @@ -136,10 +144,12 @@ class SpecReporter extends Transform { } const results = [`\n${colors['test:fail']}${symbols['test:fail']}failing tests:${white}\n`]; for (let i = 0; i < this.#failedTests.length; i++) { - ArrayPrototypePush(results, this.#formatTestReport( - 'test:fail', - this.#failedTests[i], - )); + const test = this.#failedTests[i]; + const relPath = relative(this.#cwd, test.file); + const formattedErr = this.#formatTestReport('test:fail', test); + const location = `test at ${relPath}:${test.line}:${test.column}`; + + ArrayPrototypePush(results, location, formattedErr); } callback(null, ArrayPrototypeJoin(results, '\n')); } diff --git a/lib/internal/test_runner/reporter/tap.js b/lib/internal/test_runner/reporter/tap.js index 4aec4ba072d954..1f60cfa619886e 100644 --- a/lib/internal/test_runner/reporter/tap.js +++ b/lib/internal/test_runner/reporter/tap.js @@ -18,7 +18,7 @@ const kDefaultIndent = ' '; // 4 spaces const kFrameStartRegExp = /^ {4}at /; const kLineBreakRegExp = /\n|\r\n/; const kDefaultTAPVersion = 13; -const inspectOptions = { colors: false, breakLength: Infinity }; +const inspectOptions = { __proto__: null, colors: false, breakLength: Infinity }; let testModule; // Lazy loaded due to circular dependency. function lazyLoadTest() { @@ -31,13 +31,14 @@ async function * tapReporter(source) { yield `TAP version ${kDefaultTAPVersion}\n`; for await (const { type, data } of source) { switch (type) { - case 'test:fail': + case 'test:fail': { yield reportTest(data.nesting, data.testNumber, 'not ok', data.name, data.skip, data.todo); - yield reportDetails(data.nesting, data.details); + const location = `${data.file}:${data.line}:${data.column}`; + yield reportDetails(data.nesting, data.details, location); break; - case 'test:pass': + } case 'test:pass': yield reportTest(data.nesting, data.testNumber, 'ok', data.name, data.skip, data.todo); - yield reportDetails(data.nesting, data.details); + yield reportDetails(data.nesting, data.details, null); break; case 'test:plan': yield `${indent(data.nesting)}1..${data.count}\n`; @@ -81,13 +82,18 @@ function reportTest(nesting, testNumber, status, name, skip, todo) { return line; } -function reportDetails(nesting, data = kEmptyObject) { +function reportDetails(nesting, data = kEmptyObject, location) { const { error, duration_ms } = data; const _indent = indent(nesting); let details = `${_indent} ---\n`; details += jsToYaml(_indent, 'duration_ms', duration_ms); details += jsToYaml(_indent, 'type', data.type); + + if (location) { + details += jsToYaml(_indent, 'location', location); + } + details += jsToYaml(_indent, null, error, new SafeSet()); details += `${_indent} ...\n`; return details; @@ -171,7 +177,7 @@ function jsToYaml(indent, name, value, seen) { } if (isErrorObj) { - const { kTestCodeFailure, kUnwrapErrors } = lazyLoadTest(); + const { kUnwrapErrors } = lazyLoadTest(); const { cause, code, @@ -198,15 +204,14 @@ function jsToYaml(indent, name, value, seen) { errStack = cause?.stack ?? errStack; errCode = cause?.code ?? errCode; errName = cause?.name ?? errName; + errMsg = cause?.message ?? errMsg; + if (isAssertionLike(cause)) { errExpected = cause.expected; errActual = cause.actual; errOperator = cause.operator ?? errOperator; errIsAssertion = true; } - if (failureType === kTestCodeFailure) { - errMsg = cause?.message ?? errMsg; - } } result += jsToYaml(indent, 'error', errMsg, seen); diff --git a/lib/internal/test_runner/runner.js b/lib/internal/test_runner/runner.js index 88b648d9a19cbf..2dd9ea678e3b80 100644 --- a/lib/internal/test_runner/runner.js +++ b/lib/internal/test_runner/runner.js @@ -39,10 +39,18 @@ const console = require('internal/console/global'); const { codes: { ERR_INVALID_ARG_TYPE, + ERR_INVALID_ARG_VALUE, ERR_TEST_FAILURE, + ERR_OUT_OF_RANGE, }, } = require('internal/errors'); -const { validateArray, validateBoolean, validateFunction } = require('internal/validators'); +const { + validateArray, + validateBoolean, + validateFunction, + validateObject, + validateInteger, +} = require('internal/validators'); const { getInspectPort, isUsingInspector, isInspectorMessage } = require('internal/util/inspector'); const { isRegExp } = require('internal/util/types'); const { kEmptyObject } = require('internal/util'); @@ -76,6 +84,8 @@ const kDiagnosticsFilterArgs = ['tests', 'suites', 'pass', 'fail', 'cancelled', const kCanceledTests = new SafeSet() .add(kCancelledByParent).add(kAborted).add(kTestTimeoutFailure); +let kResistStopPropagation; + // TODO(cjihrig): Replace this with recursive readdir once it lands. function processPath(path, testFiles, options) { const stats = statSync(path); @@ -124,7 +134,10 @@ function createTestFileList() { for (let i = 0; i < testPaths.length; i++) { const absolutePath = resolve(testPaths[i]); - processPath(absolutePath, testFiles, { userSupplied: true }); + processPath(absolutePath, testFiles, { + __proto__: null, + userSupplied: true, + }); } } catch (err) { if (err?.code === 'ENOENT') { @@ -143,14 +156,17 @@ function filterExecArgv(arg, i, arr) { !ArrayPrototypeSome(kFilterArgValues, (p) => arg === p || (i > 0 && arr[i - 1] === p) || StringPrototypeStartsWith(arg, `${p}=`)); } -function getRunArgs({ path, inspectPort, testNamePatterns }) { +function getRunArgs(path, { inspectPort, testNamePatterns, only }) { const argv = ArrayPrototypeFilter(process.execArgv, filterExecArgv); if (isUsingInspector()) { ArrayPrototypePush(argv, `--inspect-port=${getInspectPort(inspectPort)}`); } - if (testNamePatterns) { + if (testNamePatterns != null) { ArrayPrototypeForEach(testNamePatterns, (pattern) => ArrayPrototypePush(argv, `--test-name-pattern=${pattern}`)); } + if (only === true) { + ArrayPrototypePush(argv, '--test-only'); + } ArrayPrototypePush(argv, path); return argv; @@ -169,6 +185,17 @@ class FileTest extends Test { #rawBufferSize = 0; #reportedChildren = 0; failedSubtests = false; + + constructor(options) { + super(options); + this.loc ??= { + __proto__: null, + line: 1, + column: 1, + file: resolve(this.name), + }; + } + #skipReporting() { return this.#reportedChildren > 0 && (!this.error || this.error.failureType === kSubtestsFailed); } @@ -334,21 +361,21 @@ class FileTest extends Test { } } -function runTestFile(path, root, inspectPort, filesWatcher, testNamePatterns) { +function runTestFile(path, filesWatcher, opts) { const watchMode = filesWatcher != null; - const subtest = root.createSubtest(FileTest, path, async (t) => { - const args = getRunArgs({ path, inspectPort, testNamePatterns }); + const subtest = opts.root.createSubtest(FileTest, path, async (t) => { + const args = getRunArgs(path, opts); const stdio = ['pipe', 'pipe', 'pipe']; - const env = { ...process.env, NODE_TEST_CONTEXT: 'child-v8' }; + const env = { __proto__: null, ...process.env, NODE_TEST_CONTEXT: 'child-v8' }; if (watchMode) { stdio.push('ipc'); env.WATCH_REPORT_DEPENDENCIES = '1'; } - if (root.harness.shouldColorizeTestFiles) { + if (opts.root.harness.shouldColorizeTestFiles) { env.FORCE_COLOR = '1'; } - const child = spawn(process.execPath, args, { signal: t.signal, encoding: 'utf8', env, stdio }); + const child = spawn(process.execPath, args, { __proto__: null, signal: t.signal, encoding: 'utf8', env, stdio }); if (watchMode) { filesWatcher.runningProcesses.set(path, child); filesWatcher.watcher.watchChildProcessModules(child, path); @@ -365,7 +392,7 @@ function runTestFile(path, root, inspectPort, filesWatcher, testNamePatterns) { subtest.parseMessage(data); }); - const rl = createInterface({ input: child.stderr }); + const rl = createInterface({ __proto__: null, input: child.stderr }); rl.on('line', (line) => { if (isInspectorMessage(line)) { process.stderr.write(line + '\n'); @@ -383,15 +410,15 @@ function runTestFile(path, root, inspectPort, filesWatcher, testNamePatterns) { }); const { 0: { 0: code, 1: signal } } = await SafePromiseAll([ - once(child, 'exit', { signal: t.signal }), - finished(child.stdout, { signal: t.signal }), + once(child, 'exit', { __proto__: null, signal: t.signal }), + finished(child.stdout, { __proto__: null, signal: t.signal }), ]); if (watchMode) { filesWatcher.runningProcesses.delete(path); filesWatcher.runningSubtests.delete(path); if (filesWatcher.runningSubtests.size === 0) { - root.reporter[kEmitMessage]('test:watch:drained'); + opts.root.reporter[kEmitMessage]('test:watch:drained'); } } @@ -414,10 +441,10 @@ function runTestFile(path, root, inspectPort, filesWatcher, testNamePatterns) { return subtest.start(); } -function watchFiles(testFiles, root, inspectPort, signal, testNamePatterns) { +function watchFiles(testFiles, opts) { const runningProcesses = new SafeMap(); const runningSubtests = new SafeMap(); - const watcher = new FilesWatcher({ throttle: 500, mode: 'filter', signal }); + const watcher = new FilesWatcher({ __proto__: null, debounce: 200, mode: 'filter', signal: opts.signal }); const filesWatcher = { __proto__: null, watcher, runningProcesses, runningSubtests }; watcher.on('changed', ({ owners }) => { @@ -433,15 +460,22 @@ function watchFiles(testFiles, root, inspectPort, signal, testNamePatterns) { } if (!runningSubtests.size) { // Reset the topLevel counter - root.harness.counters.topLevel = 0; + opts.root.harness.counters.topLevel = 0; } await runningSubtests.get(file); - runningSubtests.set(file, runTestFile(file, root, inspectPort, filesWatcher, testNamePatterns)); + runningSubtests.set(file, runTestFile(file, filesWatcher, opts)); }, undefined, (error) => { triggerUncaughtException(error, true /* fromPromise */); })); }); - signal?.addEventListener('abort', () => root.postRun(), { __proto__: null, once: true }); + if (opts.signal) { + kResistStopPropagation ??= require('internal/event_target').kResistStopPropagation; + opts.signal.addEventListener( + 'abort', + () => opts.root.postRun(), + { __proto__: null, once: true, [kResistStopPropagation]: true }, + ); + } return filesWatcher; } @@ -450,8 +484,8 @@ function run(options) { if (options === null || typeof options !== 'object') { options = kEmptyObject; } - let { testNamePatterns } = options; - const { concurrency, timeout, signal, files, inspectPort, watch, setup } = options; + let { testNamePatterns, shard } = options; + const { concurrency, timeout, signal, files, inspectPort, watch, setup, only } = options; if (files != null) { validateArray(files, 'options.files'); @@ -459,6 +493,25 @@ function run(options) { if (watch != null) { validateBoolean(watch, 'options.watch'); } + if (only != null) { + validateBoolean(only, 'options.only'); + } + if (shard != null) { + validateObject(shard, 'options.shard'); + // Avoid re-evaluating the shard object in case it's a getter + shard = { __proto__: null, index: shard.index, total: shard.total }; + + validateInteger(shard.total, 'options.shard.total', 1); + validateInteger(shard.index, 'options.shard.index'); + + if (shard.index <= 0 || shard.total < shard.index) { + throw new ERR_OUT_OF_RANGE('options.shard.index', `>= 1 && <= ${shard.total} ("options.shard.total")`, shard.index); + } + + if (watch) { + throw new ERR_INVALID_ARG_VALUE('options.shard', watch, 'shards not supported with watch mode'); + } + } if (setup != null) { validateFunction(setup, 'options.setup'); } @@ -479,19 +532,24 @@ function run(options) { }); } - const root = createTestTree({ concurrency, timeout, signal }); - const testFiles = files ?? createTestFileList(); + const root = createTestTree({ __proto__: null, concurrency, timeout, signal }); + let testFiles = files ?? createTestFileList(); + + if (shard) { + testFiles = ArrayPrototypeFilter(testFiles, (_, index) => index % shard.total === shard.index - 1); + } let postRun = () => root.postRun(); let filesWatcher; + const opts = { __proto__: null, root, signal, inspectPort, testNamePatterns, only }; if (watch) { - filesWatcher = watchFiles(testFiles, root, inspectPort, signal, testNamePatterns); + filesWatcher = watchFiles(testFiles, opts); postRun = undefined; } const runFiles = () => { root.harness.bootstrapComplete = true; return SafePromiseAllSettledReturnVoid(testFiles, (path) => { - const subtest = runTestFile(path, root, inspectPort, filesWatcher, testNamePatterns); + const subtest = runTestFile(path, filesWatcher, opts); filesWatcher?.runningSubtests.set(path, subtest); return subtest; }); diff --git a/lib/internal/test_runner/test.js b/lib/internal/test_runner/test.js index 501fed4addec93..4eb02c5d4e3118 100644 --- a/lib/internal/test_runner/test.js +++ b/lib/internal/test_runner/test.js @@ -13,16 +13,20 @@ const { ObjectSeal, PromisePrototypeThen, PromiseResolve, + SafePromisePrototypeFinally, ReflectApply, RegExpPrototypeExec, SafeMap, SafeSet, SafePromiseAll, SafePromiseRace, + SymbolDispose, + ObjectDefineProperty, Symbol, } = primordials; +const { getCallerLocation } = internalBinding('util'); +const { addAbortListener } = require('events'); const { AsyncResource } = require('async_hooks'); -const { once } = require('events'); const { AbortController } = require('internal/abort_controller'); const { codes: { @@ -31,7 +35,7 @@ const { }, AbortError, } = require('internal/errors'); -const { MockTracker } = require('internal/test_runner/mock'); +const { MockTracker } = require('internal/test_runner/mock/mock'); const { TestsStream } = require('internal/test_runner/tests_stream'); const { createDeferredCallback, @@ -51,9 +55,9 @@ const { validateOneOf, validateUint32, } = require('internal/validators'); -const { setTimeout } = require('timers/promises'); +const { setTimeout } = require('timers'); const { TIMEOUT_MAX } = require('internal/timers'); -const { cpus } = require('os'); +const { availableParallelism } = require('os'); const { bigint: hrtime } = process.hrtime; const kCallbackAndPromisePresent = 'callbackAndPromisePresent'; const kCancelledByParent = 'cancelledByParent'; @@ -72,17 +76,45 @@ const kUnwrapErrors = new SafeSet() .add(kTestCodeFailure).add(kHookFailure) .add('uncaughtException').add('unhandledRejection'); const { testNamePatterns, testOnlyFlag } = parseCommandLine(); +let kResistStopPropagation; function stopTest(timeout, signal) { + const deferred = createDeferredPromise(); + const abortListener = addAbortListener(signal, deferred.resolve); + let timer; + let disposeFunction; + if (timeout === kDefaultTimeout) { - return once(signal, 'abort'); + disposeFunction = abortListener[SymbolDispose]; + } else { + timer = setTimeout(() => deferred.resolve(), timeout); + timer.unref(); + + ObjectDefineProperty(deferred, 'promise', { + __proto__: null, + configurable: true, + writable: true, + value: PromisePrototypeThen(deferred.promise, () => { + throw new ERR_TEST_FAILURE( + `test timed out after ${timeout}ms`, + kTestTimeoutFailure, + ); + }), + }); + + disposeFunction = () => { + abortListener[SymbolDispose](); + timer[SymbolDispose](); + }; } - return PromisePrototypeThen(setTimeout(timeout, null, { ref: false, signal }), () => { - throw new ERR_TEST_FAILURE( - `test timed out after ${timeout}ms`, - kTestTimeoutFailure, - ); + + ObjectDefineProperty(deferred.promise, SymbolDispose, { + __proto__: null, + configurable: true, + writable: true, + value: disposeFunction, }); + return deferred.promise; } class TestContext { @@ -122,8 +154,15 @@ class TestContext { } test(name, options, fn) { - // eslint-disable-next-line no-use-before-define - const subtest = this.#test.createSubtest(Test, name, options, fn); + const overrides = { + __proto__: null, + loc: getCallerLocation(), + }; + + const subtest = this.#test.createSubtest( + // eslint-disable-next-line no-use-before-define + Test, name, options, fn, overrides, + ); return subtest.start(); } @@ -162,15 +201,15 @@ class SuiteContext { } class Test extends AsyncResource { - #abortController; - #outerSignal; + abortController; + outerSignal; #reportedSubtest; constructor(options) { super('Test'); let { fn, name, parent, skip } = options; - const { concurrency, only, timeout, todo, signal } = options; + const { concurrency, loc, only, timeout, todo, signal } = options; if (typeof fn !== 'function') { fn = noop; @@ -229,8 +268,8 @@ class Test extends AsyncResource { case 'boolean': if (concurrency) { - // TODO(cjihrig): Use uv_available_parallelism() once it lands. - this.concurrency = parent === null ? MathMax(cpus().length - 1, 1) : Infinity; + this.concurrency = parent === null ? + MathMax(availableParallelism() - 1, 1) : Infinity; } else { this.concurrency = 1; } @@ -261,19 +300,27 @@ class Test extends AsyncResource { fn = noop; } - this.#abortController = new AbortController(); - this.#outerSignal = signal; - this.signal = this.#abortController.signal; + this.abortController = new AbortController(); + this.outerSignal = signal; + this.signal = this.abortController.signal; validateAbortSignal(signal, 'options.signal'); - this.#outerSignal?.addEventListener('abort', this.#abortHandler); + if (signal) { + kResistStopPropagation ??= require('internal/event_target').kResistStopPropagation; + } + + this.outerSignal?.addEventListener( + 'abort', + this.#abortHandler, + { __proto__: null, [kResistStopPropagation]: true }, + ); this.fn = fn; this.harness = null; // Configured on the root test by the test harness. this.mock = null; this.cancelled = false; - this.skipped = !!skip; - this.isTodo = !!todo; + this.skipped = skip !== undefined && skip !== false; + this.isTodo = todo !== undefined && todo !== false; this.startTime = null; this.endTime = null; this.passed = false; @@ -293,6 +340,17 @@ class Test extends AsyncResource { "'only' and 'runOnly' require the --test-only command-line option."; this.diagnostic(warning); } + + if (loc === undefined || kFilename === undefined) { + this.loc = undefined; + } else { + this.loc = { + __proto__: null, + line: loc[0], + column: loc[1], + file: loc[2], + }; + } } matchesTestNamePatterns() { @@ -312,7 +370,7 @@ class Test extends AsyncResource { while (this.pendingSubtests.length > 0 && this.hasConcurrency()) { const deferred = ArrayPrototypeShift(this.pendingSubtests); const test = deferred.test; - this.reporter.dequeue(test.nesting, kFilename, test.name); + this.reporter.dequeue(test.nesting, test.loc, test.name); await test.run(); deferred.resolve(); } @@ -402,7 +460,7 @@ class Test extends AsyncResource { } #abortHandler = () => { - const error = this.#outerSignal?.reason || new AbortError('The test was aborted'); + const error = this.outerSignal?.reason || new AbortError('The test was aborted'); error.failureType = kAborted; this.#cancel(error); }; @@ -420,7 +478,7 @@ class Test extends AsyncResource { ); this.startTime = this.startTime || this.endTime; // If a test was canceled before it was started, e.g inside a hook this.cancelled = true; - this.#abortController.abort(); + this.abortController.abort(); } createHook(name, fn, options) { @@ -471,7 +529,7 @@ class Test extends AsyncResource { // If there is enough available concurrency to run the test now, then do // it. Otherwise, return a Promise to the caller and mark the test as // pending for later execution. - this.reporter.enqueue(this.nesting, kFilename, this.name); + this.reporter.enqueue(this.nesting, this.loc, this.name); if (!this.parent.hasConcurrency()) { const deferred = createDeferredPromise(); @@ -480,7 +538,7 @@ class Test extends AsyncResource { return deferred.promise; } - this.reporter.dequeue(this.nesting, kFilename, this.name); + this.reporter.dequeue(this.nesting, this.loc, this.name); return this.run(); } @@ -488,7 +546,7 @@ class Test extends AsyncResource { if (this.signal.aborted) { return true; } - if (this.#outerSignal?.aborted) { + if (this.outerSignal?.aborted) { this.#abortHandler(); return true; } @@ -496,7 +554,7 @@ class Test extends AsyncResource { getRunArgs() { const ctx = new TestContext(this); - return { ctx, args: [ctx] }; + return { __proto__: null, ctx, args: [ctx] }; } async runHook(hook, args) { @@ -516,7 +574,7 @@ class Test extends AsyncResource { } } - async run(pendingSubtestsError) { + async run() { if (this.parent !== null) { this.parent.activeSubtests++; } @@ -530,23 +588,25 @@ class Test extends AsyncResource { const { args, ctx } = this.getRunArgs(); const after = async () => { if (this.hooks.after.length > 0) { - await this.runHook('after', { args, ctx }); + await this.runHook('after', { __proto__: null, args, ctx }); } }; const afterEach = runOnce(async () => { if (this.parent?.hooks.afterEach.length > 0) { - await this.parent.runHook('afterEach', { args, ctx }); + await this.parent.runHook('afterEach', { __proto__: null, args, ctx }); } }); + let stopPromise; + try { if (this.parent?.hooks.before.length > 0) { await this.parent.runHook('before', this.parent.getRunArgs()); } if (this.parent?.hooks.beforeEach.length > 0) { - await this.parent.runHook('beforeEach', { args, ctx }); + await this.parent.runHook('beforeEach', { __proto__: null, args, ctx }); } - const stopPromise = stopTest(this.timeout, this.signal); + stopPromise = stopTest(this.timeout, this.signal); const runArgs = ArrayPrototypeSlice(args); ArrayPrototypeUnshift(runArgs, this.fn, ctx); @@ -592,11 +652,26 @@ class Test extends AsyncResource { } else { this.fail(new ERR_TEST_FAILURE(err, kTestCodeFailure)); } + } finally { + stopPromise?.[SymbolDispose](); + + // Do not abort hooks and the root test as hooks instance are shared between tests suite so aborting them will + // cause them to not run for further tests. + if (this.parent !== null) { + this.abortController.abort(); + } } - // Clean up the test. Then, try to report the results and execute any - // tests that were pending due to available concurrency. - this.postRun(pendingSubtestsError); + if (this.parent !== null || typeof this.hookType === 'string') { + // Clean up the test. Then, try to report the results and execute any + // tests that were pending due to available concurrency. + // + // The root test is skipped here because it is a special case. Its + // postRun() method is called when the process is getting ready to exit. + // This helps catch any asynchronous activity that occurs after the tests + // have finished executing. + this.postRun(); + } } postRun(pendingSubtestsError) { @@ -618,7 +693,7 @@ class Test extends AsyncResource { subtest.#cancel(pendingSubtestsError); subtest.postRun(pendingSubtestsError); } - if (!subtest.passed) { + if (!subtest.passed && !subtest.isTodo) { failed++; } } @@ -630,7 +705,7 @@ class Test extends AsyncResource { this.fail(new ERR_TEST_FAILURE(msg, kSubtestsFailed)); } - this.#outerSignal?.removeEventListener('abort', this.#abortHandler); + this.outerSignal?.removeEventListener('abort', this.#abortHandler); this.mock?.reset(); if (this.parent !== null) { @@ -638,30 +713,50 @@ class Test extends AsyncResource { this.parent.addReadySubtest(this); this.parent.processReadySubtestRange(false); this.parent.processPendingSubtests(); + + if (this.parent === this.root && + this.root.activeSubtests === 0 && + this.root.pendingSubtests.length === 0 && + this.root.readySubtests.size === 0 && + this.root.hooks.after.length > 0) { + // This is done so that any global after() hooks are run. At this point + // all of the tests have finished running. However, there might be + // ref'ed handles keeping the event loop alive. This gives the global + // after() hook a chance to clean them up. + this.root.run(); + } } else if (!this.reported) { + const { + diagnostics, + harness, + loc, + nesting, + reporter, + } = this; + this.reported = true; - this.reporter.plan(this.nesting, kFilename, this.root.harness.counters.topLevel); + reporter.plan(nesting, loc, harness.counters.topLevel); - for (let i = 0; i < this.diagnostics.length; i++) { - this.reporter.diagnostic(this.nesting, kFilename, this.diagnostics[i]); + // Call this harness.coverage() before collecting diagnostics, since failure to collect coverage is a diagnostic. + const coverage = harness.coverage(); + for (let i = 0; i < diagnostics.length; i++) { + reporter.diagnostic(nesting, loc, diagnostics[i]); } - this.reporter.diagnostic(this.nesting, kFilename, `tests ${this.root.harness.counters.all}`); - this.reporter.diagnostic(this.nesting, kFilename, `suites ${this.root.harness.counters.suites}`); - this.reporter.diagnostic(this.nesting, kFilename, `pass ${this.root.harness.counters.passed}`); - this.reporter.diagnostic(this.nesting, kFilename, `fail ${this.root.harness.counters.failed}`); - this.reporter.diagnostic(this.nesting, kFilename, `cancelled ${this.root.harness.counters.cancelled}`); - this.reporter.diagnostic(this.nesting, kFilename, `skipped ${this.root.harness.counters.skipped}`); - this.reporter.diagnostic(this.nesting, kFilename, `todo ${this.root.harness.counters.todo}`); - this.reporter.diagnostic(this.nesting, kFilename, `duration_ms ${this.#duration()}`); - - const coverage = this.harness.coverage(); + reporter.diagnostic(nesting, loc, `tests ${harness.counters.all}`); + reporter.diagnostic(nesting, loc, `suites ${harness.counters.suites}`); + reporter.diagnostic(nesting, loc, `pass ${harness.counters.passed}`); + reporter.diagnostic(nesting, loc, `fail ${harness.counters.failed}`); + reporter.diagnostic(nesting, loc, `cancelled ${harness.counters.cancelled}`); + reporter.diagnostic(nesting, loc, `skipped ${harness.counters.skipped}`); + reporter.diagnostic(nesting, loc, `todo ${harness.counters.todo}`); + reporter.diagnostic(nesting, loc, `duration_ms ${this.duration()}`); if (coverage) { - this.reporter.coverage(this.nesting, kFilename, coverage); + reporter.coverage(nesting, loc, coverage); } - this.reporter.end(); + reporter.end(); } } @@ -689,7 +784,7 @@ class Test extends AsyncResource { this.finished = true; } - #duration() { + duration() { // Duration is recorded in BigInt nanoseconds. Convert to milliseconds. return Number(this.endTime - this.startTime) / 1_000_000; } @@ -697,12 +792,12 @@ class Test extends AsyncResource { report() { countCompletedTest(this); if (this.subtests.length > 0) { - this.reporter.plan(this.subtests[0].nesting, kFilename, this.subtests.length); + this.reporter.plan(this.subtests[0].nesting, this.loc, this.subtests.length); } else { this.reportStarted(); } let directive; - const details = { __proto__: null, duration_ms: this.#duration() }; + const details = { __proto__: null, duration_ms: this.duration() }; if (this.skipped) { directive = this.reporter.getSkip(this.message); @@ -715,14 +810,14 @@ class Test extends AsyncResource { } if (this.passed) { - this.reporter.ok(this.nesting, kFilename, this.testNumber, this.name, details, directive); + this.reporter.ok(this.nesting, this.loc, this.testNumber, this.name, details, directive); } else { details.error = this.error; - this.reporter.fail(this.nesting, kFilename, this.testNumber, this.name, details, directive); + this.reporter.fail(this.nesting, this.loc, this.testNumber, this.name, details, directive); } for (let i = 0; i < this.diagnostics.length; i++) { - this.reporter.diagnostic(this.nesting, kFilename, this.diagnostics[i]); + this.reporter.diagnostic(this.nesting, this.loc, this.diagnostics[i]); } } @@ -732,7 +827,7 @@ class Test extends AsyncResource { } this.#reportedSubtest = true; this.parent.reportStarted(); - this.reporter.start(this.nesting, kFilename, this.name); + this.reporter.start(this.nesting, this.loc, this.name); } } @@ -742,10 +837,21 @@ class TestHook extends Test { if (options === null || typeof options !== 'object') { options = kEmptyObject; } - const { timeout, signal } = options; - super({ __proto__: null, fn, timeout, signal }); + const { loc, timeout, signal } = options; + super({ __proto__: null, fn, loc, timeout, signal }); + + this.parentTest = options.parent ?? null; + this.hookType = options.hookType; } run(args) { + if (this.error && !this.outerSignal?.aborted) { + this.passed = false; + this.error = null; + this.abortController.abort(); + this.abortController = new AbortController(); + this.signal = this.abortController.signal; + } + this.#args = args; return super.run(); } @@ -756,6 +862,22 @@ class TestHook extends Test { return true; } postRun() { + const { error, loc, parentTest: parent } = this; + + // Report failures in the root test's after() hook. + if (error && parent !== null && + parent === parent.root && this.hookType === 'after') { + + if (isTestFailureError(error)) { + error.failureType = kHookFailure; + } + + parent.reporter.fail(0, loc, parent.subtests.length + 1, loc.file, { + __proto__: null, + duration_ms: this.duration(), + error, + }, undefined); + } } } @@ -774,27 +896,34 @@ class Suite extends Test { const { ctx, args } = this.getRunArgs(); const runArgs = [this.fn, ctx]; ArrayPrototypePushApply(runArgs, args); - this.buildSuite = PromisePrototypeThen( - PromiseResolve(ReflectApply(this.runInAsyncScope, this, runArgs)), - undefined, - (err) => { - this.fail(new ERR_TEST_FAILURE(err, kTestCodeFailure)); - }); + this.buildSuite = SafePromisePrototypeFinally( + PromisePrototypeThen( + PromiseResolve(ReflectApply(this.runInAsyncScope, this, runArgs)), + undefined, + (err) => { + this.fail(new ERR_TEST_FAILURE(err, kTestCodeFailure)); + }), + () => { + this.buildPhaseFinished = true; + }, + ); } catch (err) { this.fail(new ERR_TEST_FAILURE(err, kTestCodeFailure)); + + this.buildPhaseFinished = true; } this.fn = () => {}; - this.buildPhaseFinished = true; } getRunArgs() { const ctx = new SuiteContext(this); - return { ctx, args: [ctx] }; + return { __proto__: null, ctx, args: [ctx] }; } async run() { const hookArgs = this.getRunArgs(); + let stopPromise; try { this.parent.activeSubtests++; await this.buildSuite; @@ -806,9 +935,13 @@ class Suite extends Test { return; } + if (this.parent.hooks.before.length > 0) { + await this.parent.runHook('before', this.parent.getRunArgs()); + } + await this.runHook('before', hookArgs); - const stopPromise = stopTest(this.timeout, this.signal); + stopPromise = stopTest(this.timeout, this.signal); const subtests = this.skipped || this.error ? [] : this.subtests; const promise = SafePromiseAll(subtests, (subtests) => subtests.start()); @@ -822,6 +955,8 @@ class Suite extends Test { } else { this.fail(new ERR_TEST_FAILURE(err, kTestCodeFailure)); } + } finally { + stopPromise?.[SymbolDispose](); } this.postRun(); diff --git a/lib/internal/test_runner/tests_stream.js b/lib/internal/test_runner/tests_stream.js index 20e7d458704b20..f7730caac00fa7 100644 --- a/lib/internal/test_runner/tests_stream.js +++ b/lib/internal/test_runner/tests_stream.js @@ -12,7 +12,7 @@ class TestsStream extends Readable { #canPush; constructor() { - super({ objectMode: true }); + super({ __proto__: null, objectMode: true }); this.#buffer = []; this.#canPush = true; } @@ -29,16 +29,37 @@ class TestsStream extends Readable { } } - fail(nesting, file, testNumber, name, details, directive) { - this[kEmitMessage]('test:fail', { __proto__: null, name, nesting, file, testNumber, details, ...directive }); + fail(nesting, loc, testNumber, name, details, directive) { + this[kEmitMessage]('test:fail', { + __proto__: null, + name, + nesting, + testNumber, + details, + ...loc, + ...directive, + }); } - ok(nesting, file, testNumber, name, details, directive) { - this[kEmitMessage]('test:pass', { __proto__: null, name, nesting, file, testNumber, details, ...directive }); + ok(nesting, loc, testNumber, name, details, directive) { + this[kEmitMessage]('test:pass', { + __proto__: null, + name, + nesting, + testNumber, + details, + ...loc, + ...directive, + }); } - plan(nesting, file, count) { - this[kEmitMessage]('test:plan', { __proto__: null, nesting, file, count }); + plan(nesting, loc, count) { + this[kEmitMessage]('test:plan', { + __proto__: null, + nesting, + count, + ...loc, + }); } getSkip(reason = undefined) { @@ -49,32 +70,57 @@ class TestsStream extends Readable { return { __proto__: null, todo: reason ?? true }; } - enqueue(nesting, file, name) { - this[kEmitMessage]('test:enqueue', { __proto__: null, nesting, file, name }); + enqueue(nesting, loc, name) { + this[kEmitMessage]('test:enqueue', { + __proto__: null, + nesting, + name, + ...loc, + }); } - dequeue(nesting, file, name) { - this[kEmitMessage]('test:dequeue', { __proto__: null, nesting, file, name }); + dequeue(nesting, loc, name) { + this[kEmitMessage]('test:dequeue', { + __proto__: null, + nesting, + name, + ...loc, + }); } - start(nesting, file, name) { - this[kEmitMessage]('test:start', { __proto__: null, nesting, file, name }); + start(nesting, loc, name) { + this[kEmitMessage]('test:start', { + __proto__: null, + nesting, + name, + ...loc, + }); } - diagnostic(nesting, file, message) { - this[kEmitMessage]('test:diagnostic', { __proto__: null, nesting, file, message }); + diagnostic(nesting, loc, message) { + this[kEmitMessage]('test:diagnostic', { + __proto__: null, + nesting, + message, + ...loc, + }); } - stderr(file, message) { - this[kEmitMessage]('test:stderr', { __proto__: null, file, message }); + stderr(loc, message) { + this[kEmitMessage]('test:stderr', { __proto__: null, message, ...loc }); } - stdout(file, message) { - this[kEmitMessage]('test:stdout', { __proto__: null, file, message }); + stdout(loc, message) { + this[kEmitMessage]('test:stdout', { __proto__: null, message, ...loc }); } - coverage(nesting, file, summary) { - this[kEmitMessage]('test:coverage', { __proto__: null, nesting, file, summary }); + coverage(nesting, loc, summary) { + this[kEmitMessage]('test:coverage', { + __proto__: null, + nesting, + summary, + ...loc, + }); } end() { @@ -83,6 +129,8 @@ class TestsStream extends Readable { [kEmitMessage](type, data) { this.emit(type, data); + // Disabling as this going to the user-land + // eslint-disable-next-line node-core/set-proto-to-null-in-object this.#tryPush({ type, data }); } diff --git a/lib/internal/test_runner/utils.js b/lib/internal/test_runner/utils.js index 203d64c355bc63..326b6aba16ee5d 100644 --- a/lib/internal/test_runner/utils.js +++ b/lib/internal/test_runner/utils.js @@ -20,6 +20,7 @@ const { StringPrototypeSlice, } = primordials; +const { AsyncResource } = require('async_hooks'); const { basename, relative } = require('path'); const { createWriteStream } = require('fs'); const { pathToFileURL } = require('internal/url'); @@ -82,7 +83,7 @@ function createDeferredCallback() { resolve(); }; - return { promise, cb }; + return { __proto__: null, promise, cb }; } function isTestFailureError(err) { @@ -116,6 +117,7 @@ const kBuiltinReporters = new SafeMap([ ['spec', 'internal/test_runner/reporter/spec'], ['dot', 'internal/test_runner/reporter/dot'], ['tap', 'internal/test_runner/reporter/tap'], + ['junit', 'internal/test_runner/reporter/junit'], ]); const kDefaultReporter = process.stdout.isTTY ? 'spec' : 'tap'; @@ -168,15 +170,15 @@ async function getReportersMap(reporters, destinations, rootTest) { }); } - -async function setupTestReporters(rootTest) { +const reporterScope = new AsyncResource('TestReporterScope'); +const setupTestReporters = reporterScope.bind(async (rootTest) => { const { reporters, destinations } = parseCommandLine(); const reportersMap = await getReportersMap(reporters, destinations, rootTest); for (let i = 0; i < reportersMap.length; i++) { const { reporter, destination } = reportersMap[i]; compose(rootTest.reporter, reporter).pipe(destination); } -} +}); let globalTestOptions; @@ -419,6 +421,7 @@ module.exports = { isSupportedFileType, isTestFailureError, parseCommandLine, + reporterScope, setupTestReporters, getCoverageReport, }; diff --git a/lib/internal/url.js b/lib/internal/url.js index 9c11377aef1f24..8040aebf53ab86 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -22,6 +22,7 @@ const { ReflectOwnKeys, RegExpPrototypeSymbolReplace, SafeMap, + SafeSet, SafeWeakMap, StringPrototypeCharAt, StringPrototypeCharCodeAt, @@ -106,6 +107,40 @@ const searchParams = Symbol('query'); */ const internalSearchParams = new SafeWeakMap(); +// `unsafeProtocol`, `hostlessProtocol` and `slashedProtocol` is +// deliberately moved to `internal/url` rather than `url`. +// Workers does not bootstrap URL module. Therefore, `SafeSet` +// is not initialized on bootstrap. This case breaks the +// test-require-delete-array-iterator test. + +// Protocols that can allow "unsafe" and "unwise" chars. +const unsafeProtocol = new SafeSet([ + 'javascript', + 'javascript:', +]); +// Protocols that never have a hostname. +const hostlessProtocol = new SafeSet([ + 'javascript', + 'javascript:', +]); +// Protocols that always contain a // bit. +const slashedProtocol = new SafeSet([ + 'http', + 'http:', + 'https', + 'https:', + 'ftp', + 'ftp:', + 'gopher', + 'gopher:', + 'file', + 'file:', + 'ws', + 'ws:', + 'wss', + 'wss:', +]); + const updateActions = { kProtocol: 0, kHost: 1, @@ -623,6 +658,10 @@ function isURL(self) { class URL { constructor(input, base = undefined) { + if (arguments.length === 0) { + throw new ERR_MISSING_ARGS('url'); + } + // toUSVString is not needed. input = `${input}`; this[context] = new URLContext(); @@ -964,6 +1003,10 @@ class URL { } static canParse(url, base = undefined) { + if (arguments.length === 0) { + throw new ERR_MISSING_ARGS('url'); + } + url = `${url}`; if (base !== undefined) { @@ -1453,37 +1496,39 @@ const backslashRegEx = /\\/g; const newlineRegEx = /\n/g; const carriageReturnRegEx = /\r/g; const tabRegEx = /\t/g; +const questionRegex = /\?/g; +const hashRegex = /#/g; function encodePathChars(filepath) { - if (StringPrototypeIncludes(filepath, '%')) + if (StringPrototypeIndexOf(filepath, '%') !== -1) filepath = RegExpPrototypeSymbolReplace(percentRegEx, filepath, '%25'); // In posix, backslash is a valid character in paths: - if (!isWindows && StringPrototypeIncludes(filepath, '\\')) + if (!isWindows && StringPrototypeIndexOf(filepath, '\\') !== -1) filepath = RegExpPrototypeSymbolReplace(backslashRegEx, filepath, '%5C'); - if (StringPrototypeIncludes(filepath, '\n')) + if (StringPrototypeIndexOf(filepath, '\n') !== -1) filepath = RegExpPrototypeSymbolReplace(newlineRegEx, filepath, '%0A'); - if (StringPrototypeIncludes(filepath, '\r')) + if (StringPrototypeIndexOf(filepath, '\r') !== -1) filepath = RegExpPrototypeSymbolReplace(carriageReturnRegEx, filepath, '%0D'); - if (StringPrototypeIncludes(filepath, '\t')) + if (StringPrototypeIndexOf(filepath, '\t') !== -1) filepath = RegExpPrototypeSymbolReplace(tabRegEx, filepath, '%09'); return filepath; } function pathToFileURL(filepath) { - const outURL = new URL('file://'); if (isWindows && StringPrototypeStartsWith(filepath, '\\\\')) { + const outURL = new URL('file://'); // UNC path format: \\server\share\resource const hostnameEndIndex = StringPrototypeIndexOf(filepath, '\\', 2); if (hostnameEndIndex === -1) { throw new ERR_INVALID_ARG_VALUE( - 'filepath', + 'path', filepath, 'Missing UNC resource path', ); } if (hostnameEndIndex === 2) { throw new ERR_INVALID_ARG_VALUE( - 'filepath', + 'path', filepath, 'Empty UNC servername', ); @@ -1492,18 +1537,29 @@ function pathToFileURL(filepath) { outURL.hostname = domainToASCII(hostname); outURL.pathname = encodePathChars( RegExpPrototypeSymbolReplace(backslashRegEx, StringPrototypeSlice(filepath, hostnameEndIndex), '/')); - } else { - let resolved = path.resolve(filepath); - // path.resolve strips trailing slashes so we must add them back - const filePathLast = StringPrototypeCharCodeAt(filepath, - filepath.length - 1); - if ((filePathLast === CHAR_FORWARD_SLASH || - (isWindows && filePathLast === CHAR_BACKWARD_SLASH)) && - resolved[resolved.length - 1] !== path.sep) - resolved += '/'; - outURL.pathname = encodePathChars(resolved); + return outURL; } - return outURL; + let resolved = path.resolve(filepath); + // path.resolve strips trailing slashes so we must add them back + const filePathLast = StringPrototypeCharCodeAt(filepath, + filepath.length - 1); + if ((filePathLast === CHAR_FORWARD_SLASH || + (isWindows && filePathLast === CHAR_BACKWARD_SLASH)) && + resolved[resolved.length - 1] !== path.sep) + resolved += '/'; + + // Call encodePathChars first to avoid encoding % again for ? and #. + resolved = encodePathChars(resolved); + + // Question and hash character should be included in pathname. + // Therefore, encoding is required to eliminate parsing them in different states. + // This is done as an optimization to not creating a URL instance and + // later triggering pathname setter, which impacts performance + if (StringPrototypeIndexOf(resolved, '?') !== -1) + resolved = RegExpPrototypeSymbolReplace(questionRegex, resolved, '%3F'); + if (StringPrototypeIndexOf(resolved, '#') !== -1) + resolved = RegExpPrototypeSymbolReplace(hashRegex, resolved, '%23'); + return new URL(`file://${resolved}`); } function toPathIfFileURL(fileURLOrPath) { @@ -1526,4 +1582,7 @@ module.exports = { isURL, urlUpdateActions: updateActions, + unsafeProtocol, + hostlessProtocol, + slashedProtocol, }; diff --git a/lib/internal/util.js b/lib/internal/util.js index 2a366f3454049b..aedfa2e98896e7 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -63,6 +63,7 @@ const { toUSVString: _toUSVString, } = internalBinding('util'); const { isNativeError } = internalBinding('types'); +const { getOptionValue } = require('internal/options'); const noCrypto = !process.versions.openssl; @@ -106,10 +107,52 @@ const codesWarned = new SafeSet(); let validateString; +function getDeprecationWarningEmitter( + code, msg, deprecated, useEmitSync, + shouldEmitWarning = () => true, +) { + let warned = false; + return function() { + if (!warned && shouldEmitWarning()) { + warned = true; + if (code !== undefined) { + if (!codesWarned.has(code)) { + const emitWarning = useEmitSync ? + require('internal/process/warning').emitWarningSync : + process.emitWarning; + emitWarning(msg, 'DeprecationWarning', code, deprecated); + codesWarned.add(code); + } + } else { + process.emitWarning(msg, 'DeprecationWarning', deprecated); + } + } + }; +} + +function isPendingDeprecation() { + return getOptionValue('--pending-deprecation') && + !getOptionValue('--no-deprecation'); +} + +// Internal deprecator for pending --pending-deprecation. This can be invoked +// at snapshot building time as the warning permission is only queried at +// run time. +function pendingDeprecate(fn, msg, code) { + const emitDeprecationWarning = getDeprecationWarningEmitter( + code, msg, deprecated, false, isPendingDeprecation, + ); + function deprecated(...args) { + emitDeprecationWarning(); + return ReflectApply(fn, this, args); + } + return deprecated; +} + // Mark that a method should not be used. // Returns a modified function which warns once by default. // If --no-deprecation is set, then it is a no-op. -function deprecate(fn, msg, code) { +function deprecate(fn, msg, code, useEmitSync) { if (process.noDeprecation === true) { return fn; } @@ -121,19 +164,12 @@ function deprecate(fn, msg, code) { if (code !== undefined) validateString(code, 'code'); - let warned = false; + const emitDeprecationWarning = getDeprecationWarningEmitter( + code, msg, deprecated, useEmitSync, + ); + function deprecated(...args) { - if (!warned) { - warned = true; - if (code !== undefined) { - if (!codesWarned.has(code)) { - process.emitWarning(msg, 'DeprecationWarning', code, deprecated); - codesWarned.add(code); - } - } else { - process.emitWarning(msg, 'DeprecationWarning', deprecated); - } - } + emitDeprecationWarning(); if (new.target) { return ReflectConstruct(fn, args, new.target); } @@ -321,6 +357,36 @@ function getConstructorOf(obj) { return null; } +let cachedURL; +let cachedCWD; + +/** + * Get the current working directory while accounting for the possibility that it has been deleted. + * `process.cwd()` can fail if the parent directory is deleted while the process runs. + * @returns {URL} The current working directory or the volume root if it cannot be determined. + */ +function getCWDURL() { + const { sep } = require('path'); + const { pathToFileURL } = require('internal/url'); + + let cwd; + + try { + // The implementation of `process.cwd()` already uses proper cache when it can. + // It's a relatively cheap call performance-wise for the most common use case. + cwd = process.cwd(); + } catch { + cachedURL ??= pathToFileURL(sep); + } + + if (cwd != null && cwd !== cachedCWD) { + cachedURL = pathToFileURL(cwd + sep); + cachedCWD = cwd; + } + + return cachedURL; +} + function getSystemErrorName(err) { const entry = uvErrmapGet(err); return entry ? entry[0] : `Unknown system error ${err}`; @@ -509,6 +575,90 @@ function exposeInterface(target, name, interfaceObject) { }); } +function defineLazyProperties(target, id, keys, enumerable = true) { + const descriptors = { __proto__: null }; + let mod; + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + let lazyLoadedValue; + function set(value) { + ObjectDefineProperty(target, key, { + __proto__: null, + writable: true, + value, + }); + } + ObjectDefineProperty(set, 'name', { + __proto__: null, + value: `set ${key}`, + }); + function get() { + mod ??= require(id); + if (lazyLoadedValue === undefined) { + lazyLoadedValue = mod[key]; + set(lazyLoadedValue); + } + return lazyLoadedValue; + } + ObjectDefineProperty(get, 'name', { + __proto__: null, + value: `get ${key}`, + }); + descriptors[key] = { + __proto__: null, + configurable: true, + enumerable, + get, + set, + }; + } + ObjectDefineProperties(target, descriptors); +} + +function defineReplaceableLazyAttribute(target, id, keys, writable = true) { + let mod; + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + let value; + let setterCalled = false; + + function get() { + if (setterCalled) { + return value; + } + mod ??= require(id); + value ??= mod[key]; + return value; + } + + ObjectDefineProperty(get, 'name', { + __proto__: null, + value: `get ${key}`, + }); + + function set(val) { + setterCalled = true; + value = val; + } + ObjectDefineProperty(set, 'name', { + __proto__: null, + value: `set ${key}`, + }); + + ObjectDefineProperty(target, key, { + __proto__: null, + enumerable: true, + configurable: true, + get, + set: writable ? set : undefined, + }); + } +} + +function exposeLazyInterfaces(target, id, keys) { + defineLazyProperties(target, id, keys, false); +} + let _DOMException; const lazyDOMExceptionClass = () => { _DOMException ??= internalBinding('messaging').DOMException; @@ -607,6 +757,24 @@ function isArrayBufferDetached(value) { return false; } +/** + * Helper function to lazy-load an initialize-once value. + * @template T Return value of initializer + * @param {()=>T} initializer Initializer of the lazily loaded value. + * @returns {()=>T} + */ +function getLazy(initializer) { + let value; + let initialized = false; + return function() { + if (initialized === false) { + value = initializer(); + initialized = true; + } + return value; + }; +} + // Setup user-facing NODE_V8_COVERAGE environment variable that writes // ScriptCoverage objects to a specified directory. function setupCoverageHooks(dir) { @@ -629,6 +797,7 @@ function setupCoverageHooks(dir) { } module.exports = { + getLazy, assertCrypto, cachedResult, convertToValidSignal, @@ -636,12 +805,16 @@ module.exports = { createDeferredPromise, decorateErrorStack, defineOperation, + defineLazyProperties, + defineReplaceableLazyAttribute, deprecate, emitExperimentalWarning, exposeInterface, + exposeLazyInterfaces, filterDuplicateStrings, filterOwnProperties, getConstructorOf, + getCWDURL, getInternalGlobal, getSystemErrorMap, getSystemErrorName, @@ -678,4 +851,5 @@ module.exports = { kEmptyObject, kEnumerableProperty, setOwnProperty, + pendingDeprecate, }; diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index bc5ea4b31a2ad5..760498f22f2080 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -151,7 +151,7 @@ const { const assert = require('internal/assert'); -const { BuiltinModule } = require('internal/bootstrap/loaders'); +const { BuiltinModule } = require('internal/bootstrap/realm'); const { validateObject, validateString, diff --git a/lib/internal/util/inspector.js b/lib/internal/util/inspector.js index f5cba165fc0f32..0d9580c83224e4 100644 --- a/lib/internal/util/inspector.js +++ b/lib/internal/util/inspector.js @@ -66,7 +66,7 @@ function installConsoleExtensions(commandLineApi) { if (commandLineApi.require) { return; } const { tryGetCwd } = require('internal/process/execution'); const CJSModule = require('internal/modules/cjs/loader').Module; - const { makeRequireFunction } = require('internal/modules/cjs/helpers'); + const { makeRequireFunction } = require('internal/modules/helpers'); const consoleAPIModule = new CJSModule(''); const cwd = tryGetCwd(); consoleAPIModule.paths = []; diff --git a/lib/internal/vm.js b/lib/internal/vm.js index 4f87ce87cc29a2..b14ba13e7e4cfb 100644 --- a/lib/internal/vm.js +++ b/lib/internal/vm.js @@ -97,12 +97,11 @@ function internalCompileFunction(code, params, options) { if (importModuleDynamically !== undefined) { validateFunction(importModuleDynamically, 'options.importModuleDynamically'); - const { importModuleDynamicallyWrap } = - require('internal/vm/module'); - const { callbackMap } = internalBinding('module_wrap'); + const { importModuleDynamicallyWrap } = require('internal/vm/module'); const wrapped = importModuleDynamicallyWrap(importModuleDynamically); const func = result.function; - callbackMap.set(result.cacheKey, { + const { setCallbackForWrap } = require('internal/modules/esm/utils'); + setCallbackForWrap(result.cacheKey, { importModuleDynamically: (s, _k, i) => wrapped(s, func, i), }); } diff --git a/lib/internal/vm/module.js b/lib/internal/vm/module.js index 109b2d7e5b650c..19d93e1abfbd42 100644 --- a/lib/internal/vm/module.js +++ b/lib/internal/vm/module.js @@ -125,8 +125,8 @@ class Module { this[kWrap] = new ModuleWrap(identifier, context, sourceText, options.lineOffset, options.columnOffset, options.cachedData); - - binding.callbackMap.set(this[kWrap], { + const { setCallbackForWrap } = require('internal/modules/esm/utils'); + setCallbackForWrap(this[kWrap], { initializeImportMeta: options.initializeImportMeta, importModuleDynamically: options.importModuleDynamically ? importModuleDynamicallyWrap(options.importModuleDynamically) : @@ -302,8 +302,8 @@ class SourceTextModule extends Module { this[kLink] = async (linker) => { this.#statusOverride = 'linking'; - const promises = this[kWrap].link(async (identifier, assert) => { - const module = await linker(identifier, this, { assert }); + const promises = this[kWrap].link(async (identifier, attributes) => { + const module = await linker(identifier, this, { attributes, assert: attributes }); if (module[kWrap] === undefined) { throw new ERR_VM_MODULE_NOT_MODULE(); } diff --git a/lib/internal/watch_mode/files_watcher.js b/lib/internal/watch_mode/files_watcher.js index 848c17f4115616..b38f94d7cc8051 100644 --- a/lib/internal/watch_mode/files_watcher.js +++ b/lib/internal/watch_mode/files_watcher.js @@ -24,19 +24,19 @@ const supportsRecursiveWatching = process.platform === 'win32' || class FilesWatcher extends EventEmitter { #watchers = new SafeMap(); #filteredFiles = new SafeSet(); - #throttling = new SafeSet(); + #debouncing = new SafeSet(); #depencencyOwners = new SafeMap(); #ownerDependencies = new SafeMap(); - #throttle; + #debounce; #mode; #signal; - constructor({ throttle = 500, mode = 'filter', signal } = kEmptyObject) { + constructor({ debounce = 200, mode = 'filter', signal } = kEmptyObject) { super(); - validateNumber(throttle, 'options.throttle', 0, TIMEOUT_MAX); + validateNumber(debounce, 'options.debounce', 0, TIMEOUT_MAX); validateOneOf(mode, 'options.mode', ['filter', 'all']); - this.#throttle = throttle; + this.#debounce = debounce; this.#mode = mode; this.#signal = signal; @@ -74,16 +74,18 @@ class FilesWatcher extends EventEmitter { } #onChange(trigger) { - if (this.#throttling.has(trigger)) { + if (this.#debouncing.has(trigger)) { return; } if (this.#mode === 'filter' && !this.#filteredFiles.has(trigger)) { return; } - this.#throttling.add(trigger); + this.#debouncing.add(trigger); const owners = this.#depencencyOwners.get(trigger); - this.emit('changed', { owners }); - setTimeout(() => this.#throttling.delete(trigger), this.#throttle).unref(); + setTimeout(() => { + this.#debouncing.delete(trigger); + this.emit('changed', { owners }); + }, this.#debounce).unref(); } get watchedPaths() { diff --git a/lib/internal/webstreams/queuingstrategies.js b/lib/internal/webstreams/queuingstrategies.js index df114a44cc8adc..ee4169106838c3 100644 --- a/lib/internal/webstreams/queuingstrategies.js +++ b/lib/internal/webstreams/queuingstrategies.js @@ -78,7 +78,7 @@ class ByteLengthQueuingStrategy { constructor(init) { validateObject(init, 'init'); if (init.highWaterMark === undefined) - throw new ERR_MISSING_OPTION('options.highWaterMark'); + throw new ERR_MISSING_OPTION('init.highWaterMark'); // The highWaterMark value is not checked until the strategy // is actually used, per the spec. @@ -133,7 +133,7 @@ class CountQueuingStrategy { constructor(init) { validateObject(init, 'init'); if (init.highWaterMark === undefined) - throw new ERR_MISSING_OPTION('options.highWaterMark'); + throw new ERR_MISSING_OPTION('init.highWaterMark'); // The highWaterMark value is not checked until the strategy // is actually used, per the spec. diff --git a/lib/internal/webstreams/readablestream.js b/lib/internal/webstreams/readablestream.js index 5e312d2a8f45ea..2f1eb6cc8e6c8c 100644 --- a/lib/internal/webstreams/readablestream.js +++ b/lib/internal/webstreams/readablestream.js @@ -130,6 +130,8 @@ const { writableStreamDefaultWriterWrite, } = require('internal/webstreams/writablestream'); +const { Buffer } = require('buffer'); + const assert = require('internal/assert'); const kCancel = Symbol('kCancel'); @@ -138,6 +140,7 @@ const kChunk = Symbol('kChunk'); const kError = Symbol('kError'); const kPull = Symbol('kPull'); const kRelease = Symbol('kRelease'); +const kSkipThrow = Symbol('kSkipThrow'); let releasedError; let releasingError; @@ -670,8 +673,10 @@ TransferredReadableStream.prototype[kDeserialize] = () => {}; class ReadableStreamBYOBRequest { [kType] = 'ReadableStreamBYOBRequest'; - constructor() { - throw new ERR_ILLEGAL_CONSTRUCTOR(); + constructor(skipThrowSymbol = undefined) { + if (skipThrowSymbol !== kSkipThrow) { + throw new ERR_ILLEGAL_CONSTRUCTOR(); + } } /** @@ -753,17 +758,14 @@ ObjectDefineProperties(ReadableStreamBYOBRequest.prototype, { }); function createReadableStreamBYOBRequest(controller, view) { - return ReflectConstruct( - function() { - this[kType] = 'ReadableStreamBYOBRequest'; - this[kState] = { - controller, - view, - }; - }, - [], - ReadableStreamBYOBRequest, - ); + const stream = new ReadableStreamBYOBRequest(kSkipThrow); + + stream[kState] = { + controller, + view, + }; + + return stream; } class DefaultReadRequest { @@ -1013,9 +1015,12 @@ ObjectDefineProperties(ReadableStreamBYOBReader.prototype, { class ReadableStreamDefaultController { [kType] = 'ReadableStreamDefaultController'; + [kState] = {}; - constructor() { - throw new ERR_ILLEGAL_CONSTRUCTOR(); + constructor(skipThrowSymbol = undefined) { + if (skipThrowSymbol !== kSkipThrow) { + throw new ERR_ILLEGAL_CONSTRUCTOR(); + } } /** @@ -1071,22 +1076,14 @@ ObjectDefineProperties(ReadableStreamDefaultController.prototype, { [SymbolToStringTag]: getNonWritablePropertyDescriptor(ReadableStreamDefaultController.name), }); -function createReadableStreamDefaultController() { - return ReflectConstruct( - function() { - this[kType] = 'ReadableStreamDefaultController'; - this[kState] = {}; - }, - [], - ReadableStreamDefaultController, - ); -} - class ReadableByteStreamController { [kType] = 'ReadableByteStreamController'; + [kState] = {}; - constructor() { - throw new ERR_ILLEGAL_CONSTRUCTOR(); + constructor(skipThrowSymbol = undefined) { + if (skipThrowSymbol !== kSkipThrow) { + throw new ERR_ILLEGAL_CONSTRUCTOR(); + } } /** @@ -1197,17 +1194,6 @@ ObjectDefineProperties(ReadableByteStreamController.prototype, { [SymbolToStringTag]: getNonWritablePropertyDescriptor(ReadableByteStreamController.name), }); -function createReadableByteStreamController() { - return ReflectConstruct( - function() { - this[kType] = 'ReadableByteStreamController'; - this[kState] = {}; - }, - [], - ReadableByteStreamController, - ); -} - function createTeeReadableStream(start, pull, cancel) { return ReflectConstruct( function() { @@ -1862,6 +1848,11 @@ function readableByteStreamControllerConvertPullIntoDescriptor(desc) { throw new ERR_INVALID_STATE.RangeError('The buffer size is invalid'); assert(!(bytesFilled % elementSize)); const transferredBuffer = transferArrayBuffer(buffer); + + if (ctor === Buffer) { + return Buffer.from(transferredBuffer, byteOffset, bytesFilled / elementSize); + } + return new ctor(transferredBuffer, byteOffset, bytesFilled / elementSize); } @@ -2357,7 +2348,7 @@ function setupReadableStreamDefaultControllerFromSource( source, highWaterMark, sizeAlgorithm) { - const controller = createReadableStreamDefaultController(); + const controller = new ReadableStreamDefaultController(kSkipThrow); const start = source?.start; const pull = source?.pull; const cancel = source?.cancel; @@ -3155,7 +3146,7 @@ function setupReadableByteStreamControllerFromSource( stream, source, highWaterMark) { - const controller = createReadableByteStreamController(); + const controller = new ReadableByteStreamController(kSkipThrow); const start = source?.start; const pull = source?.pull; const cancel = source?.cancel; diff --git a/lib/internal/webstreams/transformstream.js b/lib/internal/webstreams/transformstream.js index 3a7fbebc042a22..bcccf90af91a0f 100644 --- a/lib/internal/webstreams/transformstream.js +++ b/lib/internal/webstreams/transformstream.js @@ -8,6 +8,7 @@ const { PromiseResolve, ReflectConstruct, SymbolToStringTag, + Symbol, } = primordials; const { @@ -65,6 +66,8 @@ const { const assert = require('internal/assert'); +const kSkipThrow = Symbol('kSkipThrow'); + const getNonWritablePropertyDescriptor = (value) => { return { __proto__: null, @@ -269,8 +272,10 @@ TransferredTransformStream.prototype[kDeserialize] = () => {}; class TransformStreamDefaultController { [kType] = 'TransformStreamDefaultController'; - constructor() { - throw new ERR_ILLEGAL_CONSTRUCTOR(); + constructor(skipThrowSymbol = undefined) { + if (skipThrowSymbol !== kSkipThrow) { + throw new ERR_ILLEGAL_CONSTRUCTOR(); + } } /** @@ -331,15 +336,6 @@ ObjectDefineProperties(TransformStreamDefaultController.prototype, { [SymbolToStringTag]: getNonWritablePropertyDescriptor(TransformStreamDefaultController.name), }); -function createTransformStreamDefaultController() { - return ReflectConstruct( - function() { - this[kType] = 'TransformStreamDefaultController'; - }, - [], - TransformStreamDefaultController); -} - const isTransformStream = isBrandCheck('TransformStream'); const isTransformStreamDefaultController = @@ -454,7 +450,7 @@ function setupTransformStreamDefaultController( function setupTransformStreamDefaultControllerFromTransformer( stream, transformer) { - const controller = createTransformStreamDefaultController(); + const controller = new TransformStreamDefaultController(kSkipThrow); const transform = transformer?.transform || defaultTransformAlgorithm; const flush = transformer?.flush || nonOpFlush; const transformAlgorithm = diff --git a/lib/internal/webstreams/writablestream.js b/lib/internal/webstreams/writablestream.js index b0eb5f20abb80e..44810d533c7092 100644 --- a/lib/internal/webstreams/writablestream.js +++ b/lib/internal/webstreams/writablestream.js @@ -81,6 +81,7 @@ const assert = require('internal/assert'); const kAbort = Symbol('kAbort'); const kCloseSentinel = Symbol('kCloseSentinel'); const kError = Symbol('kError'); +const kSkipThrow = Symbol('kSkipThrow'); let releasedError; @@ -523,8 +524,10 @@ ObjectDefineProperties(WritableStreamDefaultWriter.prototype, { class WritableStreamDefaultController { [kType] = 'WritableStreamDefaultController'; - constructor() { - throw new ERR_ILLEGAL_CONSTRUCTOR(); + constructor(skipThrowSymbol = undefined) { + if (skipThrowSymbol !== kSkipThrow) { + throw new ERR_ILLEGAL_CONSTRUCTOR(); + } } [kAbort](reason) { @@ -570,14 +573,6 @@ ObjectDefineProperties(WritableStreamDefaultController.prototype, { [SymbolToStringTag]: getNonWritablePropertyDescriptor(WritableStreamDefaultController.name), }); -function createWritableStreamDefaultController() { - return ReflectConstruct( - function() { - this[kType] = 'WritableStreamDefaultController'; - }, - [], WritableStreamDefaultController); -} - const isWritableStream = isBrandCheck('WritableStream'); const isWritableStreamDefaultWriter = @@ -1234,7 +1229,7 @@ function setupWritableStreamDefaultControllerFromSink( sink, highWaterMark, sizeAlgorithm) { - const controller = createWritableStreamDefaultController(); + const controller = new WritableStreamDefaultController(kSkipThrow); const start = sink?.start; const write = sink?.write; const close = sink?.close; diff --git a/lib/internal/worker.js b/lib/internal/worker.js index 3d828d2f6f2b19..98067387249627 100644 --- a/lib/internal/worker.js +++ b/lib/internal/worker.js @@ -44,6 +44,7 @@ const { getOptionValue } = require('internal/options'); const workerIo = require('internal/worker/io'); const { drainMessagePort, + receiveMessageOnPort, MessageChannel, messageTypes, kPort, @@ -81,6 +82,7 @@ const kOnCouldNotSerializeErr = Symbol('kOnCouldNotSerializeErr'); const kOnErrorMessage = Symbol('kOnErrorMessage'); const kParentSideStdio = Symbol('kParentSideStdio'); const kLoopStartTime = Symbol('kLoopStartTime'); +const kIsInternal = Symbol('kIsInternal'); const kIsOnline = Symbol('kIsOnline'); const SHARE_ENV = SymbolFor('nodejs.worker_threads.SHARE_ENV'); @@ -124,7 +126,13 @@ function assignEnvironmentData(data) { class Worker extends EventEmitter { constructor(filename, options = kEmptyObject) { super(); - debug(`[${threadId}] create new worker`, filename, options); + const isInternal = arguments[2] === kIsInternal; + debug( + `[${threadId}] create new worker`, + filename, + options, + `isInternal: ${isInternal}`, + ); if (options.execArgv) validateArray(options.execArgv, 'options.execArgv'); @@ -135,7 +143,10 @@ class Worker extends EventEmitter { } let url, doEval; - if (options.eval) { + if (isInternal) { + doEval = 'internal'; + url = `node:${filename}`; + } else if (options.eval) { if (typeof filename !== 'string') { throw new ERR_INVALID_ARG_VALUE( 'options.eval', @@ -191,12 +202,14 @@ class Worker extends EventEmitter { name = StringPrototypeTrim(options.name); } + debug('instantiating Worker.', `url: ${url}`, `doEval: ${doEval}`); // Set up the C++ handle for the worker, as well as some internal wiring. this[kHandle] = new WorkerImpl(url, env === process.env ? null : env, options.execArgv, parseResourceLimits(options.resourceLimits), !!(options.trackUnmanagedFds ?? true), + isInternal, name); if (this[kHandle].invalidExecArgv) { throw new ERR_WORKER_INVALID_EXEC_ARGV(this[kHandle].invalidExecArgv); @@ -248,6 +261,7 @@ class Worker extends EventEmitter { type: messageTypes.LOAD_SCRIPT, filename, doEval, + isInternal, cwdCounter: cwdCounter || workerIo.sharedCwdCounter, workerData: options.workerData, environmentData, @@ -428,6 +442,20 @@ class Worker extends EventEmitter { } } +/** + * A worker which has an internal module for entry point (e.g. internal/module/esm/worker). + * Internal workers bypass the permission model. + */ +class InternalWorker extends Worker { + constructor(filename, options) { + super(filename, options, kIsInternal); + } + + receiveMessageSync() { + return receiveMessageOnPort(this[kPublicPort]); + } +} + function pipeWithoutWarning(source, dest) { const sourceMaxListeners = source._maxListeners; const destMaxListeners = dest._maxListeners; @@ -508,6 +536,7 @@ function eventLoopUtilization(util1, util2) { module.exports = { ownsProcessState, + kIsOnline, isMainThread, SHARE_ENV, resourceLimits: @@ -516,5 +545,6 @@ module.exports = { getEnvironmentData, assignEnvironmentData, threadId, + InternalWorker, Worker, }; diff --git a/lib/internal/worker/io.js b/lib/internal/worker/io.js index 4e32422a5e7720..eb545885b80e5e 100644 --- a/lib/internal/worker/io.js +++ b/lib/internal/worker/io.js @@ -22,6 +22,7 @@ const { const { kEmptyObject, kEnumerableProperty, + setOwnProperty, } = require('internal/util'); const { @@ -302,15 +303,15 @@ function setupPortReferencing(port, eventEmitter, eventName) { if (name === eventName) removeListener(eventEmitter.listenerCount(name)); }); const origNewListener = eventEmitter[kNewListener]; - eventEmitter[kNewListener] = function(size, type, ...args) { + setOwnProperty(eventEmitter, kNewListener, function(size, type, ...args) { if (type === eventName) newListener(size - 1); return ReflectApply(origNewListener, this, arguments); - }; + }); const origRemoveListener = eventEmitter[kRemoveListener]; - eventEmitter[kRemoveListener] = function(size, type, ...args) { + setOwnProperty(eventEmitter, kRemoveListener, function(size, type, ...args) { if (type === eventName) removeListener(size); return ReflectApply(origRemoveListener, this, arguments); - }; + }); function newListener(size) { if (size === 0) { diff --git a/lib/module.js b/lib/module.js index b4a6dd7d18de56..ee90e92f53093c 100644 --- a/lib/module.js +++ b/lib/module.js @@ -2,8 +2,10 @@ const { findSourceMap } = require('internal/source_map/source_map_cache'); const { Module } = require('internal/modules/cjs/loader'); +const { register } = require('internal/modules/esm/loader'); const { SourceMap } = require('internal/source_map/source_map'); Module.findSourceMap = findSourceMap; +Module.register = register; Module.SourceMap = SourceMap; module.exports = Module; diff --git a/lib/net.js b/lib/net.js index f351fd00feb0e8..da40ba28d59414 100644 --- a/lib/net.js +++ b/lib/net.js @@ -265,7 +265,7 @@ function getDefaultAutoSelectFamilyAttemptTimeout() { function setDefaultAutoSelectFamilyAttemptTimeout(value) { validateInt32(value, 'value', 1); - if (value < 1) { + if (value < 10) { value = 10; } diff --git a/lib/repl.js b/lib/repl.js index 8109595b119a8b..b2d143619ae093 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -62,6 +62,7 @@ const { Boolean, Error, FunctionPrototypeBind, + JSONStringify, MathMaxApply, NumberIsNaN, NumberParseFloat, @@ -97,15 +98,17 @@ const { globalThis, } = primordials; -const { BuiltinModule } = require('internal/bootstrap/loaders'); +const { BuiltinModule } = require('internal/bootstrap/realm'); const { makeRequireFunction, addBuiltinLibsToObject, -} = require('internal/modules/cjs/helpers'); +} = require('internal/modules/helpers'); const { isIdentifierStart, isIdentifierChar, + parse: acornParse, } = require('internal/deps/acorn/acorn/dist/acorn'); +const acornWalk = require('internal/deps/acorn/acorn-walk/dist/walk'); const { decorateErrorStack, isError, @@ -225,6 +228,28 @@ module.paths = CJSModule._nodeModulePaths(module.filename); const writer = (obj) => inspect(obj, writer.options); writer.options = { ...inspect.defaultOptions, showProxy: true }; +// Converts static import statement to dynamic import statement +const toDynamicImport = (codeLine) => { + let dynamicImportStatement = ''; + const ast = acornParse(codeLine, { __proto__: null, sourceType: 'module', ecmaVersion: 'latest' }); + acornWalk.ancestor(ast, { + ImportDeclaration(node) { + const awaitDynamicImport = `await import(${JSONStringify(node.source.value)});`; + if (node.specifiers.length === 0) { + dynamicImportStatement += awaitDynamicImport; + } else if (node.specifiers.length === 1 && node.specifiers[0].type === 'ImportNamespaceSpecifier') { + dynamicImportStatement += `const ${node.specifiers[0].local.name} = ${awaitDynamicImport}`; + } else { + const importNames = ArrayPrototypeJoin(ArrayPrototypeMap(node.specifiers, ({ local, imported }) => + (local.name === imported?.name ? local.name : `${imported?.name ?? 'default'}: ${local.name}`), + ), ', '); + dynamicImportStatement += `const { ${importNames} } = ${awaitDynamicImport}`; + } + }, + }); + return dynamicImportStatement; +}; + function REPLServer(prompt, stream, eval_, @@ -458,9 +483,9 @@ function REPLServer(prompt, vm.createScript(fallbackCode, { filename: file, displayErrors: true, - importModuleDynamically: (specifier, _, importAssertions) => { + importModuleDynamically: (specifier, _, importAttributes) => { return asyncESM.esmLoader.import(specifier, parentURL, - importAssertions); + importAttributes); }, }); } catch (fallbackError) { @@ -502,9 +527,9 @@ function REPLServer(prompt, script = vm.createScript(code, { filename: file, displayErrors: true, - importModuleDynamically: (specifier, _, importAssertions) => { + importModuleDynamically: (specifier, _, importAttributes) => { return asyncESM.esmLoader.import(specifier, parentURL, - importAssertions); + importAttributes); }, }); } catch (e) { @@ -686,7 +711,7 @@ function REPLServer(prompt, 'module'; if (StringPrototypeIncludes(e.message, importErrorStr)) { e.message = 'Cannot use import statement inside the Node.js ' + - 'REPL, alternatively use dynamic import'; + 'REPL, alternatively use dynamic import: ' + toDynamicImport(self.lines.at(-1)); e.stack = SideEffectFreeRegExpPrototypeSymbolReplace( /SyntaxError:.*\n/, e.stack, diff --git a/lib/test.js b/lib/test.js index dc4045622a8284..d096cae23d5357 100644 --- a/lib/test.js +++ b/lib/test.js @@ -23,7 +23,7 @@ ObjectDefineProperty(module.exports, 'mock', { enumerable: true, get() { if (lazyMock === undefined) { - const { MockTracker } = require('internal/test_runner/mock'); + const { MockTracker } = require('internal/test_runner/mock/mock'); lazyMock = new MockTracker(); } diff --git a/lib/test/reporters.js b/lib/test/reporters.js index 287c07510bc13a..06a0b27ee58275 100644 --- a/lib/test/reporters.js +++ b/lib/test/reporters.js @@ -1,8 +1,9 @@ 'use strict'; -const { ObjectDefineProperties } = primordials; +const { ObjectDefineProperties, ReflectConstruct } = primordials; let dot; +let junit; let spec; let tap; @@ -17,13 +18,22 @@ ObjectDefineProperties(module.exports, { return dot; }, }, - spec: { + junit: { __proto__: null, configurable: true, enumerable: true, get() { + junit ??= require('internal/test_runner/reporter/junit'); + return junit; + }, + }, + spec: { + __proto__: null, + configurable: true, + enumerable: true, + value: function value() { spec ??= require('internal/test_runner/reporter/spec'); - return spec; + return ReflectConstruct(spec, arguments); }, }, tap: { diff --git a/lib/timers/promises.js b/lib/timers/promises.js index d224520f10694d..2bf36d6cc51700 100644 --- a/lib/timers/promises.js +++ b/lib/timers/promises.js @@ -40,6 +40,7 @@ const { } = require('internal/util'); const kScheduler = Symbol('kScheduler'); +let kResistStopPropagation; function cancelListenerHandler(clear, reject, signal) { if (!this._destroyed) { @@ -81,7 +82,8 @@ function setTimeout(after, value, options = kEmptyObject) { if (signal) { oncancel = FunctionPrototypeBind(cancelListenerHandler, timeout, clearTimeout, reject, signal); - signal.addEventListener('abort', oncancel); + kResistStopPropagation ??= require('internal/event_target').kResistStopPropagation; + signal.addEventListener('abort', oncancel, { __proto__: null, [kResistStopPropagation]: true }); } }); return oncancel !== undefined ? @@ -123,7 +125,8 @@ function setImmediate(value, options = kEmptyObject) { oncancel = FunctionPrototypeBind(cancelListenerHandler, immediate, clearImmediate, reject, signal); - signal.addEventListener('abort', oncancel); + kResistStopPropagation ??= require('internal/event_target').kResistStopPropagation; + signal.addEventListener('abort', oncancel, { __proto__: null, [kResistStopPropagation]: true }); } }); return oncancel !== undefined ? @@ -164,7 +167,8 @@ async function* setInterval(after, value, options = kEmptyObject) { callback = undefined; } }; - signal.addEventListener('abort', onCancel, { once: true }); + kResistStopPropagation ??= require('internal/event_target').kResistStopPropagation; + signal.addEventListener('abort', onCancel, { __proto__: null, once: true, [kResistStopPropagation]: true }); } while (!signal?.aborted) { diff --git a/lib/url.js b/lib/url.js index 2b32a7e8bc8843..5b30f11677e154 100644 --- a/lib/url.js +++ b/lib/url.js @@ -26,7 +26,6 @@ const { Int8Array, ObjectCreate, ObjectKeys, - SafeSet, StringPrototypeCharCodeAt, decodeURIComponent, } = primordials; @@ -55,8 +54,11 @@ const { domainToASCII, domainToUnicode, fileURLToPath, - pathToFileURL, + pathToFileURL: _pathToFileURL, urlToHttpOptions, + unsafeProtocol, + hostlessProtocol, + slashedProtocol, } = require('internal/url'); const bindingUrl = internalBinding('url'); @@ -92,33 +94,6 @@ const hostPattern = /^\/\/[^@/]+@[^@/]+/; const simplePathPattern = /^(\/\/?(?!\/)[^?\s]*)(\?[^\s]*)?$/; const hostnameMaxLen = 255; -// Protocols that can allow "unsafe" and "unwise" chars. -const unsafeProtocol = new SafeSet([ - 'javascript', - 'javascript:', -]); -// Protocols that never have a hostname. -const hostlessProtocol = new SafeSet([ - 'javascript', - 'javascript:', -]); -// Protocols that always contain a // bit. -const slashedProtocol = new SafeSet([ - 'http', - 'http:', - 'https', - 'https:', - 'ftp', - 'ftp:', - 'gopher', - 'gopher:', - 'file', - 'file:', - 'ws', - 'ws:', - 'wss', - 'wss:', -]); const { CHAR_SPACE, CHAR_TAB, @@ -1034,6 +1009,15 @@ Url.prototype.parseHost = function parseHost() { if (host) this.hostname = host; }; +// When used internally, we are not obligated to associate TypeError with +// this function, so non-strings can be rejected by underlying implementation. +// Public API has to validate input and throw appropriate error. +function pathToFileURL(path) { + validateString(path, 'path'); + + return _pathToFileURL(path); +} + module.exports = { // Original API Url, diff --git a/lib/util.js b/lib/util.js index f71089c6b4e6dc..7fb7994e6536ba 100644 --- a/lib/util.js +++ b/lib/util.js @@ -62,13 +62,10 @@ const { stripVTControlCharacters, } = require('internal/util/inspect'); const { debuglog } = require('internal/util/debuglog'); -const { parseArgs } = require('internal/util/parse_args/parse_args'); const { validateFunction, validateNumber, } = require('internal/validators'); -const { TextDecoder, TextEncoder } = require('internal/encoding'); -const { MIMEType, MIMEParams } = require('internal/mime'); const { isBuffer } = require('buffer').Buffer; const types = require('internal/util/types'); @@ -78,6 +75,7 @@ const { getSystemErrorName: internalErrorName, promisify, toUSVString, + defineLazyProperties, } = require('internal/util'); let abortController; @@ -385,14 +383,9 @@ module.exports = { isFunction, isPrimitive, log, - MIMEType, - MIMEParams, - parseArgs, promisify, stripVTControlCharacters, toUSVString, - TextDecoder, - TextEncoder, get transferableAbortSignal() { return lazyAbortController().transferableAbortSignal; }, @@ -404,3 +397,21 @@ module.exports = { }, types, }; + +defineLazyProperties( + module.exports, + 'internal/util/parse_args/parse_args', + ['parseArgs'], +); + +defineLazyProperties( + module.exports, + 'internal/encoding', + ['TextDecoder', 'TextEncoder'], +); + +defineLazyProperties( + module.exports, + 'internal/mime', + ['MIMEType', 'MIMEParams'], +); diff --git a/lib/vm.js b/lib/vm.js index 21acc55e2eff0a..b48e79c282541b 100644 --- a/lib/vm.js +++ b/lib/vm.js @@ -105,10 +105,9 @@ class Script extends ContextifyScript { if (importModuleDynamically !== undefined) { validateFunction(importModuleDynamically, 'options.importModuleDynamically'); - const { importModuleDynamicallyWrap } = - require('internal/vm/module'); - const { callbackMap } = internalBinding('module_wrap'); - callbackMap.set(this, { + const { importModuleDynamicallyWrap } = require('internal/vm/module'); + const { setCallbackForWrap } = require('internal/modules/esm/utils'); + setCallbackForWrap(this, { importModuleDynamically: importModuleDynamicallyWrap(importModuleDynamically), }); diff --git a/node.gyp b/node.gyp index 6b554d75d89077..08cb3f38e8f836 100644 --- a/node.gyp +++ b/node.gyp @@ -29,6 +29,8 @@ 'node_lib_target_name%': 'libnode', 'node_intermediate_lib_type%': 'static_library', 'node_builtin_modules_path%': '', + 'linked_module_files': [ + ], # We list the deps/ files out instead of globbing them in js2c.py since we # only include a subset of all the files under these directories. # The lengths of their file names combined should not exceed the @@ -36,6 +38,7 @@ # See https://docs.microsoft.com/en-us/troubleshoot/windows-client/shell-experience/command-line-string-limitation 'library_files': [ '<@(node_library_files)', + '<@(linked_module_files)', ], 'deps_files': [ 'deps/v8/tools/splaytree.mjs', @@ -576,12 +579,14 @@ 'src/uv.cc', # headers to make for a more pleasant IDE experience 'src/aliased_buffer.h', + 'src/aliased_buffer-inl.h', 'src/aliased_struct.h', 'src/aliased_struct-inl.h', 'src/async_wrap.h', 'src/async_wrap-inl.h', 'src/base_object.h', 'src/base_object-inl.h', + 'src/base_object_types.h', 'src/base64.h', 'src/base64-inl.h', 'src/callback_queue.h', @@ -970,6 +975,7 @@ '<@(_outputs)', 'config.gypi', '<@(deps_files)', + '<@(linked_module_files)', ], }, ], diff --git a/pyproject.toml b/pyproject.toml index 6b51197ad66c2e..d0c3a056f2e92c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,6 +20,7 @@ select = [ exclude = [ "deps", "tools/inspector_protocol", + "tools/node_modules", ] ignore = [ "E401", diff --git a/src/README.md b/src/README.md index e3d42921b349ee..15317f06ae0ca3 100644 --- a/src/README.md +++ b/src/README.md @@ -528,18 +528,32 @@ that state is through the use of `Realm::AddBindingData`, which gives binding functions access to an object for storing such state. That object is always a [`BaseObject`][]. -Its class needs to have a static `type_name` field based on a -constant string, in order to disambiguate it from other classes of this type, -and which could e.g. match the binding's name (in the example above, that would -be `cares_wrap`). +In the binding, call `SET_BINDING_ID()` with an identifier for the binding +type. For example, for `http_parser::BindingData`, the identifier can be +`http_parser_binding_data`. + +If the binding should be supported in a snapshot, the id and the +fully-specified class name should be added to the `SERIALIZABLE_BINDING_TYPES` +list in `base_object_types.h`, and the class should implement the serialization +and deserialization methods. See the comments of `SnapshotableObject` on how to +implement them. Otherwise, add the id and the class name to the +`UNSERIALIZABLE_BINDING_TYPES` list instead. ```cpp +// In base_object_types.h, add the binding to either +// UNSERIALIZABLE_BINDING_TYPES or SERIALIZABLE_BINDING_TYPES. +// The second parameter is a descriptive name of the class, which is +// usually the fully-specified class name. + +#define UNSERIALIZABLE_BINDING_TYPES(V) \ + V(http_parser_binding_data, http_parser::BindingData) + // In the HTTP parser source code file: class BindingData : public BaseObject { public: BindingData(Realm* realm, Local obj) : BaseObject(realm, obj) {} - static constexpr FastStringKey type_name { "http_parser" }; + SET_BINDING_ID(http_parser_binding_data) std::vector parser_buffer; bool parser_buffer_in_use = false; @@ -569,12 +583,6 @@ void InitializeHttpParser(Local target, } ``` -If the binding is loaded during bootstrap, add it to the -`SERIALIZABLE_OBJECT_TYPES` list in `src/node_snapshotable.h` and -inherit from the `SnapshotableObject` class instead. See the comments -of `SnapshotableObject` on how to implement its serialization and -deserialization. - ### Exception handling diff --git a/src/aliased_buffer-inl.h b/src/aliased_buffer-inl.h new file mode 100644 index 00000000000000..58e9b6f8cef149 --- /dev/null +++ b/src/aliased_buffer-inl.h @@ -0,0 +1,232 @@ +#ifndef SRC_ALIASED_BUFFER_INL_H_ +#define SRC_ALIASED_BUFFER_INL_H_ + +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#include "aliased_buffer.h" +#include "util-inl.h" + +namespace node { + +typedef size_t AliasedBufferIndex; + +template +AliasedBufferBase::AliasedBufferBase( + v8::Isolate* isolate, const size_t count, const AliasedBufferIndex* index) + : isolate_(isolate), count_(count), byte_offset_(0), index_(index) { + CHECK_GT(count, 0); + if (index != nullptr) { + // Will be deserialized later. + return; + } + const v8::HandleScope handle_scope(isolate_); + const size_t size_in_bytes = + MultiplyWithOverflowCheck(sizeof(NativeT), count); + + // allocate v8 ArrayBuffer + v8::Local ab = v8::ArrayBuffer::New(isolate_, size_in_bytes); + buffer_ = static_cast(ab->Data()); + + // allocate v8 TypedArray + v8::Local js_array = V8T::New(ab, byte_offset_, count); + js_array_ = v8::Global(isolate, js_array); +} + +template +AliasedBufferBase::AliasedBufferBase( + v8::Isolate* isolate, + const size_t byte_offset, + const size_t count, + const AliasedBufferBase& backing_buffer, + const AliasedBufferIndex* index) + : isolate_(isolate), + count_(count), + byte_offset_(byte_offset), + index_(index) { + if (index != nullptr) { + // Will be deserialized later. + return; + } + const v8::HandleScope handle_scope(isolate_); + v8::Local ab = backing_buffer.GetArrayBuffer(); + + // validate that the byte_offset is aligned with sizeof(NativeT) + CHECK_EQ(byte_offset & (sizeof(NativeT) - 1), 0); + // validate this fits inside the backing buffer + CHECK_LE(MultiplyWithOverflowCheck(sizeof(NativeT), count), + ab->ByteLength() - byte_offset); + + buffer_ = reinterpret_cast( + const_cast(backing_buffer.GetNativeBuffer() + byte_offset)); + + v8::Local js_array = V8T::New(ab, byte_offset, count); + js_array_ = v8::Global(isolate, js_array); +} + +template +AliasedBufferBase::AliasedBufferBase( + const AliasedBufferBase& that) + : isolate_(that.isolate_), + count_(that.count_), + byte_offset_(that.byte_offset_), + buffer_(that.buffer_) { + DCHECK_NULL(index_); + js_array_ = v8::Global(that.isolate_, that.GetJSArray()); +} + +template +AliasedBufferIndex AliasedBufferBase::Serialize( + v8::Local context, v8::SnapshotCreator* creator) { + DCHECK_NULL(index_); + return creator->AddData(context, GetJSArray()); +} + +template +inline void AliasedBufferBase::Deserialize( + v8::Local context) { + DCHECK_NOT_NULL(index_); + v8::Local arr = + context->GetDataFromSnapshotOnce(*index_).ToLocalChecked(); + // These may not hold true for AliasedBuffers that have grown, so should + // be removed when we expand the snapshot support. + DCHECK_EQ(count_, arr->Length()); + DCHECK_EQ(byte_offset_, arr->ByteOffset()); + uint8_t* raw = static_cast(arr->Buffer()->Data()); + buffer_ = reinterpret_cast(raw + byte_offset_); + js_array_.Reset(isolate_, arr); + index_ = nullptr; +} + +template +AliasedBufferBase& AliasedBufferBase::operator=( + AliasedBufferBase&& that) noexcept { + DCHECK_NULL(index_); + this->~AliasedBufferBase(); + isolate_ = that.isolate_; + count_ = that.count_; + byte_offset_ = that.byte_offset_; + buffer_ = that.buffer_; + + js_array_.Reset(isolate_, that.js_array_.Get(isolate_)); + + that.buffer_ = nullptr; + that.js_array_.Reset(); + return *this; +} + +template +v8::Local AliasedBufferBase::GetJSArray() const { + DCHECK_NULL(index_); + return js_array_.Get(isolate_); +} + +template +void AliasedBufferBase::Release() { + DCHECK_NULL(index_); + js_array_.Reset(); +} + +template +v8::Local AliasedBufferBase::GetArrayBuffer() + const { + return GetJSArray()->Buffer(); +} + +template +inline const NativeT* AliasedBufferBase::GetNativeBuffer() const { + DCHECK_NULL(index_); + return buffer_; +} + +template +inline const NativeT* AliasedBufferBase::operator*() const { + return GetNativeBuffer(); +} + +template +inline void AliasedBufferBase::SetValue(const size_t index, + NativeT value) { + DCHECK_LT(index, count_); + DCHECK_NULL(index_); + buffer_[index] = value; +} + +template +inline const NativeT AliasedBufferBase::GetValue( + const size_t index) const { + DCHECK_NULL(index_); + DCHECK_LT(index, count_); + return buffer_[index]; +} + +template +typename AliasedBufferBase::Reference +AliasedBufferBase::operator[](size_t index) { + DCHECK_NULL(index_); + return Reference(this, index); +} + +template +NativeT AliasedBufferBase::operator[](size_t index) const { + return GetValue(index); +} + +template +size_t AliasedBufferBase::Length() const { + return count_; +} + +template +void AliasedBufferBase::reserve(size_t new_capacity) { + DCHECK_NULL(index_); + DCHECK_GE(new_capacity, count_); + DCHECK_EQ(byte_offset_, 0); + const v8::HandleScope handle_scope(isolate_); + + const size_t old_size_in_bytes = sizeof(NativeT) * count_; + const size_t new_size_in_bytes = + MultiplyWithOverflowCheck(sizeof(NativeT), new_capacity); + + // allocate v8 new ArrayBuffer + v8::Local ab = + v8::ArrayBuffer::New(isolate_, new_size_in_bytes); + + // allocate new native buffer + NativeT* new_buffer = static_cast(ab->Data()); + // copy old content + memcpy(new_buffer, buffer_, old_size_in_bytes); + + // allocate v8 TypedArray + v8::Local js_array = V8T::New(ab, byte_offset_, new_capacity); + + // move over old v8 TypedArray + js_array_ = std::move(v8::Global(isolate_, js_array)); + + buffer_ = new_buffer; + count_ = new_capacity; +} + +template +inline size_t AliasedBufferBase::SelfSize() const { + return sizeof(*this); +} + +#define VM(NativeT, V8T) \ + template <> \ + inline const char* AliasedBufferBase::MemoryInfoName() \ + const { \ + return "Aliased" #V8T; \ + } \ + template <> \ + inline void AliasedBufferBase::MemoryInfo( \ + node::MemoryTracker* tracker) const { \ + tracker->TrackField("js_array", js_array_); \ + } +ALIASED_BUFFER_LIST(VM) +#undef VM + +} // namespace node + +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#endif // SRC_ALIASED_BUFFER_INL_H_ diff --git a/src/aliased_buffer.h b/src/aliased_buffer.h index 98ea2d31febce2..bc858de3b3d268 100644 --- a/src/aliased_buffer.h +++ b/src/aliased_buffer.h @@ -4,7 +4,7 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include -#include "util-inl.h" +#include "memory_tracker.h" #include "v8.h" namespace node { @@ -28,34 +28,14 @@ typedef size_t AliasedBufferIndex; * The encapsulation herein provides a placeholder where such writes can be * observed. Any notification APIs will be left as a future exercise. */ -template ::value>> -class AliasedBufferBase { +template +class AliasedBufferBase : public MemoryRetainer { public: + static_assert(std::is_scalar::value); + AliasedBufferBase(v8::Isolate* isolate, const size_t count, - const AliasedBufferIndex* index = nullptr) - : isolate_(isolate), count_(count), byte_offset_(0), index_(index) { - CHECK_GT(count, 0); - if (index != nullptr) { - // Will be deserialized later. - return; - } - const v8::HandleScope handle_scope(isolate_); - const size_t size_in_bytes = - MultiplyWithOverflowCheck(sizeof(NativeT), count); - - // allocate v8 ArrayBuffer - v8::Local ab = v8::ArrayBuffer::New( - isolate_, size_in_bytes); - buffer_ = static_cast(ab->Data()); - - // allocate v8 TypedArray - v8::Local js_array = V8T::New(ab, byte_offset_, count); - js_array_ = v8::Global(isolate, js_array); - } + const AliasedBufferIndex* index = nullptr); /** * Create an AliasedBufferBase over a sub-region of another aliased buffer. @@ -71,74 +51,16 @@ class AliasedBufferBase { const size_t byte_offset, const size_t count, const AliasedBufferBase& backing_buffer, - const AliasedBufferIndex* index = nullptr) - : isolate_(isolate), - count_(count), - byte_offset_(byte_offset), - index_(index) { - if (index != nullptr) { - // Will be deserialized later. - return; - } - const v8::HandleScope handle_scope(isolate_); - v8::Local ab = backing_buffer.GetArrayBuffer(); - - // validate that the byte_offset is aligned with sizeof(NativeT) - CHECK_EQ(byte_offset & (sizeof(NativeT) - 1), 0); - // validate this fits inside the backing buffer - CHECK_LE(MultiplyWithOverflowCheck(sizeof(NativeT), count), - ab->ByteLength() - byte_offset); - - buffer_ = reinterpret_cast( - const_cast(backing_buffer.GetNativeBuffer() + byte_offset)); - - v8::Local js_array = V8T::New(ab, byte_offset, count); - js_array_ = v8::Global(isolate, js_array); - } - - AliasedBufferBase(const AliasedBufferBase& that) - : isolate_(that.isolate_), - count_(that.count_), - byte_offset_(that.byte_offset_), - buffer_(that.buffer_) { - DCHECK_NULL(index_); - js_array_ = v8::Global(that.isolate_, that.GetJSArray()); - } + const AliasedBufferIndex* index = nullptr); + + AliasedBufferBase(const AliasedBufferBase& that); AliasedBufferIndex Serialize(v8::Local context, - v8::SnapshotCreator* creator) { - DCHECK_NULL(index_); - return creator->AddData(context, GetJSArray()); - } - - inline void Deserialize(v8::Local context) { - DCHECK_NOT_NULL(index_); - v8::Local arr = - context->GetDataFromSnapshotOnce(*index_).ToLocalChecked(); - // These may not hold true for AliasedBuffers that have grown, so should - // be removed when we expand the snapshot support. - DCHECK_EQ(count_, arr->Length()); - DCHECK_EQ(byte_offset_, arr->ByteOffset()); - uint8_t* raw = static_cast(arr->Buffer()->Data()); - buffer_ = reinterpret_cast(raw + byte_offset_); - js_array_.Reset(isolate_, arr); - index_ = nullptr; - } - - AliasedBufferBase& operator=(AliasedBufferBase&& that) noexcept { - DCHECK_NULL(index_); - this->~AliasedBufferBase(); - isolate_ = that.isolate_; - count_ = that.count_; - byte_offset_ = that.byte_offset_; - buffer_ = that.buffer_; - - js_array_.Reset(isolate_, that.js_array_.Get(isolate_)); - - that.buffer_ = nullptr; - that.js_array_.Reset(); - return *this; - } + v8::SnapshotCreator* creator); + + inline void Deserialize(v8::Local context); + + AliasedBufferBase& operator=(AliasedBufferBase&& that) noexcept; /** * Helper class that is returned from operator[] to support assignment into @@ -191,105 +113,55 @@ class AliasedBufferBase { /** * Get the underlying v8 TypedArray overlayed on top of the native buffer */ - v8::Local GetJSArray() const { - DCHECK_NULL(index_); - return js_array_.Get(isolate_); - } + v8::Local GetJSArray() const; - void Release() { - DCHECK_NULL(index_); - js_array_.Reset(); - } + void Release(); /** * Get the underlying v8::ArrayBuffer underlying the TypedArray and * overlaying the native buffer */ - v8::Local GetArrayBuffer() const { - return GetJSArray()->Buffer(); - } + v8::Local GetArrayBuffer() const; /** * Get the underlying native buffer. Note that all reads/writes should occur * through the GetValue/SetValue/operator[] methods */ - inline const NativeT* GetNativeBuffer() const { - DCHECK_NULL(index_); - return buffer_; - } + inline const NativeT* GetNativeBuffer() const; /** * Synonym for GetBuffer() */ - inline const NativeT* operator * () const { - return GetNativeBuffer(); - } + inline const NativeT* operator*() const; /** * Set position index to given value. */ - inline void SetValue(const size_t index, NativeT value) { - DCHECK_LT(index, count_); - DCHECK_NULL(index_); - buffer_[index] = value; - } + inline void SetValue(const size_t index, NativeT value); /** * Get value at position index */ - inline const NativeT GetValue(const size_t index) const { - DCHECK_NULL(index_); - DCHECK_LT(index, count_); - return buffer_[index]; - } + inline const NativeT GetValue(const size_t index) const; /** * Effectively, a synonym for GetValue/SetValue */ - Reference operator[](size_t index) { - DCHECK_NULL(index_); - return Reference(this, index); - } + Reference operator[](size_t index); - NativeT operator[](size_t index) const { - return GetValue(index); - } + NativeT operator[](size_t index) const; - size_t Length() const { - return count_; - } + size_t Length() const; // Should only be used to extend the array. // Should only be used on an owning array, not one created as a sub array of // an owning `AliasedBufferBase`. - void reserve(size_t new_capacity) { - DCHECK_NULL(index_); - DCHECK_GE(new_capacity, count_); - DCHECK_EQ(byte_offset_, 0); - const v8::HandleScope handle_scope(isolate_); - - const size_t old_size_in_bytes = sizeof(NativeT) * count_; - const size_t new_size_in_bytes = MultiplyWithOverflowCheck(sizeof(NativeT), - new_capacity); - - // allocate v8 new ArrayBuffer - v8::Local ab = v8::ArrayBuffer::New( - isolate_, new_size_in_bytes); + void reserve(size_t new_capacity); - // allocate new native buffer - NativeT* new_buffer = static_cast(ab->Data()); - // copy old content - memcpy(new_buffer, buffer_, old_size_in_bytes); + inline size_t SelfSize() const override; - // allocate v8 TypedArray - v8::Local js_array = V8T::New(ab, byte_offset_, new_capacity); - - // move over old v8 TypedArray - js_array_ = std::move(v8::Global(isolate_, js_array)); - - buffer_ = new_buffer; - count_ = new_capacity; - } + inline const char* MemoryInfoName() const override; + inline void MemoryInfo(node::MemoryTracker* tracker) const override; private: v8::Isolate* isolate_ = nullptr; @@ -302,11 +174,22 @@ class AliasedBufferBase { const AliasedBufferIndex* index_ = nullptr; }; -typedef AliasedBufferBase AliasedInt32Array; -typedef AliasedBufferBase AliasedUint8Array; -typedef AliasedBufferBase AliasedUint32Array; -typedef AliasedBufferBase AliasedFloat64Array; -typedef AliasedBufferBase AliasedBigInt64Array; +#define ALIASED_BUFFER_LIST(V) \ + V(int8_t, Int8Array) \ + V(uint8_t, Uint8Array) \ + V(int16_t, Int16Array) \ + V(uint16_t, Uint16Array) \ + V(int32_t, Int32Array) \ + V(uint32_t, Uint32Array) \ + V(float, Float32Array) \ + V(double, Float64Array) \ + V(int64_t, BigInt64Array) + +#define V(NativeT, V8T) \ + typedef AliasedBufferBase Aliased##V8T; +ALIASED_BUFFER_LIST(V) +#undef V + } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS diff --git a/src/api/environment.cc b/src/api/environment.cc index e1095037f3b997..51cd46d0fb1c02 100644 --- a/src/api/environment.cc +++ b/src/api/environment.cc @@ -65,7 +65,18 @@ MaybeLocal PrepareStackTraceCallback(Local context, if (env == nullptr) { return exception->ToString(context).FromMaybe(Local()); } - Local prepare = env->prepare_stack_trace_callback(); + Realm* realm = Realm::GetCurrent(context); + Local prepare; + if (realm != nullptr) { + // If we are in a Realm, call the realm specific prepareStackTrace callback + // to avoid passing the JS objects (the exception and trace) across the + // realm boundary with the `Error.prepareStackTrace` override. + prepare = realm->prepare_stack_trace_callback(); + } else { + // The context is created with ContextifyContext, call the principal + // realm's prepareStackTrace callback. + prepare = env->principal_realm()->prepare_stack_trace_callback(); + } if (prepare.IsEmpty()) { return exception->ToString(context).FromMaybe(Local()); } @@ -489,14 +500,10 @@ MaybeLocal LoadEnvironment( return LoadEnvironment( env, [&](const StartExecutionCallbackInfo& info) -> MaybeLocal { std::string name = "embedder_main_" + std::to_string(env->thread_id()); - builtins::BuiltinLoader::Add(name.c_str(), main_script_source_utf8); + env->builtin_loader()->Add(name.c_str(), main_script_source_utf8); Realm* realm = env->principal_realm(); - // Arguments must match the parameters specified in - // BuiltinLoader::LookupAndCompile(). - std::vector> args = {realm->process_object(), - realm->builtin_module_require()}; - return realm->ExecuteBootstrapper(name.c_str(), &args); + return realm->ExecuteBootstrapper(name.c_str()); }); } @@ -733,20 +740,19 @@ Maybe InitializePrimordials(Local context) { "internal/per_context/messageport", nullptr}; + // We do not have access to a per-Environment BuiltinLoader instance + // at this point, because this code runs before an Environment exists + // in the first place. However, creating BuiltinLoader instances is + // relatively cheap and all the scripts that we may want to run at + // startup are always present in it. + thread_local builtins::BuiltinLoader builtin_loader; for (const char** module = context_files; *module != nullptr; module++) { - // Arguments must match the parameters specified in - // BuiltinLoader::LookupAndCompile(). Local arguments[] = {exports, primordials}; - MaybeLocal maybe_fn = - builtins::BuiltinLoader::LookupAndCompile(context, *module, nullptr); - Local fn; - if (!maybe_fn.ToLocal(&fn)) { - return Nothing(); - } - MaybeLocal result = - fn->Call(context, Undefined(isolate), arraysize(arguments), arguments); - // Execution failed during context creation. - if (result.IsEmpty()) { + if (builtin_loader + .CompileAndCall( + context, *module, arraysize(arguments), arguments, nullptr) + .IsEmpty()) { + // Execution failed during context creation. return Nothing(); } } diff --git a/src/base64_version.h b/src/base64_version.h new file mode 100644 index 00000000000000..fa492a293b40e1 --- /dev/null +++ b/src/base64_version.h @@ -0,0 +1,6 @@ +// This is an auto generated file, please do not edit. +// Refer to tools/dep_updaters/update-base64.sh +#ifndef SRC_BASE64_VERSION_H_ +#define SRC_BASE64_VERSION_H_ +#define BASE64_VERSION "0.5.0" +#endif // SRC_BASE64_VERSION_H_ diff --git a/src/base_object.h b/src/base_object.h index 7bfcb95cfcab65..4ac644a034f4a6 100644 --- a/src/base_object.h +++ b/src/base_object.h @@ -25,6 +25,7 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include // std::remove_reference +#include "base_object_types.h" #include "memory_tracker.h" #include "v8.h" diff --git a/src/base_object_types.h b/src/base_object_types.h index 4916a20bbc6421..09f1af7554692c 100644 --- a/src/base_object_types.h +++ b/src/base_object_types.h @@ -10,12 +10,10 @@ namespace node { // what the class passes to SET_BINDING_ID(), the second argument should match // the C++ class name. #define SERIALIZABLE_BINDING_TYPES(V) \ - V(encoding_binding_data, encoding_binding::BindingData) \ V(fs_binding_data, fs::BindingData) \ V(v8_binding_data, v8_utils::BindingData) \ V(blob_binding_data, BlobBindingData) \ V(process_binding_data, process::BindingData) \ - V(timers_binding_data, timers::BindingData) \ V(url_binding_data, url::BindingData) #define UNSERIALIZABLE_BINDING_TYPES(V) \ diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index aab07945786cec..8b037356360729 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -20,6 +20,7 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. #include "cares_wrap.h" +#include "ada.h" #include "async_wrap-inl.h" #include "base64-inl.h" #include "base_object-inl.h" @@ -829,62 +830,62 @@ void ChannelWrap::EnsureServers() { int AnyTraits::Send(QueryWrap* wrap, const char* name) { wrap->AresQuery(name, ns_c_in, ns_t_any); - return 0; + return ARES_SUCCESS; } int ATraits::Send(QueryWrap* wrap, const char* name) { wrap->AresQuery(name, ns_c_in, ns_t_a); - return 0; + return ARES_SUCCESS; } int AaaaTraits::Send(QueryWrap* wrap, const char* name) { wrap->AresQuery(name, ns_c_in, ns_t_aaaa); - return 0; + return ARES_SUCCESS; } int CaaTraits::Send(QueryWrap* wrap, const char* name) { wrap->AresQuery(name, ns_c_in, T_CAA); - return 0; + return ARES_SUCCESS; } int CnameTraits::Send(QueryWrap* wrap, const char* name) { wrap->AresQuery(name, ns_c_in, ns_t_cname); - return 0; + return ARES_SUCCESS; } int MxTraits::Send(QueryWrap* wrap, const char* name) { wrap->AresQuery(name, ns_c_in, ns_t_mx); - return 0; + return ARES_SUCCESS; } int NsTraits::Send(QueryWrap* wrap, const char* name) { wrap->AresQuery(name, ns_c_in, ns_t_ns); - return 0; + return ARES_SUCCESS; } int TxtTraits::Send(QueryWrap* wrap, const char* name) { wrap->AresQuery(name, ns_c_in, ns_t_txt); - return 0; + return ARES_SUCCESS; } int SrvTraits::Send(QueryWrap* wrap, const char* name) { wrap->AresQuery(name, ns_c_in, ns_t_srv); - return 0; + return ARES_SUCCESS; } int PtrTraits::Send(QueryWrap* wrap, const char* name) { wrap->AresQuery(name, ns_c_in, ns_t_ptr); - return 0; + return ARES_SUCCESS; } int NaptrTraits::Send(QueryWrap* wrap, const char* name) { wrap->AresQuery(name, ns_c_in, ns_t_naptr); - return 0; + return ARES_SUCCESS; } int SoaTraits::Send(QueryWrap* wrap, const char* name) { wrap->AresQuery(name, ns_c_in, ns_t_soa); - return 0; + return ARES_SUCCESS; } int AnyTraits::Parse( @@ -1051,7 +1052,7 @@ int AnyTraits::Parse( return status; wrap->CallOnComplete(ret); - return 0; + return ARES_SUCCESS; } int ATraits::Parse( @@ -1085,7 +1086,7 @@ int ATraits::Parse( Local ttls = AddrTTLToArray(env, addrttls, naddrttls); wrap->CallOnComplete(ret, ttls); - return 0; + return ARES_SUCCESS; } int AaaaTraits::Parse( @@ -1119,7 +1120,7 @@ int AaaaTraits::Parse( Local ttls = AddrTTLToArray(env, addrttls, naddrttls); wrap->CallOnComplete(ret, ttls); - return 0; + return ARES_SUCCESS; } int CaaTraits::Parse( @@ -1141,7 +1142,7 @@ int CaaTraits::Parse( return status; wrap->CallOnComplete(ret); - return 0; + return ARES_SUCCESS; } int CnameTraits::Parse( @@ -1164,7 +1165,7 @@ int CnameTraits::Parse( return status; wrap->CallOnComplete(ret); - return 0; + return ARES_SUCCESS; } int MxTraits::Parse( @@ -1187,7 +1188,7 @@ int MxTraits::Parse( return status; wrap->CallOnComplete(mx_records); - return 0; + return ARES_SUCCESS; } int NsTraits::Parse( @@ -1210,7 +1211,7 @@ int NsTraits::Parse( return status; wrap->CallOnComplete(names); - return 0; + return ARES_SUCCESS; } int TxtTraits::Parse( @@ -1232,7 +1233,7 @@ int TxtTraits::Parse( return status; wrap->CallOnComplete(txt_records); - return 0; + return ARES_SUCCESS; } int SrvTraits::Parse( @@ -1254,7 +1255,7 @@ int SrvTraits::Parse( return status; wrap->CallOnComplete(srv_records); - return 0; + return ARES_SUCCESS; } int PtrTraits::Parse( @@ -1278,7 +1279,7 @@ int PtrTraits::Parse( return status; wrap->CallOnComplete(aliases); - return 0; + return ARES_SUCCESS; } int NaptrTraits::Parse( @@ -1300,7 +1301,7 @@ int NaptrTraits::Parse( return status; wrap->CallOnComplete(naptr_records); - return 0; + return ARES_SUCCESS; } int SoaTraits::Parse( @@ -1351,7 +1352,7 @@ int SoaTraits::Parse( ares_free_data(soa_out); wrap->CallOnComplete(soa_record); - return 0; + return ARES_SUCCESS; } int ReverseTraits::Send(GetHostByAddrWrap* wrap, const char* name) { @@ -1380,7 +1381,7 @@ int ReverseTraits::Send(GetHostByAddrWrap* wrap, const char* name) { family, GetHostByAddrWrap::Callback, wrap->MakeCallbackPointer()); - return 0; + return ARES_SUCCESS; } int ReverseTraits::Parse( @@ -1395,7 +1396,7 @@ int ReverseTraits::Parse( HandleScope handle_scope(env->isolate()); Context::Scope context_scope(env->context()); wrap->CallOnComplete(HostentToNames(env, host)); - return 0; + return ARES_SUCCESS; } namespace { @@ -1413,9 +1414,11 @@ static void Query(const FunctionCallbackInfo& args) { Local string = args[1].As(); auto wrap = std::make_unique(channel, req_wrap_obj); - node::Utf8Value name(env->isolate(), string); + node::Utf8Value utf8name(env->isolate(), string); + auto plain_name = utf8name.ToStringView(); + std::string name = ada::idna::to_ascii(plain_name); channel->ModifyActivityQueryCount(1); - int err = wrap->Send(*name); + int err = wrap->Send(name.c_str()); if (err) { channel->ModifyActivityQueryCount(-1); } else { @@ -1558,6 +1561,7 @@ void GetAddrInfo(const FunctionCallbackInfo& args) { CHECK(args[4]->IsBoolean()); Local req_wrap_obj = args[0].As(); node::Utf8Value hostname(env->isolate(), args[1]); + std::string ascii_hostname = ada::idna::to_ascii(hostname.ToStringView()); int32_t flags = 0; if (args[3]->IsInt32()) { @@ -1590,17 +1594,18 @@ void GetAddrInfo(const FunctionCallbackInfo& args) { hints.ai_socktype = SOCK_STREAM; hints.ai_flags = flags; - TRACE_EVENT_NESTABLE_ASYNC_BEGIN2( - TRACING_CATEGORY_NODE2(dns, native), "lookup", req_wrap.get(), - "hostname", TRACE_STR_COPY(*hostname), - "family", - family == AF_INET ? "ipv4" : family == AF_INET6 ? "ipv6" : "unspec"); - - int err = req_wrap->Dispatch(uv_getaddrinfo, - AfterGetAddrInfo, - *hostname, - nullptr, - &hints); + TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(TRACING_CATEGORY_NODE2(dns, native), + "lookup", + req_wrap.get(), + "hostname", + TRACE_STR_COPY(ascii_hostname.data()), + "family", + family == AF_INET ? "ipv4" + : family == AF_INET6 ? "ipv6" + : "unspec"); + + int err = req_wrap->Dispatch( + uv_getaddrinfo, AfterGetAddrInfo, ascii_hostname.data(), nullptr, &hints); if (err == 0) // Release ownership of the pointer allowing the ownership to be transferred USE(req_wrap.release()); diff --git a/src/cjs_module_lexer_version.h b/src/cjs_module_lexer_version.h new file mode 100644 index 00000000000000..3e120e550329cc --- /dev/null +++ b/src/cjs_module_lexer_version.h @@ -0,0 +1,6 @@ +// This is an auto generated file, please do not edit. +// Refer to tools/dep_updaters/update-cjs-module-lexer.sh +#ifndef SRC_CJS_MODULE_LEXER_VERSION_H_ +#define SRC_CJS_MODULE_LEXER_VERSION_H_ +#define CJS_MODULE_LEXER_VERSION "1.2.2" +#endif // SRC_CJS_MODULE_LEXER_VERSION_H_ diff --git a/src/cleanup_queue-inl.h b/src/cleanup_queue-inl.h index d1fbd8241d9919..dad23ecf3aec24 100644 --- a/src/cleanup_queue-inl.h +++ b/src/cleanup_queue-inl.h @@ -26,8 +26,8 @@ bool CleanupQueue::empty() const { } void CleanupQueue::Add(Callback cb, void* arg) { - auto insertion_info = cleanup_hooks_.emplace( - CleanupHookCallback{cb, arg, cleanup_hook_counter_++}); + auto insertion_info = + cleanup_hooks_.emplace(cb, arg, cleanup_hook_counter_++); // Make sure there was no existing element with these values. CHECK_EQ(insertion_info.second, true); } diff --git a/src/crypto/crypto_keys.cc b/src/crypto/crypto_keys.cc index 0be2283d6017a4..fdf6cd45e970c8 100644 --- a/src/crypto/crypto_keys.cc +++ b/src/crypto/crypto_keys.cc @@ -908,6 +908,8 @@ v8::Local KeyObjectHandle::Initialize(Environment* env) { isolate, templ, "getSymmetricKeySize", GetSymmetricKeySize); SetProtoMethodNoSideEffect( isolate, templ, "getAsymmetricKeyType", GetAsymmetricKeyType); + SetProtoMethodNoSideEffect( + isolate, templ, "checkEcKeyData", CheckEcKeyData); SetProtoMethod(isolate, templ, "export", Export); SetProtoMethod(isolate, templ, "exportJwk", ExportJWK); SetProtoMethod(isolate, templ, "initECRaw", InitECRaw); @@ -927,6 +929,7 @@ void KeyObjectHandle::RegisterExternalReferences( registry->Register(Init); registry->Register(GetSymmetricKeySize); registry->Register(GetAsymmetricKeyType); + registry->Register(CheckEcKeyData); registry->Register(Export); registry->Register(ExportJWK); registry->Register(InitECRaw); @@ -1238,6 +1241,34 @@ void KeyObjectHandle::GetAsymmetricKeyType( args.GetReturnValue().Set(key->GetAsymmetricKeyType()); } +bool KeyObjectHandle::CheckEcKeyData() const { + MarkPopErrorOnReturn mark_pop_error_on_return; + + const ManagedEVPPKey& key = data_->GetAsymmetricKey(); + KeyType type = data_->GetKeyType(); + CHECK_NE(type, kKeyTypeSecret); + EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new(key.get(), nullptr)); + CHECK(ctx); + CHECK_EQ(EVP_PKEY_id(key.get()), EVP_PKEY_EC); + + if (type == kKeyTypePrivate) { + return EVP_PKEY_check(ctx.get()) == 1; + } + +#if OPENSSL_VERSION_MAJOR >= 3 + return EVP_PKEY_public_check_quick(ctx.get()) == 1; +#else + return EVP_PKEY_public_check(ctx.get()) == 1; +#endif +} + +void KeyObjectHandle::CheckEcKeyData(const FunctionCallbackInfo& args) { + KeyObjectHandle* key; + ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder()); + + args.GetReturnValue().Set(key->CheckEcKeyData()); +} + void KeyObjectHandle::GetSymmetricKeySize( const FunctionCallbackInfo& args) { KeyObjectHandle* key; diff --git a/src/crypto/crypto_keys.h b/src/crypto/crypto_keys.h index eb4f5222670e89..820d26cc153177 100644 --- a/src/crypto/crypto_keys.h +++ b/src/crypto/crypto_keys.h @@ -193,6 +193,9 @@ class KeyObjectHandle : public BaseObject { const v8::FunctionCallbackInfo& args); v8::Local GetAsymmetricKeyType() const; + static void CheckEcKeyData(const v8::FunctionCallbackInfo& args); + bool CheckEcKeyData() const; + static void GetSymmetricKeySize( const v8::FunctionCallbackInfo& args); diff --git a/src/crypto/crypto_tls.cc b/src/crypto/crypto_tls.cc index 13937262997365..b76cd1117eab0d 100644 --- a/src/crypto/crypto_tls.cc +++ b/src/crypto/crypto_tls.cc @@ -223,7 +223,45 @@ int SelectALPNCallback( const unsigned char* in, unsigned int inlen, void* arg) { - TLSWrap* w = static_cast(arg); + TLSWrap* w = static_cast(SSL_get_app_data(s)); + if (w->alpn_callback_enabled_) { + Environment* env = w->env(); + HandleScope handle_scope(env->isolate()); + + Local callback_arg = + Buffer::Copy(env, reinterpret_cast(in), inlen) + .ToLocalChecked(); + + MaybeLocal maybe_callback_result = + w->MakeCallback(env->alpn_callback_string(), 1, &callback_arg); + + if (UNLIKELY(maybe_callback_result.IsEmpty())) { + // Implies the callback didn't return, because some exception was thrown + // during processing, e.g. if callback returned an invalid ALPN value. + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + + Local callback_result = maybe_callback_result.ToLocalChecked(); + + if (callback_result->IsUndefined()) { + // If you set an ALPN callback, but you return undefined for an ALPN + // request, you're rejecting all proposed ALPN protocols, and so we send + // a fatal alert: + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + + CHECK(callback_result->IsNumber()); + unsigned int result_int = callback_result.As()->Value(); + + // The callback returns an offset into the given buffer, for the selected + // protocol that should be returned. We then set outlen & out to point + // to the selected input length & value directly: + *outlen = *(in + result_int); + *out = (in + result_int + 1); + + return SSL_TLSEXT_ERR_OK; + } + const std::vector& alpn_protos = w->alpn_protos_; if (alpn_protos.empty()) return SSL_TLSEXT_ERR_NOACK; @@ -1249,6 +1287,16 @@ void TLSWrap::OnClientHelloParseEnd(void* arg) { c->Cycle(); } +void TLSWrap::EnableALPNCb(const FunctionCallbackInfo& args) { + TLSWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); + wrap->alpn_callback_enabled_ = true; + + SSL* ssl = wrap->ssl_.get(); + SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(ssl); + SSL_CTX_set_alpn_select_cb(ssl_ctx, SelectALPNCallback, nullptr); +} + void TLSWrap::GetServername(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); @@ -1542,7 +1590,8 @@ void TLSWrap::SetALPNProtocols(const FunctionCallbackInfo& args) { } else { w->alpn_protos_ = std::vector( protos.data(), protos.data() + protos.length()); - SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), SelectALPNCallback, w); + SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(ssl); + SSL_CTX_set_alpn_select_cb(ssl_ctx, SelectALPNCallback, nullptr); } } @@ -2069,6 +2118,7 @@ void TLSWrap::Initialize( SetProtoMethod(isolate, t, "certCbDone", CertCbDone); SetProtoMethod(isolate, t, "destroySSL", DestroySSL); SetProtoMethod(isolate, t, "enableCertCb", EnableCertCb); + SetProtoMethod(isolate, t, "enableALPNCb", EnableALPNCb); SetProtoMethod(isolate, t, "endParser", EndParser); SetProtoMethod(isolate, t, "enableKeylogCallback", EnableKeylogCallback); SetProtoMethod(isolate, t, "enableSessionCallbacks", EnableSessionCallbacks); @@ -2138,6 +2188,7 @@ void TLSWrap::RegisterExternalReferences(ExternalReferenceRegistry* registry) { registry->Register(CertCbDone); registry->Register(DestroySSL); registry->Register(EnableCertCb); + registry->Register(EnableALPNCb); registry->Register(EndParser); registry->Register(EnableKeylogCallback); registry->Register(EnableSessionCallbacks); diff --git a/src/crypto/crypto_tls.h b/src/crypto/crypto_tls.h index 01414efc6b0258..b65cea22255248 100644 --- a/src/crypto/crypto_tls.h +++ b/src/crypto/crypto_tls.h @@ -175,6 +175,7 @@ class TLSWrap : public AsyncWrap, static void CertCbDone(const v8::FunctionCallbackInfo& args); static void DestroySSL(const v8::FunctionCallbackInfo& args); static void EnableCertCb(const v8::FunctionCallbackInfo& args); + static void EnableALPNCb(const v8::FunctionCallbackInfo& args); static void EnableKeylogCallback( const v8::FunctionCallbackInfo& args); static void EnableSessionCallbacks( @@ -292,6 +293,7 @@ class TLSWrap : public AsyncWrap, public: std::vector alpn_protos_; // Accessed by SelectALPNCallback. + bool alpn_callback_enabled_ = false; // Accessed by SelectALPNCallback. }; } // namespace crypto diff --git a/src/env-inl.h b/src/env-inl.h index 7ceab0da0c632f..b959fb48d29ce1 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -24,7 +24,7 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS -#include "aliased_buffer.h" +#include "aliased_buffer-inl.h" #include "callback_queue-inl.h" #include "env.h" #include "node.h" @@ -388,6 +388,10 @@ inline std::vector* Environment::destroy_async_id_list() { return &destroy_async_id_list_; } +inline builtins::BuiltinLoader* Environment::builtin_loader() { + return &builtin_loader_; +} + inline double Environment::new_async_id() { async_hooks()->async_id_fields()[AsyncHooks::kAsyncIdCounter] += 1; return async_hooks()->async_id_fields()[AsyncHooks::kAsyncIdCounter]; @@ -778,6 +782,7 @@ void Environment::set_process_exit_handler( #undef VY #undef VP +#define VM(PropertyName) V(PropertyName##_binding, v8::FunctionTemplate) #define V(PropertyName, TypeName) \ inline v8::Local IsolateData::PropertyName() const { \ return PropertyName##_.Get(isolate_); \ @@ -786,7 +791,9 @@ void Environment::set_process_exit_handler( PropertyName##_.Set(isolate_, value); \ } PER_ISOLATE_TEMPLATE_PROPERTIES(V) + NODE_BINDINGS_WITH_PER_ISOLATE_INIT(VM) #undef V +#undef VM #define VP(PropertyName, StringValue) V(v8::Private, PropertyName) #define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName) diff --git a/src/env.cc b/src/env.cc index 5bdbfad4f4d3ef..1650027820a18f 100644 --- a/src/env.cc +++ b/src/env.cc @@ -311,6 +311,7 @@ IsolateDataSerializeInfo IsolateData::Serialize(SnapshotCreator* creator) { info.primitive_values.push_back(creator->AddData(async_wrap_provider(i))); uint32_t id = 0; +#define VM(PropertyName) V(PropertyName##_binding, FunctionTemplate) #define V(PropertyName, TypeName) \ do { \ Local field = PropertyName(); \ @@ -321,6 +322,7 @@ IsolateDataSerializeInfo IsolateData::Serialize(SnapshotCreator* creator) { id++; \ } while (0); PER_ISOLATE_TEMPLATE_PROPERTIES(V) + NODE_BINDINGS_WITH_PER_ISOLATE_INIT(VM) #undef V return info; @@ -330,6 +332,11 @@ void IsolateData::DeserializeProperties(const IsolateDataSerializeInfo* info) { size_t i = 0; HandleScope handle_scope(isolate_); + if (per_process::enabled_debug_list.enabled(DebugCategory::MKSNAPSHOT)) { + fprintf(stderr, "deserializing IsolateDataSerializeInfo...\n"); + std::cerr << *info << "\n"; + } + #define VP(PropertyName, StringValue) V(Private, PropertyName) #define VY(PropertyName, StringValue) V(Symbol, PropertyName) #define VS(PropertyName, StringValue) V(String, PropertyName) @@ -365,6 +372,7 @@ void IsolateData::DeserializeProperties(const IsolateDataSerializeInfo* info) { const std::vector& values = info->template_values; i = 0; // index to the array uint32_t id = 0; +#define VM(PropertyName) V(PropertyName##_binding, FunctionTemplate) #define V(PropertyName, TypeName) \ do { \ if (values.size() > i && id == values[i].id) { \ @@ -385,6 +393,7 @@ void IsolateData::DeserializeProperties(const IsolateDataSerializeInfo* info) { } while (0); PER_ISOLATE_TEMPLATE_PROPERTIES(V); + NODE_BINDINGS_WITH_PER_ISOLATE_INIT(VM); #undef V } @@ -451,12 +460,12 @@ void IsolateData::CreateProperties() { NODE_ASYNC_PROVIDER_TYPES(V) #undef V - // TODO(legendecas): eagerly create per isolate templates. Local templ = FunctionTemplate::New(isolate()); templ->InstanceTemplate()->SetInternalFieldCount( BaseObject::kInternalFieldCount); templ->Inherit(BaseObject::GetConstructorTemplate(this)); set_binding_data_ctor_template(templ); + binding::CreateInternalBindingTemplates(this); contextify::ContextifyContext::InitializeGlobalTemplates(this); } @@ -538,7 +547,7 @@ void Environment::AssignToContext(Local context, // Used to retrieve bindings context->SetAlignedPointerInEmbedderData( ContextEmbedderIndex::kBindingDataStoreIndex, - realm->binding_data_store()); + realm != nullptr ? realm->binding_data_store() : nullptr); // ContextifyContexts will update this to a pointer to the native object. context->SetAlignedPointerInEmbedderData( @@ -667,6 +676,15 @@ Environment::Environment(IsolateData* isolate_data, thread_id_(thread_id.id == static_cast(-1) ? AllocateEnvironmentThreadId().id : thread_id.id) { +#ifdef NODE_V8_SHARED_RO_HEAP + if (!is_main_thread()) { + CHECK_NOT_NULL(isolate_data->worker_context()); + // TODO(addaleax): Adjust for the embedder API snapshot support changes + builtin_loader()->CopySourceAndCodeCacheReferenceFrom( + isolate_data->worker_context()->env()->builtin_loader()); + } +#endif + // We'll be creating new objects so make sure we've entered the context. HandleScope handle_scope(isolate); @@ -1580,18 +1598,6 @@ void Environment::PrintInfoForSnapshotIfDebug() { if (enabled_debug_list()->enabled(DebugCategory::MKSNAPSHOT)) { fprintf(stderr, "At the exit of the Environment:\n"); principal_realm()->PrintInfoForSnapshot(); - fprintf(stderr, "\nBuiltins without cache:\n"); - for (const auto& s : builtins_without_cache) { - fprintf(stderr, "%s\n", s.c_str()); - } - fprintf(stderr, "\nBuiltins with cache:\n"); - for (const auto& s : builtins_with_cache) { - fprintf(stderr, "%s\n", s.c_str()); - } - fprintf(stderr, "\nStatic bindings (need to be registered):\n"); - for (const auto mod : internal_bindings) { - fprintf(stderr, "%s:%s\n", mod->nm_filename, mod->nm_modname); - } } } @@ -1599,11 +1605,6 @@ EnvSerializeInfo Environment::Serialize(SnapshotCreator* creator) { EnvSerializeInfo info; Local ctx = context(); - // Currently all modules are compiled without cache in builtin snapshot - // builder. - info.builtins = std::vector(builtins_without_cache.begin(), - builtins_without_cache.end()); - info.async_hooks = async_hooks_.Serialize(ctx, creator); info.immediate_info = immediate_info_.Serialize(ctx, creator); info.timeout_info = timeout_info_.Serialize(ctx, creator); @@ -1648,9 +1649,13 @@ void Environment::RunDeserializeRequests() { void Environment::DeserializeProperties(const EnvSerializeInfo* info) { Local ctx = context(); + if (enabled_debug_list_.enabled(DebugCategory::MKSNAPSHOT)) { + fprintf(stderr, "deserializing EnvSerializeInfo...\n"); + std::cerr << *info << "\n"; + } + RunDeserializeRequests(); - builtins_in_snapshot = info->builtins; async_hooks_.Deserialize(ctx); immediate_info_.Deserialize(ctx); timeout_info_.Deserialize(ctx); @@ -1661,11 +1666,6 @@ void Environment::DeserializeProperties(const EnvSerializeInfo* info) { should_abort_on_uncaught_toggle_.Deserialize(ctx); principal_realm_->DeserializeProperties(&info->principal_realm); - - if (enabled_debug_list_.enabled(DebugCategory::MKSNAPSHOT)) { - fprintf(stderr, "deserializing...\n"); - std::cerr << *info << "\n"; - } } uint64_t GuessMemoryAvailableToTheProcess() { @@ -1839,8 +1839,6 @@ void Environment::MemoryInfo(MemoryTracker* tracker) const { // Iteratable STLs have their own sizes subtracted from the parent // by default. tracker->TrackField("isolate_data", isolate_data_); - tracker->TrackField("builtins_with_cache", builtins_with_cache); - tracker->TrackField("builtins_without_cache", builtins_without_cache); tracker->TrackField("destroy_async_id_list", destroy_async_id_list_); tracker->TrackField("exec_argv", exec_argv_); tracker->TrackField("exiting", exiting_); diff --git a/src/env.h b/src/env.h index b67a476701f9bd..06250f32e14863 100644 --- a/src/env.h +++ b/src/env.h @@ -154,11 +154,14 @@ class NODE_EXTERN_PRIVATE IsolateData : public MemoryRetainer { #undef VS #undef VP +#define VM(PropertyName) V(PropertyName##_binding, v8::FunctionTemplate) #define V(PropertyName, TypeName) \ inline v8::Local PropertyName() const; \ inline void set_##PropertyName(v8::Local value); PER_ISOLATE_TEMPLATE_PROPERTIES(V) + NODE_BINDINGS_WITH_PER_ISOLATE_INIT(VM) #undef V +#undef VM inline v8::Local async_wrap_provider(int index) const; @@ -178,6 +181,7 @@ class NODE_EXTERN_PRIVATE IsolateData : public MemoryRetainer { #define VP(PropertyName, StringValue) V(v8::Private, PropertyName) #define VY(PropertyName, StringValue) V(v8::Symbol, PropertyName) #define VS(PropertyName, StringValue) V(v8::String, PropertyName) +#define VM(PropertyName) V(v8::FunctionTemplate, PropertyName##_binding) #define VT(PropertyName, TypeName) V(TypeName, PropertyName) #define V(TypeName, PropertyName) \ v8::Eternal PropertyName ## _; @@ -185,8 +189,9 @@ class NODE_EXTERN_PRIVATE IsolateData : public MemoryRetainer { PER_ISOLATE_SYMBOL_PROPERTIES(VY) PER_ISOLATE_STRING_PROPERTIES(VS) PER_ISOLATE_TEMPLATE_PROPERTIES(VT) + NODE_BINDINGS_WITH_PER_ISOLATE_INIT(VM) #undef V -#undef V +#undef VM #undef VT #undef VS #undef VY @@ -456,7 +461,6 @@ struct DeserializeRequest { }; struct EnvSerializeInfo { - std::vector builtins; AsyncHooks::SerializeInfo async_hooks; TickInfo::SerializeInfo tick_info; ImmediateInfo::SerializeInfo immediate_info; @@ -691,12 +695,7 @@ class Environment : public MemoryRetainer { // List of id's that have been destroyed and need the destroy() cb called. inline std::vector* destroy_async_id_list(); - std::set internal_bindings; - std::set builtins_with_cache; - std::set builtins_without_cache; - // This is only filled during deserialization. We use a vector since - // it's only used for tests. - std::vector builtins_in_snapshot; + builtins::BuiltinLoader* builtin_loader(); std::unordered_multimap hash_to_module_map; std::unordered_map id_to_module_map; @@ -1102,6 +1101,8 @@ class Environment : public MemoryRetainer { std::unique_ptr principal_realm_ = nullptr; + builtins::BuiltinLoader builtin_loader_; + // Used by allocate_managed_buffer() and release_managed_buffer() to keep // track of the BackingStore for a given pointer. std::unordered_map> diff --git a/src/env_properties.h b/src/env_properties.h index 2a1843f68309e4..5fc5106c0c5ad2 100644 --- a/src/env_properties.h +++ b/src/env_properties.h @@ -30,6 +30,7 @@ // Symbols are per-isolate primitives but Environment proxies them // for the sake of convenience. #define PER_ISOLATE_SYMBOL_PROPERTIES(V) \ + V(fs_use_promises_symbol, "fs_use_promises_symbol") \ V(async_id_symbol, "async_id_symbol") \ V(handle_onclose_symbol, "handle_onclose") \ V(no_message_symbol, "no_message_symbol") \ @@ -49,6 +50,7 @@ V(ack_string, "ack") \ V(address_string, "address") \ V(aliases_string, "aliases") \ + V(alpn_callback_string, "ALPNCallback") \ V(args_string, "args") \ V(asn1curve_string, "asn1Curve") \ V(async_ids_stack_string, "async_ids_stack") \ @@ -385,7 +387,6 @@ V(domexception_function, v8::Function) \ V(enhance_fatal_stack_after_inspector, v8::Function) \ V(enhance_fatal_stack_before_inspector, v8::Function) \ - V(fs_use_promises_symbol, v8::Symbol) \ V(get_source_map_error_source, v8::Function) \ V(host_import_module_dynamically_callback, v8::Function) \ V(host_initialize_import_meta_object_callback, v8::Function) \ diff --git a/src/js_native_api.h b/src/js_native_api.h index 3aa0ee5c1c5c5c..d665052b947552 100644 --- a/src/js_native_api.h +++ b/src/js_native_api.h @@ -28,7 +28,7 @@ #ifndef NAPI_EXTERN #ifdef _WIN32 #define NAPI_EXTERN __declspec(dllexport) -#elif defined(__wasm32__) +#elif defined(__wasm__) #define NAPI_EXTERN \ __attribute__((visibility("default"))) \ __attribute__((__import_module__("napi"))) @@ -517,6 +517,16 @@ NAPI_EXTERN napi_status NAPI_CDECL napi_add_finalizer(napi_env env, #endif // NAPI_VERSION >= 5 +#ifdef NAPI_EXPERIMENTAL + +NAPI_EXTERN napi_status NAPI_CDECL +node_api_post_finalizer(napi_env env, + napi_finalize finalize_cb, + void* finalize_data, + void* finalize_hint); + +#endif // NAPI_EXPERIMENTAL + #if NAPI_VERSION >= 6 // BigInt diff --git a/src/js_native_api_v8.cc b/src/js_native_api_v8.cc index 10b821119d3ff2..b1b66b7da6cc21 100644 --- a/src/js_native_api_v8.cc +++ b/src/js_native_api_v8.cc @@ -57,8 +57,22 @@ (out) = v8::type::New((buffer), (byte_offset), (length)); \ } while (0) -namespace v8impl { +void napi_env__::InvokeFinalizerFromGC(v8impl::RefTracker* finalizer) { + if (module_api_version != NAPI_VERSION_EXPERIMENTAL) { + EnqueueFinalizer(finalizer); + } else { + // The experimental code calls finalizers immediately to release native + // objects as soon as possible. In that state any code that may affect GC + // state causes a fatal error. To work around this issue the finalizer code + // can call node_api_post_finalizer. + auto restore_state = node::OnScopeLeave( + [this, saved = in_gc_finalizer] { in_gc_finalizer = saved; }); + in_gc_finalizer = true; + finalizer->Finalize(); + } +} +namespace v8impl { namespace { template @@ -68,6 +82,7 @@ napi_status NewString(napi_env env, napi_value* result, StringMaker string_maker) { CHECK_ENV(env); + env->CheckGCAccess(); if (length > 0) CHECK_ARG(env, str); CHECK_ARG(env, result); RETURN_STATUS_IF_FALSE( @@ -92,6 +107,7 @@ napi_status NewExternalString(napi_env env, StringMaker string_maker) { napi_status status; #if defined(V8_ENABLE_SANDBOX) + env->CheckGCAccess(); status = create_api(env, str, length, result); if (status == napi_ok) { if (copied != nullptr) { @@ -604,28 +620,70 @@ void Finalizer::ResetFinalizer() { finalize_hint_ = nullptr; } -// Wrapper around v8impl::Persistent that implements reference counting. -RefBase::RefBase(napi_env env, - uint32_t initial_refcount, - Ownership ownership, - napi_finalize finalize_callback, - void* finalize_data, - void* finalize_hint) +TrackedFinalizer::TrackedFinalizer(napi_env env, + napi_finalize finalize_callback, + void* finalize_data, + void* finalize_hint) : Finalizer(env, finalize_callback, finalize_data, finalize_hint), - refcount_(initial_refcount), - ownership_(ownership) { + RefTracker() { Link(finalize_callback == nullptr ? &env->reflist : &env->finalizing_reflist); } -// When a RefBase is being deleted, it may have been queued to call its +TrackedFinalizer* TrackedFinalizer::New(napi_env env, + napi_finalize finalize_callback, + void* finalize_data, + void* finalize_hint) { + return new TrackedFinalizer( + env, finalize_callback, finalize_data, finalize_hint); +} + +// When a TrackedFinalizer is being deleted, it may have been queued to call its // finalizer. -RefBase::~RefBase() { +TrackedFinalizer::~TrackedFinalizer() { // Remove from the env's tracked list. Unlink(); // Try to remove the finalizer from the scheduled second pass callback. env_->DequeueFinalizer(this); } +void TrackedFinalizer::Finalize() { + FinalizeCore(/*deleteMe:*/ true); +} + +void TrackedFinalizer::FinalizeCore(bool deleteMe) { + // Swap out the field finalize_callback so that it can not be accidentally + // called more than once. + napi_finalize finalize_callback = finalize_callback_; + void* finalize_data = finalize_data_; + void* finalize_hint = finalize_hint_; + ResetFinalizer(); + + // Either the RefBase is going to be deleted in the finalize_callback or not, + // it should be removed from the tracked list. + Unlink(); + // If the finalize_callback is present, it should either delete the + // derived RefBase, or the RefBase ownership was set to Ownership::kRuntime + // and the deleteMe parameter is true. + if (finalize_callback != nullptr) { + env_->CallFinalizer(finalize_callback, finalize_data, finalize_hint); + } + + if (deleteMe) { + delete this; + } +} + +// Wrapper around v8impl::Persistent that implements reference counting. +RefBase::RefBase(napi_env env, + uint32_t initial_refcount, + Ownership ownership, + napi_finalize finalize_callback, + void* finalize_data, + void* finalize_hint) + : TrackedFinalizer(env, finalize_callback, finalize_data, finalize_hint), + refcount_(initial_refcount), + ownership_(ownership) {} + RefBase* RefBase::New(napi_env env, uint32_t initial_refcount, Ownership ownership, @@ -660,31 +718,9 @@ uint32_t RefBase::RefCount() { } void RefBase::Finalize() { - Ownership ownership = ownership_; - // Swap out the field finalize_callback so that it can not be accidentally - // called more than once. - napi_finalize finalize_callback = finalize_callback_; - void* finalize_data = finalize_data_; - void* finalize_hint = finalize_hint_; - ResetFinalizer(); - - // Either the RefBase is going to be deleted in the finalize_callback or not, - // it should be removed from the tracked list. - Unlink(); - // 1. If the finalize_callback is present, it should either delete the - // RefBase, or set ownership with Ownership::kRuntime. - // 2. If the finalizer is not present, the RefBase can be deleted after the - // call. - if (finalize_callback != nullptr) { - env_->CallFinalizer(finalize_callback, finalize_data, finalize_hint); - // No access to `this` after finalize_callback is called. - } - // If the RefBase is not Ownership::kRuntime, userland code should delete it. - // Now delete it if it is Ownership::kRuntime. - if (ownership == Ownership::kRuntime) { - delete this; - } + // Delete it if it is Ownership::kRuntime. + FinalizeCore(/*deleteMe:*/ ownership_ == Ownership::kRuntime); } template @@ -779,7 +815,7 @@ void Reference::WeakCallback(const v8::WeakCallbackInfo& data) { Reference* reference = data.GetParameter(); // The reference must be reset during the weak callback as the API protocol. reference->persistent_.Reset(); - reference->env_->EnqueueFinalizer(reference); + reference->env_->InvokeFinalizerFromGC(reference); } } // end of namespace v8impl @@ -1436,6 +1472,7 @@ napi_status NAPI_CDECL napi_is_array(napi_env env, napi_value value, bool* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); CHECK_ARG(env, result); @@ -1495,6 +1532,7 @@ napi_status NAPI_CDECL napi_get_prototype(napi_env env, napi_status NAPI_CDECL napi_create_object(napi_env env, napi_value* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, result); *result = v8impl::JsValueFromV8LocalValue(v8::Object::New(env->isolate)); @@ -1504,6 +1542,7 @@ napi_status NAPI_CDECL napi_create_object(napi_env env, napi_value* result) { napi_status NAPI_CDECL napi_create_array(napi_env env, napi_value* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, result); *result = v8impl::JsValueFromV8LocalValue(v8::Array::New(env->isolate)); @@ -1515,6 +1554,7 @@ napi_status NAPI_CDECL napi_create_array_with_length(napi_env env, size_t length, napi_value* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, result); *result = @@ -1615,6 +1655,7 @@ napi_status NAPI_CDECL napi_create_double(napi_env env, double value, napi_value* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, result); *result = @@ -1627,6 +1668,7 @@ napi_status NAPI_CDECL napi_create_int32(napi_env env, int32_t value, napi_value* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, result); *result = @@ -1639,6 +1681,7 @@ napi_status NAPI_CDECL napi_create_uint32(napi_env env, uint32_t value, napi_value* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, result); *result = v8impl::JsValueFromV8LocalValue( @@ -1651,6 +1694,7 @@ napi_status NAPI_CDECL napi_create_int64(napi_env env, int64_t value, napi_value* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, result); *result = v8impl::JsValueFromV8LocalValue( @@ -1663,6 +1707,7 @@ napi_status NAPI_CDECL napi_create_bigint_int64(napi_env env, int64_t value, napi_value* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, result); *result = @@ -1675,6 +1720,7 @@ napi_status NAPI_CDECL napi_create_bigint_uint64(napi_env env, uint64_t value, napi_value* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, result); *result = v8impl::JsValueFromV8LocalValue( @@ -1689,6 +1735,7 @@ napi_status NAPI_CDECL napi_create_bigint_words(napi_env env, const uint64_t* words, napi_value* result) { NAPI_PREAMBLE(env); + env->CheckGCAccess(); CHECK_ARG(env, words); CHECK_ARG(env, result); @@ -1709,6 +1756,7 @@ napi_status NAPI_CDECL napi_get_boolean(napi_env env, bool value, napi_value* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, result); v8::Isolate* isolate = env->isolate; @@ -1726,6 +1774,7 @@ napi_status NAPI_CDECL napi_create_symbol(napi_env env, napi_value description, napi_value* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, result); v8::Isolate* isolate = env->isolate; @@ -1748,6 +1797,7 @@ napi_status NAPI_CDECL node_api_symbol_for(napi_env env, size_t length, napi_value* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, result); napi_value js_description_string; @@ -1793,6 +1843,7 @@ napi_status NAPI_CDECL napi_create_error(napi_env env, napi_value msg, napi_value* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, msg); CHECK_ARG(env, result); @@ -1813,6 +1864,7 @@ napi_status NAPI_CDECL napi_create_type_error(napi_env env, napi_value msg, napi_value* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, msg); CHECK_ARG(env, result); @@ -1833,6 +1885,7 @@ napi_status NAPI_CDECL napi_create_range_error(napi_env env, napi_value msg, napi_value* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, msg); CHECK_ARG(env, result); @@ -1853,6 +1906,7 @@ napi_status NAPI_CDECL node_api_create_syntax_error(napi_env env, napi_value msg, napi_value* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, msg); CHECK_ARG(env, result); @@ -1874,6 +1928,7 @@ napi_status NAPI_CDECL napi_typeof(napi_env env, // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); CHECK_ARG(env, result); @@ -1913,6 +1968,7 @@ napi_status NAPI_CDECL napi_typeof(napi_env env, napi_status NAPI_CDECL napi_get_undefined(napi_env env, napi_value* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, result); *result = v8impl::JsValueFromV8LocalValue(v8::Undefined(env->isolate)); @@ -1922,6 +1978,7 @@ napi_status NAPI_CDECL napi_get_undefined(napi_env env, napi_value* result) { napi_status NAPI_CDECL napi_get_null(napi_env env, napi_value* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, result); *result = v8impl::JsValueFromV8LocalValue(v8::Null(env->isolate)); @@ -1967,6 +2024,7 @@ napi_status NAPI_CDECL napi_get_new_target(napi_env env, CHECK_ENV(env); CHECK_ARG(env, cbinfo); CHECK_ARG(env, result); + env->CheckGCAccess(); v8impl::CallbackWrapper* info = reinterpret_cast(cbinfo); @@ -2013,6 +2071,7 @@ napi_status NAPI_CDECL napi_call_function(napi_env env, napi_status NAPI_CDECL napi_get_global(napi_env env, napi_value* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, result); *result = v8impl::JsValueFromV8LocalValue(env->context()->Global()); @@ -2110,6 +2169,7 @@ napi_status NAPI_CDECL napi_is_error(napi_env env, // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot // throw JS exceptions. CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); CHECK_ARG(env, result); @@ -2125,6 +2185,7 @@ napi_status NAPI_CDECL napi_get_value_double(napi_env env, // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); CHECK_ARG(env, result); @@ -2142,6 +2203,7 @@ napi_status NAPI_CDECL napi_get_value_int32(napi_env env, // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); CHECK_ARG(env, result); @@ -2166,6 +2228,7 @@ napi_status NAPI_CDECL napi_get_value_uint32(napi_env env, // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); CHECK_ARG(env, result); @@ -2190,6 +2253,7 @@ napi_status NAPI_CDECL napi_get_value_int64(napi_env env, // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); CHECK_ARG(env, result); @@ -2223,6 +2287,7 @@ napi_status NAPI_CDECL napi_get_value_bigint_int64(napi_env env, int64_t* result, bool* lossless) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); CHECK_ARG(env, result); CHECK_ARG(env, lossless); @@ -2241,6 +2306,7 @@ napi_status NAPI_CDECL napi_get_value_bigint_uint64(napi_env env, uint64_t* result, bool* lossless) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); CHECK_ARG(env, result); CHECK_ARG(env, lossless); @@ -2260,6 +2326,7 @@ napi_status NAPI_CDECL napi_get_value_bigint_words(napi_env env, size_t* word_count, uint64_t* words) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); CHECK_ARG(env, word_count); @@ -2290,6 +2357,7 @@ napi_status NAPI_CDECL napi_get_value_bool(napi_env env, // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); CHECK_ARG(env, result); @@ -2312,6 +2380,7 @@ napi_status NAPI_CDECL napi_get_value_bool(napi_env env, napi_status NAPI_CDECL napi_get_value_string_latin1( napi_env env, napi_value value, char* buf, size_t bufsize, size_t* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); v8::Local val = v8impl::V8LocalValueFromJsValue(value); @@ -2350,6 +2419,7 @@ napi_status NAPI_CDECL napi_get_value_string_latin1( napi_status NAPI_CDECL napi_get_value_string_utf8( napi_env env, napi_value value, char* buf, size_t bufsize, size_t* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); v8::Local val = v8impl::V8LocalValueFromJsValue(value); @@ -2391,6 +2461,7 @@ napi_status NAPI_CDECL napi_get_value_string_utf16(napi_env env, size_t bufsize, size_t* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); v8::Local val = v8impl::V8LocalValueFromJsValue(value); @@ -2577,6 +2648,7 @@ napi_status NAPI_CDECL napi_get_value_external(napi_env env, napi_value value, void** result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); CHECK_ARG(env, result); @@ -2597,6 +2669,7 @@ napi_status NAPI_CDECL napi_create_reference(napi_env env, // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); CHECK_ARG(env, result); @@ -2621,6 +2694,7 @@ napi_status NAPI_CDECL napi_delete_reference(napi_env env, napi_ref ref) { // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, ref); delete reinterpret_cast(ref); @@ -2639,6 +2713,7 @@ napi_status NAPI_CDECL napi_reference_ref(napi_env env, // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, ref); v8impl::Reference* reference = reinterpret_cast(ref); @@ -2661,6 +2736,7 @@ napi_status NAPI_CDECL napi_reference_unref(napi_env env, // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, ref); v8impl::Reference* reference = reinterpret_cast(ref); @@ -2687,6 +2763,7 @@ napi_status NAPI_CDECL napi_get_reference_value(napi_env env, // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, ref); CHECK_ARG(env, result); @@ -2701,6 +2778,7 @@ napi_status NAPI_CDECL napi_open_handle_scope(napi_env env, // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, result); *result = v8impl::JsHandleScopeFromV8HandleScope( @@ -2714,6 +2792,7 @@ napi_status NAPI_CDECL napi_close_handle_scope(napi_env env, // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, scope); if (env->open_handle_scopes == 0) { return napi_handle_scope_mismatch; @@ -2729,6 +2808,7 @@ napi_status NAPI_CDECL napi_open_escapable_handle_scope( // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, result); *result = v8impl::JsEscapableHandleScopeFromV8EscapableHandleScope( @@ -2742,6 +2822,7 @@ napi_status NAPI_CDECL napi_close_escapable_handle_scope( // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, scope); if (env->open_handle_scopes == 0) { return napi_handle_scope_mismatch; @@ -2759,6 +2840,7 @@ napi_status NAPI_CDECL napi_escape_handle(napi_env env, // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, scope); CHECK_ARG(env, escapee); CHECK_ARG(env, result); @@ -2837,6 +2919,7 @@ napi_status NAPI_CDECL napi_is_exception_pending(napi_env env, bool* result) { // NAPI_PREAMBLE is not used here: this function must execute when there is a // pending exception. CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, result); *result = !env->last_exception.IsEmpty(); @@ -2848,6 +2931,7 @@ napi_status NAPI_CDECL napi_get_and_clear_last_exception(napi_env env, // NAPI_PREAMBLE is not used here: this function must execute when there is a // pending exception. CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, result); if (env->last_exception.IsEmpty()) { @@ -2865,6 +2949,7 @@ napi_status NAPI_CDECL napi_is_arraybuffer(napi_env env, napi_value value, bool* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); CHECK_ARG(env, result); @@ -2917,6 +3002,7 @@ napi_status NAPI_CDECL napi_get_arraybuffer_info(napi_env env, void** data, size_t* byte_length) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, arraybuffer); v8::Local value = v8impl::V8LocalValueFromJsValue(arraybuffer); @@ -2939,6 +3025,7 @@ napi_status NAPI_CDECL napi_is_typedarray(napi_env env, napi_value value, bool* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); CHECK_ARG(env, result); @@ -3025,6 +3112,7 @@ napi_status NAPI_CDECL napi_get_typedarray_info(napi_env env, napi_value* arraybuffer, size_t* byte_offset) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, typedarray); v8::Local value = v8impl::V8LocalValueFromJsValue(typedarray); @@ -3115,6 +3203,7 @@ napi_status NAPI_CDECL napi_is_dataview(napi_env env, napi_value value, bool* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); CHECK_ARG(env, result); @@ -3131,6 +3220,7 @@ napi_status NAPI_CDECL napi_get_dataview_info(napi_env env, napi_value* arraybuffer, size_t* byte_offset) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, dataview); v8::Local value = v8impl::V8LocalValueFromJsValue(dataview); @@ -3206,6 +3296,7 @@ napi_status NAPI_CDECL napi_is_promise(napi_env env, napi_value value, bool* is_promise) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); CHECK_ARG(env, is_promise); @@ -3232,6 +3323,7 @@ napi_status NAPI_CDECL napi_is_date(napi_env env, napi_value value, bool* is_date) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); CHECK_ARG(env, is_date); @@ -3244,6 +3336,7 @@ napi_status NAPI_CDECL napi_get_date_value(napi_env env, napi_value value, double* result) { NAPI_PREAMBLE(env); + env->CheckGCAccess(); CHECK_ARG(env, value); CHECK_ARG(env, result); @@ -3290,6 +3383,7 @@ napi_status NAPI_CDECL napi_add_finalizer(napi_env env, // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, js_object); CHECK_ARG(env, finalize_cb); @@ -3310,6 +3404,20 @@ napi_status NAPI_CDECL napi_add_finalizer(napi_env env, return napi_clear_last_error(env); } +#ifdef NAPI_EXPERIMENTAL + +napi_status NAPI_CDECL node_api_post_finalizer(napi_env env, + napi_finalize finalize_cb, + void* finalize_data, + void* finalize_hint) { + CHECK_ENV(env); + env->EnqueueFinalizer(v8impl::TrackedFinalizer::New( + env, finalize_cb, finalize_data, finalize_hint)); + return napi_clear_last_error(env); +} + +#endif + napi_status NAPI_CDECL napi_adjust_external_memory(napi_env env, int64_t change_in_bytes, int64_t* adjusted_value) { @@ -3355,6 +3463,7 @@ napi_status NAPI_CDECL napi_get_instance_data(napi_env env, void** data) { napi_status NAPI_CDECL napi_detach_arraybuffer(napi_env env, napi_value arraybuffer) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, arraybuffer); v8::Local value = v8impl::V8LocalValueFromJsValue(arraybuffer); @@ -3374,6 +3483,7 @@ napi_status NAPI_CDECL napi_is_detached_arraybuffer(napi_env env, napi_value arraybuffer, bool* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, arraybuffer); CHECK_ARG(env, result); diff --git a/src/js_native_api_v8.h b/src/js_native_api_v8.h index f7646778311bfd..6472d2ad7b8d18 100644 --- a/src/js_native_api_v8.h +++ b/src/js_native_api_v8.h @@ -105,6 +105,9 @@ struct napi_env__ { CallIntoModule([&](napi_env env) { cb(env, data, hint); }); } + // Invoke finalizer from V8 garbage collector. + void InvokeFinalizerFromGC(v8impl::RefTracker* finalizer); + // Enqueue the finalizer to the napi_env's own queue of the second pass // weak callback. // Implementation should drain the queue at the time it is safe to call @@ -130,6 +133,19 @@ struct napi_env__ { delete this; } + void CheckGCAccess() { + if (module_api_version == NAPI_VERSION_EXPERIMENTAL && in_gc_finalizer) { + v8impl::OnFatalError( + nullptr, + "Finalizer is calling a function that may affect GC state.\n" + "The finalizers are run directly from GC and must not affect GC " + "state.\n" + "Use `node_api_post_finalizer` from inside of the finalizer to work " + "around this issue.\n" + "It schedules the call as a new task in the event loop."); + } + } + v8::Isolate* const isolate; // Shortcut for context()->GetIsolate() v8impl::Persistent context_persistent; @@ -148,6 +164,7 @@ struct napi_env__ { int refs = 1; void* instance_data = nullptr; int32_t module_api_version = NODE_API_DEFAULT_MODULE_API_VERSION; + bool in_gc_finalizer = false; protected: // Should not be deleted directly. Delete with `napi_env__::DeleteMe()` @@ -211,6 +228,7 @@ inline napi_status napi_set_last_error(napi_env env, // NAPI_PREAMBLE is not wrapped in do..while: try_catch must have function scope #define NAPI_PREAMBLE(env) \ CHECK_ENV((env)); \ + (env)->CheckGCAccess(); \ RETURN_STATUS_IF_FALSE( \ (env), (env)->last_exception.IsEmpty(), napi_pending_exception); \ RETURN_STATUS_IF_FALSE((env), \ @@ -268,14 +286,6 @@ inline napi_status napi_set_last_error(napi_env env, } \ } while (0) -#define RETURN_STATUS_IF_FALSE_WITH_PREAMBLE(env, condition, status) \ - do { \ - if (!(condition)) { \ - return napi_set_last_error( \ - (env), try_catch.HasCaught() ? napi_pending_exception : (status)); \ - } \ - } while (0) - #define CHECK_MAYBE_EMPTY_WITH_PREAMBLE(env, maybe, status) \ RETURN_STATUS_IF_FALSE_WITH_PREAMBLE((env), !((maybe).IsEmpty()), (status)) @@ -363,8 +373,28 @@ enum class Ownership { kUserland, }; -// Wrapper around Finalizer that implements reference counting. -class RefBase : public Finalizer, public RefTracker { +// Wrapper around Finalizer that can be tracked. +class TrackedFinalizer : public Finalizer, public RefTracker { + protected: + TrackedFinalizer(napi_env env, + napi_finalize finalize_callback, + void* finalize_data, + void* finalize_hint); + + public: + static TrackedFinalizer* New(napi_env env, + napi_finalize finalize_callback, + void* finalize_data, + void* finalize_hint); + ~TrackedFinalizer() override; + + protected: + void Finalize() override; + void FinalizeCore(bool deleteMe); +}; + +// Wrapper around TrackedFinalizer that implements reference counting. +class RefBase : public TrackedFinalizer { protected: RefBase(napi_env env, uint32_t initial_refcount, @@ -380,7 +410,6 @@ class RefBase : public Finalizer, public RefTracker { napi_finalize finalize_callback, void* finalize_data, void* finalize_hint); - virtual ~RefBase(); void* Data(); uint32_t Ref(); diff --git a/src/js_native_api_v8_internals.h b/src/js_native_api_v8_internals.h index 4f1b94d3d0c9d7..7bf3bf0fa7e1a2 100644 --- a/src/js_native_api_v8_internals.h +++ b/src/js_native_api_v8_internals.h @@ -17,6 +17,7 @@ #include "env.h" #include "gtest/gtest_prod.h" +#include "node_errors.h" #include "node_internals.h" #define NAPI_ARRAYSIZE(array) node::arraysize((array)) @@ -34,6 +35,11 @@ using Persistent = v8::Global; using PersistentToLocal = node::PersistentToLocal; +[[noreturn]] inline void OnFatalError(const char* location, + const char* message) { + node::OnFatalError(location, message); +} + } // end of namespace v8impl #endif // SRC_JS_NATIVE_API_V8_INTERNALS_H_ diff --git a/src/memory_tracker-inl.h b/src/memory_tracker-inl.h index a4970d9392faa7..0e4f2870a5aae5 100644 --- a/src/memory_tracker-inl.h +++ b/src/memory_tracker-inl.h @@ -4,6 +4,7 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include "memory_tracker.h" +#include "util-inl.h" namespace node { @@ -269,13 +270,6 @@ void MemoryTracker::TrackInlineField(const char* name, TrackInlineFieldWithSize(name, sizeof(value), "uv_async_t"); } -template -void MemoryTracker::TrackField(const char* name, - const AliasedBufferBase& value, - const char* node_name) { - TrackField(name, value.GetJSArray(), "AliasedBuffer"); -} - void MemoryTracker::Track(const MemoryRetainer* retainer, const char* edge_name) { v8::HandleScope handle_scope(isolate_); diff --git a/src/memory_tracker.h b/src/memory_tracker.h index 4682f25916e52d..cae4e5c7a663c1 100644 --- a/src/memory_tracker.h +++ b/src/memory_tracker.h @@ -2,7 +2,6 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS -#include "aliased_buffer.h" #include "v8-profiler.h" #include @@ -13,8 +12,15 @@ #include #include +namespace v8 { +class BackingStore; +} + namespace node { +template +struct MallocedBuffer; + // Set the node name of a MemoryRetainer to klass #define SET_MEMORY_INFO_NAME(Klass) \ inline const char* MemoryInfoName() const override { return #Klass; } @@ -231,10 +237,6 @@ class MemoryTracker { inline void TrackInlineField(const char* edge_name, const uv_async_t& value, const char* node_name = nullptr); - template - inline void TrackField(const char* edge_name, - const AliasedBufferBase& value, - const char* node_name = nullptr); // Put a memory container into the graph, create an edge from // the current node if there is one on the stack. diff --git a/src/module_wrap.cc b/src/module_wrap.cc index 0645b3ddf506df..21b9a702aebaf4 100644 --- a/src/module_wrap.cc +++ b/src/module_wrap.cc @@ -4,6 +4,7 @@ #include "memory_tracker-inl.h" #include "node_contextify.h" #include "node_errors.h" +#include "node_external_reference.h" #include "node_internals.h" #include "node_process-inl.h" #include "node_watchdog.h" @@ -249,19 +250,19 @@ void ModuleWrap::New(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(that); } -static Local createImportAssertionContainer(Environment* env, - Isolate* isolate, Local raw_assertions) { - Local assertions = - Object::New(isolate, v8::Null(env->isolate()), nullptr, nullptr, 0); - for (int i = 0; i < raw_assertions->Length(); i += 3) { - assertions - ->Set(env->context(), - raw_assertions->Get(env->context(), i).As(), - raw_assertions->Get(env->context(), i + 1).As()) - .ToChecked(); +static Local createImportAttributesContainer( + Environment* env, Isolate* isolate, Local raw_attributes) { + Local attributes = + Object::New(isolate, v8::Null(env->isolate()), nullptr, nullptr, 0); + for (int i = 0; i < raw_attributes->Length(); i += 3) { + attributes + ->Set(env->context(), + raw_attributes->Get(env->context(), i).As(), + raw_attributes->Get(env->context(), i + 1).As()) + .ToChecked(); } - return assertions; + return attributes; } void ModuleWrap::Link(const FunctionCallbackInfo& args) { @@ -297,13 +298,13 @@ void ModuleWrap::Link(const FunctionCallbackInfo& args) { Utf8Value specifier_utf8(env->isolate(), specifier); std::string specifier_std(*specifier_utf8, specifier_utf8.length()); - Local raw_assertions = module_request->GetImportAssertions(); - Local assertions = - createImportAssertionContainer(env, isolate, raw_assertions); + Local raw_attributes = module_request->GetImportAssertions(); + Local attributes = + createImportAttributesContainer(env, isolate, raw_attributes); Local argv[] = { specifier, - assertions, + attributes, }; MaybeLocal maybe_resolve_return_value = @@ -499,7 +500,7 @@ void ModuleWrap::GetError(const FunctionCallbackInfo& args) { MaybeLocal ModuleWrap::ResolveModuleCallback( Local context, Local specifier, - Local import_assertions, + Local import_attributes, Local referrer) { Environment* env = Environment::GetCurrent(context); if (env == nullptr) { @@ -552,7 +553,7 @@ static MaybeLocal ImportModuleDynamically( Local host_defined_options, Local resource_name, Local specifier, - Local import_assertions) { + Local import_attributes) { Isolate* isolate = context->GetIsolate(); Environment* env = Environment::GetCurrent(context); if (env == nullptr) { @@ -601,13 +602,13 @@ static MaybeLocal ImportModuleDynamically( UNREACHABLE(); } - Local assertions = - createImportAssertionContainer(env, isolate, import_assertions); + Local attributes = + createImportAttributesContainer(env, isolate, import_attributes); Local import_args[] = { object, Local(specifier), - assertions, + attributes, }; Local result; @@ -808,8 +809,27 @@ void ModuleWrap::Initialize(Local target, #undef V } +void ModuleWrap::RegisterExternalReferences( + ExternalReferenceRegistry* registry) { + registry->Register(New); + + registry->Register(Link); + registry->Register(Instantiate); + registry->Register(Evaluate); + registry->Register(SetSyntheticExport); + registry->Register(CreateCachedData); + registry->Register(GetNamespace); + registry->Register(GetStatus); + registry->Register(GetError); + registry->Register(GetStaticDependencySpecifiers); + + registry->Register(SetImportModuleDynamicallyCallback); + registry->Register(SetInitializeImportMetaObjectCallback); +} } // namespace loader } // namespace node NODE_BINDING_CONTEXT_AWARE_INTERNAL(module_wrap, node::loader::ModuleWrap::Initialize) +NODE_BINDING_EXTERNAL_REFERENCE( + module_wrap, node::loader::ModuleWrap::RegisterExternalReferences) diff --git a/src/module_wrap.h b/src/module_wrap.h index 58b233d036515c..ce4610a461a2b4 100644 --- a/src/module_wrap.h +++ b/src/module_wrap.h @@ -11,6 +11,7 @@ namespace node { class Environment; +class ExternalReferenceRegistry; namespace contextify { class ContextifyContext; @@ -44,6 +45,7 @@ class ModuleWrap : public BaseObject { v8::Local unused, v8::Local context, void* priv); + static void RegisterExternalReferences(ExternalReferenceRegistry* registry); static void HostInitializeImportMetaObjectCallback( v8::Local context, v8::Local module, @@ -96,7 +98,7 @@ class ModuleWrap : public BaseObject { static v8::MaybeLocal ResolveModuleCallback( v8::Local context, v8::Local specifier, - v8::Local import_assertions, + v8::Local import_attributes, v8::Local referrer); static ModuleWrap* GetFromModule(node::Environment*, v8::Local); diff --git a/src/node.cc b/src/node.cc index 96cdcd3064f963..0c75b5a08edd05 100644 --- a/src/node.cc +++ b/src/node.cc @@ -132,8 +132,6 @@ namespace node { -using builtins::BuiltinLoader; - using v8::EscapableHandleScope; using v8::Isolate; using v8::Local; @@ -275,15 +273,7 @@ MaybeLocal StartExecution(Environment* env, const char* main_script_id) { CHECK_NOT_NULL(main_script_id); Realm* realm = env->principal_realm(); - // Arguments must match the parameters specified in - // BuiltinLoader::LookupAndCompile(). - std::vector> arguments = {env->process_object(), - env->builtin_module_require(), - env->internal_binding_loader(), - env->primordials()}; - - return scope.EscapeMaybe( - realm->ExecuteBootstrapper(main_script_id, &arguments)); + return scope.EscapeMaybe(realm->ExecuteBootstrapper(main_script_id)); } MaybeLocal StartExecution(Environment* env, StartExecutionCallback cb) { @@ -1222,9 +1212,6 @@ int LoadSnapshotDataAndRun(const SnapshotData** snapshot_data_ptr, } } - if ((*snapshot_data_ptr) != nullptr) { - BuiltinLoader::RefreshCodeCache((*snapshot_data_ptr)->code_cache); - } NodeMainInstance main_instance(*snapshot_data_ptr, uv_default_loop(), per_process::v8_platform.Platform(), diff --git a/src/node_api.cc b/src/node_api.cc index 7537dc20b2bd82..7285b71f54231f 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -82,9 +82,8 @@ void node_napi_env__::trigger_fatal_exception(v8::Local local_err) { node::errors::TriggerUncaughtException(isolate, local_err, local_msg); } -// option enforceUncaughtExceptionPolicy is added for not breaking existing -// running n-api add-ons, and should be deprecated in the next major Node.js -// release. +// The option enforceUncaughtExceptionPolicy is added for not breaking existing +// running Node-API add-ons. template void node_napi_env__::CallbackIntoModule(T&& call) { CallIntoModule(call, [](napi_env env_, v8::Local local_err) { @@ -93,19 +92,24 @@ void node_napi_env__::CallbackIntoModule(T&& call) { return; } node::Environment* node_env = env->node_env(); - if (!node_env->options()->force_node_api_uncaught_exceptions_policy && + // If the module api version is less than NAPI_VERSION_EXPERIMENTAL, + // and the option --force-node-api-uncaught-exceptions-policy is not + // specified, emit a warning about the uncaught exception instead of + // triggering uncaught exception event. + if (env->module_api_version < NAPI_VERSION_EXPERIMENTAL && + !node_env->options()->force_node_api_uncaught_exceptions_policy && !enforceUncaughtExceptionPolicy) { ProcessEmitDeprecationWarning( node_env, "Uncaught N-API callback exception detected, please run node " - "with option --force-node-api-uncaught-exceptions-policy=true" + "with option --force-node-api-uncaught-exceptions-policy=true " "to handle those exceptions properly.", "DEP0168"); return; } // If there was an unhandled exception in the complete callback, // report it as a fatal exception. (There is no JavaScript on the - // callstack that can possibly handle it.) + // call stack that can possibly handle it.) env->trigger_fatal_exception(local_err); }); } @@ -913,6 +917,7 @@ napi_status NAPI_CDECL napi_async_init(napi_env env, napi_value async_resource_name, napi_async_context* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, async_resource_name); CHECK_ARG(env, result); @@ -946,6 +951,7 @@ napi_status NAPI_CDECL napi_async_init(napi_env env, napi_status NAPI_CDECL napi_async_destroy(napi_env env, napi_async_context async_context) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, async_context); v8impl::AsyncContext* node_async_context = @@ -1095,6 +1101,7 @@ napi_status NAPI_CDECL napi_is_buffer(napi_env env, napi_value value, bool* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); CHECK_ARG(env, result); @@ -1107,6 +1114,7 @@ napi_status NAPI_CDECL napi_get_buffer_info(napi_env env, void** data, size_t* length) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, value); v8::Local buffer = v8impl::V8LocalValueFromJsValue(value); @@ -1228,6 +1236,7 @@ napi_create_async_work(napi_env env, void* data, napi_async_work* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, execute); CHECK_ARG(env, result); @@ -1258,6 +1267,7 @@ napi_create_async_work(napi_env env, napi_status NAPI_CDECL napi_delete_async_work(napi_env env, napi_async_work work) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, work); uvimpl::Work::Delete(reinterpret_cast(work)); @@ -1312,6 +1322,7 @@ napi_create_threadsafe_function(napi_env env, napi_threadsafe_function_call_js call_js_cb, napi_threadsafe_function* result) { CHECK_ENV(env); + env->CheckGCAccess(); CHECK_ARG(env, async_resource_name); RETURN_STATUS_IF_FALSE(env, initial_thread_count > 0, napi_invalid_arg); CHECK_ARG(env, result); diff --git a/src/node_api.h b/src/node_api.h index 03454683c401d4..49a23aed9c6e90 100644 --- a/src/node_api.h +++ b/src/node_api.h @@ -1,11 +1,11 @@ #ifndef SRC_NODE_API_H_ #define SRC_NODE_API_H_ -#ifdef BUILDING_NODE_EXTENSION +#if defined(BUILDING_NODE_EXTENSION) && !defined(NAPI_EXTERN) #ifdef _WIN32 // Building native addon against node #define NAPI_EXTERN __declspec(dllimport) -#elif defined(__wasm32__) +#elif defined(__wasm__) #define NAPI_EXTERN __attribute__((__import_module__("napi"))) #endif #endif @@ -17,8 +17,13 @@ struct uv_loop_s; // Forward declaration. #ifdef _WIN32 #define NAPI_MODULE_EXPORT __declspec(dllexport) #else +#ifdef __EMSCRIPTEN__ +#define NAPI_MODULE_EXPORT \ + __attribute__((visibility("default"))) __attribute__((used)) +#else #define NAPI_MODULE_EXPORT __attribute__((visibility("default"))) #endif +#endif #if defined(__GNUC__) #define NAPI_NO_RETURN __attribute__((noreturn)) @@ -30,7 +35,7 @@ struct uv_loop_s; // Forward declaration. typedef napi_value(NAPI_CDECL* napi_addon_register_func)(napi_env env, napi_value exports); -typedef int32_t(NAPI_CDECL* node_api_addon_get_api_version_func)(); +typedef int32_t(NAPI_CDECL* node_api_addon_get_api_version_func)(void); // Used by deprecated registration method napi_module_register. typedef struct napi_module { @@ -49,7 +54,7 @@ typedef struct napi_module { NAPI_MODULE_INITIALIZER_X_HELPER(base, version) #define NAPI_MODULE_INITIALIZER_X_HELPER(base, version) base##version -#ifdef __wasm32__ +#ifdef __wasm__ #define NAPI_MODULE_INITIALIZER_BASE napi_register_wasm_v #else #define NAPI_MODULE_INITIALIZER_BASE napi_register_module_v @@ -66,7 +71,7 @@ typedef struct napi_module { #define NAPI_MODULE_INIT() \ EXTERN_C_START \ - NAPI_MODULE_EXPORT int32_t NODE_API_MODULE_GET_API_VERSION() { \ + NAPI_MODULE_EXPORT int32_t NODE_API_MODULE_GET_API_VERSION(void) { \ return NAPI_VERSION; \ } \ NAPI_MODULE_EXPORT napi_value NAPI_MODULE_INITIALIZER(napi_env env, \ @@ -143,7 +148,6 @@ NAPI_EXTERN napi_status NAPI_CDECL napi_get_buffer_info(napi_env env, void** data, size_t* length); -#ifndef __wasm32__ // Methods to manage simple async operations NAPI_EXTERN napi_status NAPI_CDECL napi_create_async_work(napi_env env, @@ -159,7 +163,6 @@ NAPI_EXTERN napi_status NAPI_CDECL napi_queue_async_work(napi_env env, napi_async_work work); NAPI_EXTERN napi_status NAPI_CDECL napi_cancel_async_work(napi_env env, napi_async_work work); -#endif // __wasm32__ // version management NAPI_EXTERN napi_status NAPI_CDECL @@ -197,7 +200,6 @@ napi_close_callback_scope(napi_env env, napi_callback_scope scope); #if NAPI_VERSION >= 4 -#ifndef __wasm32__ // Calling into JS from other threads NAPI_EXTERN napi_status NAPI_CDECL napi_create_threadsafe_function(napi_env env, @@ -231,7 +233,6 @@ napi_unref_threadsafe_function(napi_env env, napi_threadsafe_function func); NAPI_EXTERN napi_status NAPI_CDECL napi_ref_threadsafe_function(napi_env env, napi_threadsafe_function func); -#endif // __wasm32__ #endif // NAPI_VERSION >= 4 diff --git a/src/node_binding.cc b/src/node_binding.cc index 259ce86b4c443c..502f93845ac154 100644 --- a/src/node_binding.cc +++ b/src/node_binding.cc @@ -110,6 +110,12 @@ NODE_BUILTIN_BINDINGS(V) #undef V +#define V(modname) \ + void _register_isolate_##modname(node::IsolateData* isolate_data, \ + v8::Local target); +NODE_BINDINGS_WITH_PER_ISOLATE_INIT(V) +#undef V + #ifdef _AIX // On AIX, dlopen() behaves differently from other operating systems, in that // it returns unique values from each call, rather than identical values, when @@ -237,9 +243,12 @@ static bool libc_may_be_musl() { return false; } namespace node { using v8::Context; +using v8::EscapableHandleScope; using v8::Exception; -using v8::Function; using v8::FunctionCallbackInfo; +using v8::FunctionTemplate; +using v8::HandleScope; +using v8::Isolate; using v8::Local; using v8::Object; using v8::String; @@ -571,50 +580,86 @@ inline struct node_module* FindModule(struct node_module* list, return mp; } -static Local InitInternalBinding(Environment* env, - node_module* mod, - Local module) { - // Internal bindings don't have a "module" object, only exports. - Local ctor = env->binding_data_ctor_template() - ->GetFunction(env->context()) - .ToLocalChecked(); - Local exports = ctor->NewInstance(env->context()).ToLocalChecked(); +void CreateInternalBindingTemplates(IsolateData* isolate_data) { +#define V(modname) \ + do { \ + Local templ = \ + FunctionTemplate::New(isolate_data->isolate()); \ + templ->InstanceTemplate()->SetInternalFieldCount( \ + BaseObject::kInternalFieldCount); \ + templ->Inherit(BaseObject::GetConstructorTemplate(isolate_data)); \ + _register_isolate_##modname(isolate_data, templ); \ + isolate_data->set_##modname##_binding(templ); \ + } while (0); + NODE_BINDINGS_WITH_PER_ISOLATE_INIT(V) +#undef V +} + +static Local GetInternalBindingExportObject(IsolateData* isolate_data, + const char* mod_name, + Local context) { + Local ctor; +#define V(name) \ + if (strcmp(mod_name, #name) == 0) { \ + ctor = isolate_data->name##_binding(); \ + } else // NOLINT(readability/braces) + NODE_BINDINGS_WITH_PER_ISOLATE_INIT(V) +#undef V + { + ctor = isolate_data->binding_data_ctor_template(); + } + + Local obj = ctor->GetFunction(context) + .ToLocalChecked() + ->NewInstance(context) + .ToLocalChecked(); + return obj; +} + +static Local InitInternalBinding(Realm* realm, node_module* mod) { + EscapableHandleScope scope(realm->isolate()); + Local context = realm->context(); + Local exports = GetInternalBindingExportObject( + realm->isolate_data(), mod->nm_modname, context); CHECK_NULL(mod->nm_register_func); CHECK_NOT_NULL(mod->nm_context_register_func); - Local unused = Undefined(env->isolate()); - mod->nm_context_register_func(exports, unused, env->context(), mod->nm_priv); - return exports; + Local unused = Undefined(realm->isolate()); + // Internal bindings don't have a "module" object, only exports. + mod->nm_context_register_func(exports, unused, context, mod->nm_priv); + return scope.Escape(exports); } void GetInternalBinding(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); + Realm* realm = Realm::GetCurrent(args); + Isolate* isolate = realm->isolate(); + HandleScope scope(isolate); + Local context = realm->context(); CHECK(args[0]->IsString()); Local module = args[0].As(); - node::Utf8Value module_v(env->isolate(), module); + node::Utf8Value module_v(isolate, module); Local exports; node_module* mod = FindModule(modlist_internal, *module_v, NM_F_INTERNAL); if (mod != nullptr) { - exports = InitInternalBinding(env, mod, module); - env->internal_bindings.insert(mod); + exports = InitInternalBinding(realm, mod); + realm->internal_bindings.insert(mod); } else if (!strcmp(*module_v, "constants")) { - exports = Object::New(env->isolate()); - CHECK( - exports->SetPrototype(env->context(), Null(env->isolate())).FromJust()); - DefineConstants(env->isolate(), exports); + exports = Object::New(isolate); + CHECK(exports->SetPrototype(context, Null(isolate)).FromJust()); + DefineConstants(isolate, exports); } else if (!strcmp(*module_v, "natives")) { - exports = builtins::BuiltinLoader::GetSourceObject(env->context()); + exports = realm->env()->builtin_loader()->GetSourceObject(context); // Legacy feature: process.binding('natives').config contains stringified // config.gypi CHECK(exports - ->Set(env->context(), - env->config_string(), - builtins::BuiltinLoader::GetConfigString(env->isolate())) + ->Set(context, + realm->isolate_data()->config_string(), + realm->env()->builtin_loader()->GetConfigString(isolate)) .FromJust()); } else { - return THROW_ERR_INVALID_MODULE(env, "No such binding: %s", *module_v); + return THROW_ERR_INVALID_MODULE(isolate, "No such binding: %s", *module_v); } args.GetReturnValue().Set(exports); diff --git a/src/node_binding.h b/src/node_binding.h index 32106afb0b7260..637f3e010acb63 100644 --- a/src/node_binding.h +++ b/src/node_binding.h @@ -24,6 +24,8 @@ static_assert(static_cast(NM_F_LINKED) == static_cast(node::ModuleFlags::kLinked), "NM_F_LINKED != node::ModuleFlags::kLinked"); +#define NODE_BINDINGS_WITH_PER_ISOLATE_INIT(V) V(builtins) + #define NODE_BINDING_CONTEXT_AWARE_CPP(modname, regfunc, priv, flags) \ static node::node_module _module = { \ NODE_MODULE_VERSION, \ @@ -51,9 +53,20 @@ node::addon_context_register_func get_node_api_context_register_func( namespace node { +// Define a node internal binding that may be loaded in a context of +// a node::Environment. +// If an internal binding needs initializing per-isolate templates, define +// with NODE_BINDING_PER_ISOLATE_INIT too. #define NODE_BINDING_CONTEXT_AWARE_INTERNAL(modname, regfunc) \ NODE_BINDING_CONTEXT_AWARE_CPP(modname, regfunc, nullptr, NM_F_INTERNAL) +// Define a per-isolate initialization function for a node internal binding. +#define NODE_BINDING_PER_ISOLATE_INIT(modname, per_isolate_func) \ + void _register_isolate_##modname(node::IsolateData* isolate_data, \ + v8::Local target) { \ + per_isolate_func(isolate_data, target); \ + } + // Globals per process // This is set by node::Init() which is used by embedders extern bool node_is_initialized; @@ -94,6 +107,8 @@ class DLib { // use the __attribute__((constructor)). Need to // explicitly call the _register* functions. void RegisterBuiltinBindings(); +// Create per-isolate templates for the internal bindings. +void CreateInternalBindingTemplates(IsolateData* isolate_data); void GetInternalBinding(const v8::FunctionCallbackInfo& args); void GetLinkedBinding(const v8::FunctionCallbackInfo& args); void DLOpen(const v8::FunctionCallbackInfo& args); diff --git a/src/node_blob.h b/src/node_blob.h index d3426d05d09dcd..08d354e2366a69 100644 --- a/src/node_blob.h +++ b/src/node_blob.h @@ -147,9 +147,7 @@ class BlobBindingData : public SnapshotableObject { SERIALIZABLE_OBJECT_METHODS() - static constexpr FastStringKey type_name{"node::BlobBindingData"}; - static constexpr EmbedderObjectType type_int = - EmbedderObjectType::k_blob_binding_data; + SET_BINDING_ID(blob_binding_data) void MemoryInfo(MemoryTracker* tracker) const override; SET_SELF_SIZE(BlobBindingData) diff --git a/src/node_builtins.cc b/src/node_builtins.cc index 356ec3acd0bf3a..30b08ece2a75f0 100644 --- a/src/node_builtins.cc +++ b/src/node_builtins.cc @@ -3,6 +3,7 @@ #include "env-inl.h" #include "node_external_reference.h" #include "node_internals.h" +#include "node_threadsafe_cow-inl.h" #include "simdutf.h" #include "util-inl.h" @@ -14,6 +15,7 @@ using v8::DEFAULT; using v8::EscapableHandleScope; using v8::Function; using v8::FunctionCallbackInfo; +using v8::FunctionTemplate; using v8::IntegrityLevel; using v8::Isolate; using v8::Local; @@ -21,17 +23,18 @@ using v8::MaybeLocal; using v8::Name; using v8::None; using v8::Object; +using v8::ObjectTemplate; using v8::PropertyCallbackInfo; using v8::ScriptCompiler; using v8::ScriptOrigin; using v8::Set; using v8::SideEffectType; using v8::String; +using v8::Undefined; using v8::Value; -BuiltinLoader BuiltinLoader::instance_; - -BuiltinLoader::BuiltinLoader() : config_(GetConfig()), has_code_cache_(false) { +BuiltinLoader::BuiltinLoader() + : config_(GetConfig()), code_cache_(std::make_shared()) { LoadJavaScriptSource(); #ifdef NODE_SHARED_BUILTIN_CJS_MODULE_LEXER_LEXER_PATH AddExternalizedBuiltin( @@ -51,25 +54,21 @@ BuiltinLoader::BuiltinLoader() : config_(GetConfig()), has_code_cache_(false) { #endif // NODE_SHARED_BUILTIN_UNDICI_UNDICI_PATH } -BuiltinLoader* BuiltinLoader::GetInstance() { - return &instance_; -} - bool BuiltinLoader::Exists(const char* id) { - auto& source = GetInstance()->source_; - return source.find(id) != source.end(); + auto source = source_.read(); + return source->find(id) != source->end(); } bool BuiltinLoader::Add(const char* id, const UnionBytes& source) { - auto result = GetInstance()->source_.emplace(id, source); + auto result = source_.write()->emplace(id, source); return result.second; } Local BuiltinLoader::GetSourceObject(Local context) { Isolate* isolate = context->GetIsolate(); Local out = Object::New(isolate); - auto& source = GetInstance()->source_; - for (auto const& x : source) { + auto source = source_.read(); + for (auto const& x : *source) { Local key = OneByteString(isolate, x.first.c_str(), x.first.size()); out->Set(context, key, x.second.ToStringChecked(isolate)).FromJust(); } @@ -77,23 +76,21 @@ Local BuiltinLoader::GetSourceObject(Local context) { } Local BuiltinLoader::GetConfigString(Isolate* isolate) { - return GetInstance()->config_.ToStringChecked(isolate); + return config_.ToStringChecked(isolate); } -std::vector BuiltinLoader::GetBuiltinIds() { +std::vector BuiltinLoader::GetBuiltinIds() const { std::vector ids; - ids.reserve(source_.size()); - for (auto const& x : source_) { + auto source = source_.read(); + ids.reserve(source->size()); + for (auto const& x : *source) { ids.emplace_back(x.first); } return ids; } -void BuiltinLoader::InitializeBuiltinCategories() { - if (builtin_categories_.is_initialized) { - DCHECK(!builtin_categories_.can_be_required.empty()); - return; - } +BuiltinLoader::BuiltinCategories BuiltinLoader::GetBuiltinCategories() const { + BuiltinCategories builtin_categories; std::vector prefixes = { #if !HAVE_OPENSSL @@ -107,10 +104,10 @@ void BuiltinLoader::InitializeBuiltinCategories() { "internal/main/" }; - builtin_categories_.can_be_required.emplace( + builtin_categories.can_be_required.emplace( "internal/deps/cjs-module-lexer/lexer"); - builtin_categories_.cannot_be_required = std::set { + builtin_categories.cannot_be_required = std::set { #if !HAVE_INSPECTOR "inspector", "internal/util/inspector", #endif // !HAVE_INSPECTOR @@ -133,55 +130,35 @@ void BuiltinLoader::InitializeBuiltinCategories() { "internal/v8_prof_processor", }; - for (auto const& x : source_) { + auto source = source_.read(); + for (auto const& x : *source) { const std::string& id = x.first; for (auto const& prefix : prefixes) { if (prefix.length() > id.length()) { continue; } if (id.find(prefix) == 0 && - builtin_categories_.can_be_required.count(id) == 0) { - builtin_categories_.cannot_be_required.emplace(id); + builtin_categories.can_be_required.count(id) == 0) { + builtin_categories.cannot_be_required.emplace(id); } } } - for (auto const& x : source_) { + for (auto const& x : *source) { const std::string& id = x.first; - if (0 == builtin_categories_.cannot_be_required.count(id)) { - builtin_categories_.can_be_required.emplace(id); + if (0 == builtin_categories.cannot_be_required.count(id)) { + builtin_categories.can_be_required.emplace(id); } } - builtin_categories_.is_initialized = true; -} - -const std::set& BuiltinLoader::GetCannotBeRequired() { - InitializeBuiltinCategories(); - return builtin_categories_.cannot_be_required; -} - -const std::set& BuiltinLoader::GetCanBeRequired() { - InitializeBuiltinCategories(); - return builtin_categories_.can_be_required; + return builtin_categories; } -bool BuiltinLoader::CanBeRequired(const char* id) { - return GetCanBeRequired().count(id) == 1; -} - -bool BuiltinLoader::CannotBeRequired(const char* id) { - return GetCannotBeRequired().count(id) == 1; -} - -BuiltinCodeCacheMap* BuiltinLoader::code_cache() { - return &code_cache_; -} - -ScriptCompiler::CachedData* BuiltinLoader::GetCodeCache(const char* id) const { - Mutex::ScopedLock lock(code_cache_mutex_); - const auto it = code_cache_.find(id); - if (it == code_cache_.end()) { +const ScriptCompiler::CachedData* BuiltinLoader::GetCodeCache( + const char* id) const { + RwLock::ScopedReadLock lock(code_cache_->mutex); + const auto it = code_cache_->map.find(id); + if (it == code_cache_->map.end()) { // The module has not been compiled before. return nullptr; } @@ -206,12 +183,13 @@ static std::string OnDiskFileName(const char* id) { #endif // NODE_BUILTIN_MODULES_PATH MaybeLocal BuiltinLoader::LoadBuiltinSource(Isolate* isolate, - const char* id) { + const char* id) const { + auto source = source_.read(); #ifdef NODE_BUILTIN_MODULES_PATH if (strncmp(id, "embedder_main_", strlen("embedder_main_")) == 0) { #endif // NODE_BUILTIN_MODULES_PATH - const auto source_it = source_.find(id); - if (UNLIKELY(source_it == source_.end())) { + const auto source_it = source->find(id); + if (UNLIKELY(source_it == source->end())) { fprintf(stderr, "Cannot find native builtin: \"%s\".\n", id); ABORT(); } @@ -236,14 +214,30 @@ MaybeLocal BuiltinLoader::LoadBuiltinSource(Isolate* isolate, #endif // NODE_BUILTIN_MODULES_PATH } +namespace { +static Mutex externalized_builtins_mutex; +std::unordered_map externalized_builtin_sources; +} // namespace + void BuiltinLoader::AddExternalizedBuiltin(const char* id, const char* filename) { std::string source; - int r = ReadFileSync(&source, filename); - if (r != 0) { - fprintf( - stderr, "Cannot load externalized builtin: \"%s:%s\".\n", id, filename); - ABORT(); + { + Mutex::ScopedLock lock(externalized_builtins_mutex); + auto it = externalized_builtin_sources.find(id); + if (it != externalized_builtin_sources.end()) { + source = it->second; + } else { + int r = ReadFileSync(&source, filename); + if (r != 0) { + fprintf(stderr, + "Cannot load externalized builtin: \"%s:%s\".\n", + id, + filename); + ABORT(); + } + externalized_builtin_sources[id] = source; + } } Add(id, source); @@ -285,12 +279,12 @@ MaybeLocal BuiltinLoader::LookupAndCompileInternal( // `CompileFunction()` call below, because this function may recurse if // there is a syntax error during bootstrap (because the fatal exception // handler is invoked, which may load built-in modules). - Mutex::ScopedLock lock(code_cache_mutex_); - auto cache_it = code_cache_.find(id); - if (cache_it != code_cache_.end()) { + RwLock::ScopedLock lock(code_cache_->mutex); + auto cache_it = code_cache_->map.find(id); + if (cache_it != code_cache_->map.end()) { // Transfer ownership to ScriptCompiler::Source later. cached_data = cache_it->second.release(); - code_cache_.erase(cache_it); + code_cache_->map.erase(cache_it); } } @@ -351,31 +345,26 @@ MaybeLocal BuiltinLoader::LookupAndCompileInternal( CHECK_NOT_NULL(new_cached_data); { - Mutex::ScopedLock lock(code_cache_mutex_); - const auto it = code_cache_.find(id); - // TODO(joyeecheung): it's safer for each thread to have its own - // copy of the code cache map. - if (it == code_cache_.end()) { - code_cache_.emplace(id, std::move(new_cached_data)); - } else { - it->second.reset(new_cached_data.release()); - } + RwLock::ScopedLock lock(code_cache_->mutex); + code_cache_->map[id] = std::move(new_cached_data); } return scope.Escape(fun); } -MaybeLocal BuiltinLoader::LookupAndCompile( - Local context, - const char* id, - Environment* optional_env) { +// Returns Local of the compiled module if return_code_cache +// is false (we are only compiling the function). +// Otherwise return a Local containing the cache. +MaybeLocal BuiltinLoader::LookupAndCompile(Local context, + const char* id, + Realm* optional_realm) { Result result; std::vector> parameters; Isolate* isolate = context->GetIsolate(); // Detects parameters of the scripts based on module ids. - // internal/bootstrap/loaders: process, getLinkedBinding, - // getInternalBinding, primordials - if (strcmp(id, "internal/bootstrap/loaders") == 0) { + // internal/bootstrap/realm: process, getLinkedBinding, + // getInternalBinding, primordials + if (strcmp(id, "internal/bootstrap/realm") == 0) { parameters = { FIXED_ONE_BYTE_STRING(isolate, "process"), FIXED_ONE_BYTE_STRING(isolate, "getLinkedBinding"), @@ -390,8 +379,12 @@ MaybeLocal BuiltinLoader::LookupAndCompile( FIXED_ONE_BYTE_STRING(isolate, "exports"), FIXED_ONE_BYTE_STRING(isolate, "primordials"), }; - } else if (strncmp(id, "internal/main/", strlen("internal/main/")) == 0) { - // internal/main/*: process, require, internalBinding, primordials + } else if (strncmp(id, "internal/main/", strlen("internal/main/")) == 0 || + strncmp(id, + "internal/bootstrap/", + strlen("internal/bootstrap/")) == 0) { + // internal/main/*, internal/bootstrap/*: process, require, + // internalBinding, primordials parameters = { FIXED_ONE_BYTE_STRING(isolate, "process"), FIXED_ONE_BYTE_STRING(isolate, "require"), @@ -404,16 +397,6 @@ MaybeLocal BuiltinLoader::LookupAndCompile( FIXED_ONE_BYTE_STRING(isolate, "process"), FIXED_ONE_BYTE_STRING(isolate, "require"), }; - } else if (strncmp(id, - "internal/bootstrap/", - strlen("internal/bootstrap/")) == 0) { - // internal/bootstrap/*: process, require, internalBinding, primordials - parameters = { - FIXED_ONE_BYTE_STRING(isolate, "process"), - FIXED_ONE_BYTE_STRING(isolate, "require"), - FIXED_ONE_BYTE_STRING(isolate, "internalBinding"), - FIXED_ONE_BYTE_STRING(isolate, "primordials"), - }; } else { // others: exports, require, module, process, internalBinding, primordials parameters = { @@ -426,17 +409,86 @@ MaybeLocal BuiltinLoader::LookupAndCompile( }; } - MaybeLocal maybe = GetInstance()->LookupAndCompileInternal( - context, id, ¶meters, &result); - if (optional_env != nullptr) { - RecordResult(id, result, optional_env); + MaybeLocal maybe = + LookupAndCompileInternal(context, id, ¶meters, &result); + if (optional_realm != nullptr) { + DCHECK_EQ(this, optional_realm->env()->builtin_loader()); + RecordResult(id, result, optional_realm); } return maybe; } +MaybeLocal BuiltinLoader::CompileAndCall(Local context, + const char* id, + Realm* realm) { + Isolate* isolate = context->GetIsolate(); + // Arguments must match the parameters specified in + // BuiltinLoader::LookupAndCompile(). + std::vector> arguments; + // Detects parameters of the scripts based on module ids. + // internal/bootstrap/realm: process, getLinkedBinding, + // getInternalBinding, primordials + if (strcmp(id, "internal/bootstrap/realm") == 0) { + Local get_linked_binding; + Local get_internal_binding; + if (!NewFunctionTemplate(isolate, binding::GetLinkedBinding) + ->GetFunction(context) + .ToLocal(&get_linked_binding) || + !NewFunctionTemplate(isolate, binding::GetInternalBinding) + ->GetFunction(context) + .ToLocal(&get_internal_binding)) { + return MaybeLocal(); + } + arguments = {realm->process_object(), + get_linked_binding, + get_internal_binding, + realm->primordials()}; + } else if (strncmp(id, "internal/main/", strlen("internal/main/")) == 0 || + strncmp(id, + "internal/bootstrap/", + strlen("internal/bootstrap/")) == 0) { + // internal/main/*, internal/bootstrap/*: process, require, + // internalBinding, primordials + arguments = {realm->process_object(), + realm->builtin_module_require(), + realm->internal_binding_loader(), + realm->primordials()}; + } else if (strncmp(id, "embedder_main_", strlen("embedder_main_")) == 0) { + // Synthetic embedder main scripts from LoadEnvironment(): process, require + arguments = { + realm->process_object(), + realm->builtin_module_require(), + }; + } else { + // This should be invoked with the other CompileAndCall() methods, as + // we are unable to generate the arguments. + // Currently there are two cases: + // internal/per_context/*: the arguments are generated in + // InitializePrimordials() + // all the other cases: the arguments are generated in the JS-land loader. + UNREACHABLE(); + } + return CompileAndCall(context, id, arguments.size(), arguments.data(), realm); +} + +MaybeLocal BuiltinLoader::CompileAndCall(Local context, + const char* id, + int argc, + Local argv[], + Realm* optional_realm) { + // Arguments must match the parameters specified in + // BuiltinLoader::LookupAndCompile(). + MaybeLocal maybe_fn = LookupAndCompile(context, id, optional_realm); + Local fn; + if (!maybe_fn.ToLocal(&fn)) { + return MaybeLocal(); + } + Local undefined = Undefined(context->GetIsolate()); + return fn->Call(context, undefined, argc, argv); +} + bool BuiltinLoader::CompileAllBuiltins(Local context) { - BuiltinLoader* loader = GetInstance(); - std::vector ids = loader->GetBuiltinIds(); + std::vector ids = GetBuiltinIds(); bool all_succeeded = true; std::string v8_tools_prefix = "internal/deps/v8/tools/"; for (const auto& id : ids) { @@ -444,7 +496,7 @@ bool BuiltinLoader::CompileAllBuiltins(Local context) { continue; } v8::TryCatch bootstrapCatch(context->GetIsolate()); - USE(loader->LookupAndCompile(context, id.c_str(), nullptr)); + USE(LookupAndCompile(context, id.c_str(), nullptr)); if (bootstrapCatch.HasCaught()) { per_process::Debug(DebugCategory::CODE_CACHE, "Failed to compile code cache for %s\n", @@ -456,11 +508,9 @@ bool BuiltinLoader::CompileAllBuiltins(Local context) { return all_succeeded; } -void BuiltinLoader::CopyCodeCache(std::vector* out) { - BuiltinLoader* loader = GetInstance(); - Mutex::ScopedLock lock(loader->code_cache_mutex()); - auto in = loader->code_cache(); - for (auto const& item : *in) { +void BuiltinLoader::CopyCodeCache(std::vector* out) const { + RwLock::ScopedReadLock lock(code_cache_->mutex); + for (auto const& item : code_cache_->map) { out->push_back( {item.first, {item.second->data, item.second->data + item.second->length}}); @@ -468,24 +518,16 @@ void BuiltinLoader::CopyCodeCache(std::vector* out) { } void BuiltinLoader::RefreshCodeCache(const std::vector& in) { - BuiltinLoader* loader = GetInstance(); - Mutex::ScopedLock lock(loader->code_cache_mutex()); - auto out = loader->code_cache(); + RwLock::ScopedLock lock(code_cache_->mutex); for (auto const& item : in) { size_t length = item.data.size(); uint8_t* buffer = new uint8_t[length]; memcpy(buffer, item.data.data(), length); auto new_cache = std::make_unique( buffer, length, v8::ScriptCompiler::CachedData::BufferOwned); - auto cache_it = out->find(item.id); - if (cache_it != out->end()) { - // Release the old cache and replace it with the new copy. - cache_it->second.reset(new_cache.release()); - } else { - out->emplace(item.id, new_cache.release()); - } + code_cache_->map[item.id] = std::move(new_cache); } - loader->has_code_cache_ = true; + code_cache_->has_code_cache = true; } void BuiltinLoader::GetBuiltinCategories( @@ -495,20 +537,19 @@ void BuiltinLoader::GetBuiltinCategories( Local context = env->context(); Local result = Object::New(isolate); - // Copy from the per-process categories - std::set cannot_be_required = - GetInstance()->GetCannotBeRequired(); - std::set can_be_required = GetInstance()->GetCanBeRequired(); + BuiltinCategories builtin_categories = + env->builtin_loader()->GetBuiltinCategories(); if (!env->owns_process_state()) { - can_be_required.erase("trace_events"); - cannot_be_required.insert("trace_events"); + builtin_categories.can_be_required.erase("trace_events"); + builtin_categories.cannot_be_required.insert("trace_events"); } Local cannot_be_required_js; Local can_be_required_js; - if (!ToV8Value(context, cannot_be_required).ToLocal(&cannot_be_required_js)) + if (!ToV8Value(context, builtin_categories.cannot_be_required) + .ToLocal(&cannot_be_required_js)) return; if (result ->Set(context, @@ -516,7 +557,9 @@ void BuiltinLoader::GetBuiltinCategories( cannot_be_required_js) .IsNothing()) return; - if (!ToV8Value(context, can_be_required).ToLocal(&can_be_required_js)) return; + if (!ToV8Value(context, builtin_categories.can_be_required) + .ToLocal(&can_be_required_js)) + return; if (result ->Set(context, OneByteString(isolate, "canBeRequired"), @@ -528,44 +571,44 @@ void BuiltinLoader::GetBuiltinCategories( } void BuiltinLoader::GetCacheUsage(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - Isolate* isolate = env->isolate(); - Local context = env->context(); + Realm* realm = Realm::GetCurrent(args); + Isolate* isolate = realm->isolate(); + Local context = realm->context(); Local result = Object::New(isolate); Local builtins_with_cache_js; Local builtins_without_cache_js; Local builtins_in_snapshot_js; - if (!ToV8Value(context, env->builtins_with_cache) + if (!ToV8Value(context, realm->builtins_with_cache) .ToLocal(&builtins_with_cache_js)) { return; } if (result - ->Set(env->context(), + ->Set(context, OneByteString(isolate, "compiledWithCache"), builtins_with_cache_js) .IsNothing()) { return; } - if (!ToV8Value(context, env->builtins_without_cache) + if (!ToV8Value(context, realm->builtins_without_cache) .ToLocal(&builtins_without_cache_js)) { return; } if (result - ->Set(env->context(), + ->Set(context, OneByteString(isolate, "compiledWithoutCache"), builtins_without_cache_js) .IsNothing()) { return; } - if (!ToV8Value(context, env->builtins_in_snapshot) + if (!ToV8Value(context, realm->builtins_in_snapshot) .ToLocal(&builtins_in_snapshot_js)) { return; } if (result - ->Set(env->context(), + ->Set(context, OneByteString(isolate, "compiledInSnapshot"), builtins_in_snapshot_js) .IsNothing()) { @@ -577,35 +620,38 @@ void BuiltinLoader::GetCacheUsage(const FunctionCallbackInfo& args) { void BuiltinLoader::BuiltinIdsGetter(Local property, const PropertyCallbackInfo& info) { - Isolate* isolate = info.GetIsolate(); + Environment* env = Environment::GetCurrent(info); + Isolate* isolate = env->isolate(); - std::vector ids = GetInstance()->GetBuiltinIds(); + std::vector ids = env->builtin_loader()->GetBuiltinIds(); info.GetReturnValue().Set( ToV8Value(isolate->GetCurrentContext(), ids).ToLocalChecked()); } void BuiltinLoader::ConfigStringGetter( Local property, const PropertyCallbackInfo& info) { - info.GetReturnValue().Set(GetConfigString(info.GetIsolate())); + Environment* env = Environment::GetCurrent(info); + info.GetReturnValue().Set( + env->builtin_loader()->GetConfigString(info.GetIsolate())); } void BuiltinLoader::RecordResult(const char* id, BuiltinLoader::Result result, - Environment* env) { + Realm* realm) { if (result == BuiltinLoader::Result::kWithCache) { - env->builtins_with_cache.insert(id); + realm->builtins_with_cache.insert(id); } else { - env->builtins_without_cache.insert(id); + realm->builtins_without_cache.insert(id); } } void BuiltinLoader::CompileFunction(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); + Realm* realm = Realm::GetCurrent(args); CHECK(args[0]->IsString()); - node::Utf8Value id_v(env->isolate(), args[0].As()); + node::Utf8Value id_v(realm->isolate(), args[0].As()); const char* id = *id_v; - MaybeLocal maybe = - GetInstance()->LookupAndCompile(env->context(), id, env); + MaybeLocal maybe = realm->env()->builtin_loader()->LookupAndCompile( + realm->context(), id, realm); Local fn; if (maybe.ToLocal(&fn)) { args.GetReturnValue().Set(fn); @@ -613,55 +659,67 @@ void BuiltinLoader::CompileFunction(const FunctionCallbackInfo& args) { } void BuiltinLoader::HasCachedBuiltins(const FunctionCallbackInfo& args) { - args.GetReturnValue().Set( - v8::Boolean::New(args.GetIsolate(), GetInstance()->has_code_cache_)); -} - -// TODO(joyeecheung): It is somewhat confusing that Class::Initialize -// is used to initialize to the binding, but it is the current convention. -// Rename this across the code base to something that makes more sense. -void BuiltinLoader::Initialize(Local target, - Local unused, - Local context, - void* priv) { - Environment* env = Environment::GetCurrent(context); - Isolate* isolate = env->isolate(); - - target - ->SetAccessor(context, - env->config_string(), - ConfigStringGetter, - nullptr, - MaybeLocal(), - DEFAULT, - None, - SideEffectType::kHasNoSideEffect) - .Check(); - target - ->SetAccessor(context, - FIXED_ONE_BYTE_STRING(isolate, "builtinIds"), - BuiltinIdsGetter, - nullptr, - MaybeLocal(), - DEFAULT, - None, - SideEffectType::kHasNoSideEffect) - .Check(); - - target - ->SetAccessor(context, - FIXED_ONE_BYTE_STRING(isolate, "builtinCategories"), - GetBuiltinCategories, - nullptr, - Local(), - DEFAULT, - None, - SideEffectType::kHasNoSideEffect) - .Check(); - - SetMethod(context, target, "getCacheUsage", BuiltinLoader::GetCacheUsage); - SetMethod(context, target, "compileFunction", BuiltinLoader::CompileFunction); - SetMethod(context, target, "hasCachedBuiltins", HasCachedBuiltins); + auto instance = Environment::GetCurrent(args)->builtin_loader(); + RwLock::ScopedReadLock lock(instance->code_cache_->mutex); + args.GetReturnValue().Set(v8::Boolean::New( + args.GetIsolate(), instance->code_cache_->has_code_cache)); +} + +void SetInternalLoaders(const FunctionCallbackInfo& args) { + Realm* realm = Realm::GetCurrent(args); + CHECK(args[0]->IsFunction()); + CHECK(args[1]->IsFunction()); + DCHECK(realm->internal_binding_loader().IsEmpty()); + DCHECK(realm->builtin_module_require().IsEmpty()); + realm->set_internal_binding_loader(args[0].As()); + realm->set_builtin_module_require(args[1].As()); +} + +void BuiltinLoader::CopySourceAndCodeCacheReferenceFrom( + const BuiltinLoader* other) { + code_cache_ = other->code_cache_; + source_ = other->source_; +} + +void BuiltinLoader::CreatePerIsolateProperties(IsolateData* isolate_data, + Local target) { + Isolate* isolate = isolate_data->isolate(); + Local proto = target->PrototypeTemplate(); + + proto->SetAccessor(isolate_data->config_string(), + ConfigStringGetter, + nullptr, + Local(), + DEFAULT, + None, + SideEffectType::kHasNoSideEffect); + + proto->SetAccessor(FIXED_ONE_BYTE_STRING(isolate, "builtinIds"), + BuiltinIdsGetter, + nullptr, + Local(), + DEFAULT, + None, + SideEffectType::kHasNoSideEffect); + + proto->SetAccessor(FIXED_ONE_BYTE_STRING(isolate, "builtinCategories"), + GetBuiltinCategories, + nullptr, + Local(), + DEFAULT, + None, + SideEffectType::kHasNoSideEffect); + + SetMethod(isolate, proto, "getCacheUsage", BuiltinLoader::GetCacheUsage); + SetMethod(isolate, proto, "compileFunction", BuiltinLoader::CompileFunction); + SetMethod(isolate, proto, "hasCachedBuiltins", HasCachedBuiltins); + SetMethod(isolate, proto, "setInternalLoaders", SetInternalLoaders); +} + +void BuiltinLoader::CreatePerContextProperties(Local target, + Local unused, + Local context, + void* priv) { // internalBinding('builtins') should be frozen target->SetIntegrityLevel(context, IntegrityLevel::kFrozen).FromJust(); } @@ -674,12 +732,15 @@ void BuiltinLoader::RegisterExternalReferences( registry->Register(GetCacheUsage); registry->Register(CompileFunction); registry->Register(HasCachedBuiltins); + registry->Register(SetInternalLoaders); } } // namespace builtins } // namespace node -NODE_BINDING_CONTEXT_AWARE_INTERNAL(builtins, - node::builtins::BuiltinLoader::Initialize) +NODE_BINDING_PER_ISOLATE_INIT( + builtins, node::builtins::BuiltinLoader::CreatePerIsolateProperties) +NODE_BINDING_CONTEXT_AWARE_INTERNAL( + builtins, node::builtins::BuiltinLoader::CreatePerContextProperties) NODE_BINDING_EXTERNAL_REFERENCE( builtins, node::builtins::BuiltinLoader::RegisterExternalReferences) diff --git a/src/node_builtins.h b/src/node_builtins.h index 90b158b84bb2a6..81d6d1cca279c2 100644 --- a/src/node_builtins.h +++ b/src/node_builtins.h @@ -6,10 +6,12 @@ #include #include #include +#include #include #include #include #include "node_mutex.h" +#include "node_threadsafe_cow.h" #include "node_union_bytes.h" #include "v8.h" @@ -19,6 +21,8 @@ class PerProcessTest; namespace node { class SnapshotBuilder; class ExternalReferenceRegistry; +class Realm; + namespace builtins { using BuiltinSourceMap = std::map; @@ -35,65 +39,70 @@ struct CodeCacheInfo { // bootstrap scripts, whose source are bundled into the binary as static data. class NODE_EXTERN_PRIVATE BuiltinLoader { public: + BuiltinLoader(); BuiltinLoader(const BuiltinLoader&) = delete; BuiltinLoader& operator=(const BuiltinLoader&) = delete; static void RegisterExternalReferences(ExternalReferenceRegistry* registry); - static void Initialize(v8::Local target, - v8::Local unused, - v8::Local context, - void* priv); + static void CreatePerIsolateProperties( + IsolateData* isolate_data, v8::Local target); + static void CreatePerContextProperties(v8::Local target, + v8::Local unused, + v8::Local context, + void* priv); // The parameters used to compile the scripts are detected based on // the pattern of the id. - static v8::MaybeLocal LookupAndCompile( - v8::Local context, - const char* id, - Environment* optional_env); + v8::MaybeLocal LookupAndCompile(v8::Local context, + const char* id, + Realm* optional_realm); + + v8::MaybeLocal CompileAndCall(v8::Local context, + const char* id, + int argc, + v8::Local argv[], + Realm* optional_realm); + + v8::MaybeLocal CompileAndCall(v8::Local context, + const char* id, + Realm* realm); - static v8::Local GetSourceObject(v8::Local context); + v8::Local GetSourceObject(v8::Local context); // Returns config.gypi as a JSON string - static v8::Local GetConfigString(v8::Isolate* isolate); - static bool Exists(const char* id); - static bool Add(const char* id, const UnionBytes& source); - static bool Add(const char* id, std::string_view utf8source); + v8::Local GetConfigString(v8::Isolate* isolate); + bool Exists(const char* id); + bool Add(const char* id, const UnionBytes& source); + bool Add(const char* id, std::string_view utf8source); - static bool CompileAllBuiltins(v8::Local context); - static void RefreshCodeCache(const std::vector& in); - static void CopyCodeCache(std::vector* out); + bool CompileAllBuiltins(v8::Local context); + void RefreshCodeCache(const std::vector& in); + void CopyCodeCache(std::vector* out) const; + + void CopySourceAndCodeCacheReferenceFrom(const BuiltinLoader* other); private: // Only allow access from friends. friend class CodeCacheBuilder; - BuiltinLoader(); - static BuiltinLoader* GetInstance(); - // Generated by tools/js2c.py as node_javascript.cc void LoadJavaScriptSource(); // Loads data into source_ UnionBytes GetConfig(); // Return data for config.gypi - std::vector GetBuiltinIds(); + std::vector GetBuiltinIds() const; struct BuiltinCategories { - bool is_initialized = false; std::set can_be_required; std::set cannot_be_required; }; - void InitializeBuiltinCategories(); - const std::set& GetCannotBeRequired(); - const std::set& GetCanBeRequired(); + // This method builds `BuiltinCategories` from scratch every time, + // and is therefore somewhat expensive, but also currently only being + // used for testing, so that should not be an issue. + BuiltinCategories GetBuiltinCategories() const; - bool CanBeRequired(const char* id); - bool CannotBeRequired(const char* id); - - BuiltinCodeCacheMap* code_cache(); - const Mutex& code_cache_mutex() const { return code_cache_mutex_; } - - v8::ScriptCompiler::CachedData* GetCodeCache(const char* id) const; + const v8::ScriptCompiler::CachedData* GetCodeCache(const char* id) const; enum class Result { kWithCache, kWithoutCache }; v8::MaybeLocal LoadBuiltinSource(v8::Isolate* isolate, - const char* id); + const char* id) const; // If an exception is encountered (e.g. source code contains // syntax error), the returned value is empty. v8::MaybeLocal LookupAndCompileInternal( @@ -104,7 +113,7 @@ class NODE_EXTERN_PRIVATE BuiltinLoader { static void RecordResult(const char* id, BuiltinLoader::Result result, - Environment* env); + Realm* realm); static void GetBuiltinCategories( v8::Local property, const v8::PropertyCallbackInfo& info); @@ -122,18 +131,18 @@ class NODE_EXTERN_PRIVATE BuiltinLoader { static void HasCachedBuiltins( const v8::FunctionCallbackInfo& args); - static void AddExternalizedBuiltin(const char* id, const char* filename); + void AddExternalizedBuiltin(const char* id, const char* filename); - static BuiltinLoader instance_; - BuiltinCategories builtin_categories_; - BuiltinSourceMap source_; - BuiltinCodeCacheMap code_cache_; - UnionBytes config_; + ThreadsafeCopyOnWrite source_; - // Used to synchronize access to the code cache map - Mutex code_cache_mutex_; + const UnionBytes config_; - bool has_code_cache_; + struct BuiltinCodeCache { + RwLock mutex; + BuiltinCodeCacheMap map; + bool has_code_cache = false; + }; + std::shared_ptr code_cache_; friend class ::PerProcessTest; }; diff --git a/src/node_errors.cc b/src/node_errors.cc index e58e45be7bbb64..11bf2cc8b43916 100644 --- a/src/node_errors.cc +++ b/src/node_errors.cc @@ -954,9 +954,9 @@ void PerIsolateMessageListener(Local message, Local error) { } void SetPrepareStackTraceCallback(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); + Realm* realm = Realm::GetCurrent(args); CHECK(args[0]->IsFunction()); - env->set_prepare_stack_trace_callback(args[0].As()); + realm->set_prepare_stack_trace_callback(args[0].As()); } static void SetSourceMapsEnabled(const FunctionCallbackInfo& args) { @@ -981,11 +981,11 @@ static void SetMaybeCacheGeneratedSourceMap( static void SetEnhanceStackForFatalException( const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); + Realm* realm = Realm::GetCurrent(args); CHECK(args[0]->IsFunction()); CHECK(args[1]->IsFunction()); - env->set_enhance_fatal_stack_before_inspector(args[0].As()); - env->set_enhance_fatal_stack_after_inspector(args[1].As()); + realm->set_enhance_fatal_stack_before_inspector(args[0].As()); + realm->set_enhance_fatal_stack_after_inspector(args[1].As()); } // Side effect-free stringification that will never throw exceptions. diff --git a/src/node_external_reference.h b/src/node_external_reference.h index 954bb233e941f8..0b594967732faf 100644 --- a/src/node_external_reference.h +++ b/src/node_external_reference.h @@ -74,6 +74,7 @@ class ExternalReferenceRegistry { V(heap_utils) \ V(messaging) \ V(mksnapshot) \ + V(module_wrap) \ V(options) \ V(os) \ V(performance) \ diff --git a/src/node_file.cc b/src/node_file.cc index 4993da585322db..7f627ac458492c 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -20,7 +20,7 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. #include "node_file.h" // NOLINT(build/include_inline) #include "node_file-inl.h" -#include "aliased_buffer.h" +#include "aliased_buffer-inl.h" #include "memory_tracker-inl.h" #include "node_buffer.h" #include "node_external_reference.h" @@ -70,7 +70,6 @@ using v8::Object; using v8::ObjectTemplate; using v8::Promise; using v8::String; -using v8::Symbol; using v8::Undefined; using v8::Value; @@ -1053,8 +1052,9 @@ static void InternalModuleReadJSON(const FunctionCallbackInfo& args) { if (offset >= 3 && 0 == memcmp(chars.data(), "\xEF\xBB\xBF", 3)) { start = 3; // Skip UTF-8 BOM. } - const size_t size = offset - start; + + // TODO(anonrig): Follow-up on removing the following changes for AIX. char* p = &chars[start]; char* pe = &chars[size]; char* pos[2]; @@ -1082,16 +1082,14 @@ static void InternalModuleReadJSON(const FunctionCallbackInfo& args) { } } - Local return_value[] = { - String::NewFromUtf8(isolate, - &chars[start], - v8::NewStringType::kNormal, - size).ToLocalChecked(), - Boolean::New(isolate, p < pe ? true : false) - }; + String::NewFromUtf8( + isolate, &chars[start], v8::NewStringType::kNormal, size) + .ToLocalChecked(), + Boolean::New(isolate, p < pe ? true : false)}; + args.GetReturnValue().Set( - Array::New(isolate, return_value, arraysize(return_value))); + Array::New(isolate, return_value, arraysize(return_value))); } // Used to speed up module loading. Returns 0 if the path refers to @@ -2792,13 +2790,9 @@ void Initialize(Local target, fdcloset->SetInternalFieldCount(FSReqBase::kInternalFieldCount); env->set_fdclose_constructor_template(fdcloset); - Local use_promises_symbol = - Symbol::New(isolate, - FIXED_ONE_BYTE_STRING(isolate, "use promises")); - env->set_fs_use_promises_symbol(use_promises_symbol); target->Set(context, FIXED_ONE_BYTE_STRING(isolate, "kUsePromises"), - use_promises_symbol).Check(); + env->fs_use_promises_symbol()).Check(); } BindingData* FSReqBase::binding_data() { diff --git a/src/node_file.h b/src/node_file.h index a4ca120d918127..472b45f4611042 100644 --- a/src/node_file.h +++ b/src/node_file.h @@ -69,9 +69,7 @@ class BindingData : public SnapshotableObject { using InternalFieldInfo = InternalFieldInfoBase; SERIALIZABLE_OBJECT_METHODS() - static constexpr FastStringKey type_name{"node::fs::BindingData"}; - static constexpr EmbedderObjectType type_int = - EmbedderObjectType::k_fs_binding_data; + SET_BINDING_ID(fs_binding_data) void MemoryInfo(MemoryTracker* tracker) const override; SET_SELF_SIZE(BindingData) diff --git a/src/node_http2.cc b/src/node_http2.cc index d0733bb304cf91..528bf3aa58b322 100644 --- a/src/node_http2.cc +++ b/src/node_http2.cc @@ -1,5 +1,5 @@ #include "node_http2.h" -#include "aliased_buffer.h" +#include "aliased_buffer-inl.h" #include "aliased_struct-inl.h" #include "debug_utils-inl.h" #include "histogram-inl.h" diff --git a/src/node_http2_state.h b/src/node_http2_state.h index 75a98bf476b2f7..f9ac6b40c3410a 100644 --- a/src/node_http2_state.h +++ b/src/node_http2_state.h @@ -125,7 +125,7 @@ class Http2State : public BaseObject { SET_SELF_SIZE(Http2State) SET_MEMORY_INFO_NAME(Http2State) - static constexpr FastStringKey type_name { "http2" }; + SET_BINDING_ID(http2_binding_data) private: struct http2_state_internal { diff --git a/src/node_http_parser.cc b/src/node_http_parser.cc index 2849d3bee1ac83..9f166ccc245c06 100644 --- a/src/node_http_parser.cc +++ b/src/node_http_parser.cc @@ -95,7 +95,7 @@ class BindingData : public BaseObject { public: BindingData(Realm* realm, Local obj) : BaseObject(realm, obj) {} - static constexpr FastStringKey type_name { "http_parser" }; + SET_BINDING_ID(http_parser_binding_data) std::vector parser_buffer; bool parser_buffer_in_use = false; diff --git a/src/node_main_instance.cc b/src/node_main_instance.cc index a8661c3c2263fc..1d23631780cf90 100644 --- a/src/node_main_instance.cc +++ b/src/node_main_instance.cc @@ -158,6 +158,11 @@ NodeMainInstance::CreateMainEnvironment(int* exit_code) { &(snapshot_data_->env_info), EnvironmentFlags::kDefaultFlags, {})); +#ifdef NODE_V8_SHARED_RO_HEAP + // TODO(addaleax): Do this as part of creating the Environment + // once we store the SnapshotData* itself on IsolateData. + env->builtin_loader()->RefreshCodeCache(snapshot_data_->code_cache); +#endif context = Context::FromSnapshot(isolate_, SnapshotData::kNodeMainContextIndex, {DeserializeNodeInternalFields, env.get()}) diff --git a/src/node_metadata.cc b/src/node_metadata.cc index 6fe09f843e26b7..22546e9de25bdf 100644 --- a/src/node_metadata.cc +++ b/src/node_metadata.cc @@ -2,7 +2,9 @@ #include "acorn_version.h" #include "ada.h" #include "ares.h" +#include "base64_version.h" #include "brotli/encode.h" +#include "cjs_module_lexer_version.h" #include "llhttp.h" #include "nghttp2/nghttp2ver.h" #include "node.h" @@ -97,8 +99,10 @@ Metadata::Versions::Versions() { #ifndef NODE_SHARED_BUILTIN_UNDICI_UNDICI_PATH undici = UNDICI_VERSION; #endif - acorn = ACORN_VERSION; + acorn = ACORN_VERSION; + cjs_module_lexer = CJS_MODULE_LEXER_VERSION; + base64 = BASE64_VERSION; uvwasi = UVWASI_VERSION_STRING; #if HAVE_OPENSSL diff --git a/src/node_metadata.h b/src/node_metadata.h index 1831bfd0baaac7..cf051585e779e2 100644 --- a/src/node_metadata.h +++ b/src/node_metadata.h @@ -48,7 +48,9 @@ namespace node { V(acorn) \ V(simdutf) \ V(ada) \ - NODE_VERSIONS_KEY_UNDICI(V) + NODE_VERSIONS_KEY_UNDICI(V) \ + V(cjs_module_lexer) \ + V(base64) #if HAVE_OPENSSL #define NODE_VERSIONS_KEY_CRYPTO(V) V(openssl) diff --git a/src/node_options.cc b/src/node_options.cc index 26f205bc3b425c..6ee79f7df8a1f8 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -114,12 +114,19 @@ void EnvironmentOptions::CheckOptions(std::vector* errors, errors->push_back("--policy-integrity cannot be empty"); } - if (!module_type.empty()) { - if (module_type != "commonjs" && module_type != "module") { + if (!input_type.empty()) { + if (input_type != "commonjs" && input_type != "module") { errors->push_back("--input-type must be \"module\" or \"commonjs\""); } } + if (!type.empty()) { + if (type != "commonjs" && type != "module") { + errors->push_back("--experimental-default-type must be " + "\"module\" or \"commonjs\""); + } + } + if (!experimental_specifier_resolution.empty()) { if (experimental_specifier_resolution != "node" && experimental_specifier_resolution != "explicit") { @@ -181,7 +188,7 @@ void EnvironmentOptions::CheckOptions(std::vector* errors, } else if (force_repl) { errors->push_back("either --watch or --interactive " "can be used, not both"); - } else if (argv->size() < 1 || (*argv)[1].empty()) { + } else if (!test_runner && (argv->size() < 1 || (*argv)[1].empty())) { errors->push_back("--watch requires specifying a file"); } @@ -399,7 +406,7 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { &EnvironmentOptions::experimental_wasm_modules, kAllowedInEnvvar); AddOption("--experimental-import-meta-resolve", - "experimental ES Module import.meta.resolve() support", + "experimental ES Module import.meta.resolve() parentURL support", &EnvironmentOptions::experimental_import_meta_resolve, kAllowedInEnvvar); AddOption("--experimental-policy", @@ -451,7 +458,7 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { kAllowedInEnvvar); AddOption("--input-type", "set module type for string input", - &EnvironmentOptions::module_type, + &EnvironmentOptions::input_type, kAllowedInEnvvar); AddOption("--experimental-specifier-resolution", "Select extension resolution algorithm for es modules; " @@ -563,6 +570,9 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { AddOption("--test", "launch test runner on startup", &EnvironmentOptions::test_runner); + AddOption("--test-concurrency", + "specify test runner concurrency", + &EnvironmentOptions::test_runner_concurrency); AddOption("--experimental-test-coverage", "enable code coverage in the test runner", &EnvironmentOptions::test_runner_coverage); @@ -581,6 +591,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { "run tests with 'only' option set", &EnvironmentOptions::test_only, kAllowedInEnvvar); + AddOption("--test-shard", + "run test at specific shard", + &EnvironmentOptions::test_shard, + kAllowedInEnvvar); AddOption("--test-udp-no-try-send", "", // For testing only. &EnvironmentOptions::test_udp_no_try_send); AddOption("--throw-deprecation", @@ -616,6 +630,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { "show stack traces on process warnings", &EnvironmentOptions::trace_warnings, kAllowedInEnvvar); + AddOption("--experimental-default-type", + "set module system to use by default", + &EnvironmentOptions::type, + kAllowedInEnvvar); AddOption("--extra-info-on-fatal-exception", "hide extra information on fatal exception that causes exit", &EnvironmentOptions::extra_info_on_fatal_exception, diff --git a/src/node_options.h b/src/node_options.h index 7d210049aff445..743e19f58d5863 100644 --- a/src/node_options.h +++ b/src/node_options.h @@ -117,7 +117,8 @@ class EnvironmentOptions : public Options { std::string experimental_specifier_resolution; bool experimental_wasm_modules = false; bool experimental_import_meta_resolve = false; - std::string module_type; + std::string input_type; // Value of --input-type + std::string type; // Value of --experimental-default-type std::string experimental_policy; std::string experimental_policy_integrity; bool has_policy_integrity_string = false; @@ -155,12 +156,14 @@ class EnvironmentOptions : public Options { std::string redirect_warnings; std::string diagnostic_dir; bool test_runner = false; + uint64_t test_runner_concurrency = 0; bool test_runner_coverage = false; std::vector test_name_pattern; std::vector test_reporter; std::vector test_reporter_destination; bool test_only = false; bool test_udp_no_try_send = false; + std::string test_shard; bool throw_deprecation = false; bool trace_atomics_wait = false; bool trace_deprecation = false; diff --git a/src/node_perf.cc b/src/node_perf.cc index 582a74ebd14769..c16543acba425a 100644 --- a/src/node_perf.cc +++ b/src/node_perf.cc @@ -1,5 +1,5 @@ #include "node_perf.h" -#include "aliased_buffer.h" +#include "aliased_buffer-inl.h" #include "env-inl.h" #include "histogram-inl.h" #include "memory_tracker-inl.h" @@ -215,18 +215,6 @@ static void RemoveGarbageCollectionTracking( GarbageCollectionCleanupHook(env); } -// Gets the name of a function -inline Local GetName(Local fn) { - Local val = fn->GetDebugName(); - if (val.IsEmpty() || val->IsUndefined()) { - Local boundFunction = fn->GetBoundFunction(); - if (!boundFunction.IsEmpty() && !boundFunction->IsUndefined()) { - val = GetName(boundFunction.As()); - } - } - return val; -} - // Notify a custom PerformanceEntry to observers void Notify(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); diff --git a/src/node_process.h b/src/node_process.h index 30f655dfc71f23..5af062e63ea49b 100644 --- a/src/node_process.h +++ b/src/node_process.h @@ -54,9 +54,7 @@ class BindingData : public SnapshotableObject { using InternalFieldInfo = InternalFieldInfoBase; SERIALIZABLE_OBJECT_METHODS() - static constexpr FastStringKey type_name{"node::process::BindingData"}; - static constexpr EmbedderObjectType type_int = - EmbedderObjectType::k_process_binding_data; + SET_BINDING_ID(process_binding_data) BindingData(Realm* realm, v8::Local object); diff --git a/src/node_realm-inl.h b/src/node_realm-inl.h index b4c5896adc04ae..2fc3eef97729d1 100644 --- a/src/node_realm-inl.h +++ b/src/node_realm-inl.h @@ -30,6 +30,10 @@ inline Realm* Realm::GetCurrent(const v8::PropertyCallbackInfo& info) { return GetCurrent(info.GetIsolate()->GetCurrentContext()); } +inline IsolateData* Realm::isolate_data() const { + return env_->isolate_data(); +} + inline Environment* Realm::env() const { return env_; } @@ -62,9 +66,11 @@ inline T* Realm::GetBindingData(v8::Local context) { static_cast(context->GetAlignedPointerFromEmbedderData( ContextEmbedderIndex::kBindingDataStoreIndex)); DCHECK_NOT_NULL(map); - auto it = map->find(T::type_name); - if (UNLIKELY(it == map->end())) return nullptr; - T* result = static_cast(it->second.get()); + constexpr size_t binding_index = static_cast(T::binding_type_int); + static_assert(binding_index < std::tuple_size_v); + auto ptr = (*map)[binding_index]; + if (UNLIKELY(!ptr)) return nullptr; + T* result = static_cast(ptr.get()); DCHECK_NOT_NULL(result); DCHECK_EQ(result->realm(), GetCurrent(context)); return result; @@ -80,8 +86,10 @@ inline T* Realm::AddBindingData(v8::Local context, static_cast(context->GetAlignedPointerFromEmbedderData( ContextEmbedderIndex::kBindingDataStoreIndex)); DCHECK_NOT_NULL(map); - auto result = map->emplace(T::type_name, item); - CHECK(result.second); + constexpr size_t binding_index = static_cast(T::binding_type_int); + static_assert(binding_index < std::tuple_size_v); + CHECK(!(*map)[binding_index]); // Should not insert the binding twice. + (*map)[binding_index] = item; DCHECK_EQ(GetBindingData(context), item.get()); return item.get(); } diff --git a/src/node_realm.cc b/src/node_realm.cc index 4a1502b136fed1..7e58b2aa2d59d6 100644 --- a/src/node_realm.cc +++ b/src/node_realm.cc @@ -8,17 +8,14 @@ namespace node { -using builtins::BuiltinLoader; using v8::Context; using v8::EscapableHandleScope; -using v8::Function; using v8::HandleScope; using v8::Local; using v8::MaybeLocal; using v8::Object; using v8::SnapshotCreator; using v8::String; -using v8::Undefined; using v8::Value; Realm::Realm(Environment* env, @@ -47,6 +44,8 @@ void Realm::MemoryInfo(MemoryTracker* tracker) const { tracker->TrackField("env", env_); tracker->TrackField("cleanup_queue", cleanup_queue_); + tracker->TrackField("builtins_with_cache", builtins_with_cache); + tracker->TrackField("builtins_without_cache", builtins_without_cache); } void Realm::CreateProperties() { @@ -97,6 +96,11 @@ RealmSerializeInfo Realm::Serialize(SnapshotCreator* creator) { RealmSerializeInfo info; Local ctx = context(); + // Currently all modules are compiled without cache in builtin snapshot + // builder. + info.builtins = std::vector(builtins_without_cache.begin(), + builtins_without_cache.end()); + uint32_t id = 0; #define V(PropertyName, TypeName) \ do { \ @@ -121,6 +125,8 @@ RealmSerializeInfo Realm::Serialize(SnapshotCreator* creator) { void Realm::DeserializeProperties(const RealmSerializeInfo* info) { Local ctx = context(); + builtins_in_snapshot = info->builtins; + const std::vector& values = info->persistent_values; size_t i = 0; // index to the array uint32_t id = 0; @@ -157,20 +163,11 @@ void Realm::DeserializeProperties(const RealmSerializeInfo* info) { DoneBootstrapping(); } -MaybeLocal Realm::ExecuteBootstrapper( - const char* id, std::vector>* arguments) { +MaybeLocal Realm::ExecuteBootstrapper(const char* id) { EscapableHandleScope scope(isolate()); Local ctx = context(); - MaybeLocal maybe_fn = - BuiltinLoader::LookupAndCompile(ctx, id, env()); - - Local fn; - if (!maybe_fn.ToLocal(&fn)) { - return MaybeLocal(); - } - MaybeLocal result = - fn->Call(ctx, Undefined(isolate()), arguments->size(), arguments->data()); + env()->builtin_loader()->CompileAndCall(ctx, id, this); // If there was an error during bootstrap, it must be unrecoverable // (e.g. max call stack exceeded). Clear the stack so that the @@ -185,65 +182,15 @@ MaybeLocal Realm::ExecuteBootstrapper( return scope.EscapeMaybe(result); } -MaybeLocal Realm::BootstrapInternalLoaders() { - EscapableHandleScope scope(isolate_); - - // Arguments must match the parameters specified in - // BuiltinLoader::LookupAndCompile(). - std::vector> loaders_args = { - process_object(), - NewFunctionTemplate(isolate_, binding::GetLinkedBinding) - ->GetFunction(context()) - .ToLocalChecked(), - NewFunctionTemplate(isolate_, binding::GetInternalBinding) - ->GetFunction(context()) - .ToLocalChecked(), - primordials()}; - - // Bootstrap internal loaders - Local loader_exports; - if (!ExecuteBootstrapper("internal/bootstrap/loaders", &loaders_args) - .ToLocal(&loader_exports)) { - return MaybeLocal(); - } - CHECK(loader_exports->IsObject()); - Local loader_exports_obj = loader_exports.As(); - Local internal_binding_loader = - loader_exports_obj->Get(context(), env_->internal_binding_string()) - .ToLocalChecked(); - CHECK(internal_binding_loader->IsFunction()); - set_internal_binding_loader(internal_binding_loader.As()); - Local require = - loader_exports_obj->Get(context(), env_->require_string()) - .ToLocalChecked(); - CHECK(require->IsFunction()); - set_builtin_module_require(require.As()); - - return scope.Escape(loader_exports); -} - MaybeLocal Realm::BootstrapNode() { - EscapableHandleScope scope(isolate_); + HandleScope scope(isolate_); - // Arguments must match the parameters specified in - // BuiltinLoader::LookupAndCompile(). - // process, require, internalBinding, primordials - std::vector> node_args = {process_object(), - builtin_module_require(), - internal_binding_loader(), - primordials()}; - - MaybeLocal result = - ExecuteBootstrapper("internal/bootstrap/node", &node_args); - - if (result.IsEmpty()) { + if (ExecuteBootstrapper("internal/bootstrap/node").IsEmpty()) { return MaybeLocal(); } if (!env_->no_browser_globals()) { - result = ExecuteBootstrapper("internal/bootstrap/browser", &node_args); - - if (result.IsEmpty()) { + if (ExecuteBootstrapper("internal/bootstrap/browser").IsEmpty()) { return MaybeLocal(); } } @@ -252,9 +199,7 @@ MaybeLocal Realm::BootstrapNode() { auto thread_switch_id = env_->is_main_thread() ? "internal/bootstrap/switches/is_main_thread" : "internal/bootstrap/switches/is_not_main_thread"; - result = ExecuteBootstrapper(thread_switch_id, &node_args); - - if (result.IsEmpty()) { + if (ExecuteBootstrapper(thread_switch_id).IsEmpty()) { return MaybeLocal(); } @@ -262,9 +207,7 @@ MaybeLocal Realm::BootstrapNode() { env_->owns_process_state() ? "internal/bootstrap/switches/does_own_process_state" : "internal/bootstrap/switches/does_not_own_process_state"; - result = ExecuteBootstrapper(process_state_switch_id, &node_args); - - if (result.IsEmpty()) { + if (ExecuteBootstrapper(process_state_switch_id).IsEmpty()) { return MaybeLocal(); } @@ -276,7 +219,7 @@ MaybeLocal Realm::BootstrapNode() { return MaybeLocal(); } - return scope.EscapeMaybe(result); + return v8::True(isolate_); } MaybeLocal Realm::RunBootstrapping() { @@ -284,11 +227,11 @@ MaybeLocal Realm::RunBootstrapping() { CHECK(!has_run_bootstrapping_code()); - if (BootstrapInternalLoaders().IsEmpty()) { + Local result; + if (!ExecuteBootstrapper("internal/bootstrap/realm").ToLocal(&result)) { return MaybeLocal(); } - Local result; if (!BootstrapNode().ToLocal(&result)) { return MaybeLocal(); } @@ -319,8 +262,9 @@ void Realm::DoneBootstrapping() { void Realm::RunCleanup() { TRACE_EVENT0(TRACING_CATEGORY_NODE1(realm), "RunCleanup"); - binding_data_store_.clear(); - + for (size_t i = 0; i < binding_data_store_.size(); ++i) { + binding_data_store_[i].reset(); + } cleanup_queue_.Drain(); } @@ -332,6 +276,20 @@ void Realm::PrintInfoForSnapshot() { std::cout << "#" << i++ << " " << obj << ": " << obj->MemoryInfoName() << "\n"; }); + + fprintf(stderr, "\nnBuiltins without cache:\n"); + for (const auto& s : builtins_without_cache) { + fprintf(stderr, "%s\n", s.c_str()); + } + fprintf(stderr, "\nBuiltins with cache:\n"); + for (const auto& s : builtins_with_cache) { + fprintf(stderr, "%s\n", s.c_str()); + } + fprintf(stderr, "\nStatic bindings (need to be registered):\n"); + for (const auto mod : internal_bindings) { + fprintf(stderr, "%s:%s\n", mod->nm_filename, mod->nm_modname); + } + fprintf(stderr, "End of the Realm.\n"); } diff --git a/src/node_realm.h b/src/node_realm.h index 407a3729c32dee..c9377b8ae17f86 100644 --- a/src/node_realm.h +++ b/src/node_realm.h @@ -13,6 +13,7 @@ namespace node { struct RealmSerializeInfo { + std::vector builtins; std::vector persistent_values; std::vector native_objects; @@ -20,9 +21,9 @@ struct RealmSerializeInfo { friend std::ostream& operator<<(std::ostream& o, const RealmSerializeInfo& i); }; -using BindingDataStore = std::unordered_map, - FastStringKey::Hash>; +using BindingDataStore = std::array, + static_cast( + BindingDataType::kBindingDataTypeCount)>; /** * node::Realm is a container for a set of JavaScript objects and functions @@ -67,9 +68,7 @@ class Realm : public MemoryRetainer { RealmSerializeInfo Serialize(v8::SnapshotCreator* creator); void DeserializeProperties(const RealmSerializeInfo* info); - v8::MaybeLocal ExecuteBootstrapper( - const char* id, std::vector>* arguments); - v8::MaybeLocal BootstrapInternalLoaders(); + v8::MaybeLocal ExecuteBootstrapper(const char* id); v8::MaybeLocal BootstrapNode(); v8::MaybeLocal RunBootstrapping(); @@ -120,6 +119,13 @@ class Realm : public MemoryRetainer { PER_REALM_STRONG_PERSISTENT_VALUES(V) #undef V + std::set internal_bindings; + std::set builtins_with_cache; + std::set builtins_without_cache; + // This is only filled during deserialization. We use a vector since + // it's only used for tests. + std::vector builtins_in_snapshot; + private: void InitializeContext(v8::Local context, const RealmSerializeInfo* realm_info); diff --git a/src/node_snapshotable.cc b/src/node_snapshotable.cc index f70e6ddf4303f3..c1b48f6acda32f 100644 --- a/src/node_snapshotable.cc +++ b/src/node_snapshotable.cc @@ -102,6 +102,9 @@ std::ostream& operator<<(std::ostream& output, std::ostream& operator<<(std::ostream& output, const RealmSerializeInfo& i) { output << "{\n" + << "// -- builtins begins --\n" + << i.builtins << ",\n" + << "// -- builtins ends --\n" << "// -- persistent_values begins --\n" << i.persistent_values << ",\n" << "// -- persistent_values ends --\n" @@ -115,9 +118,6 @@ std::ostream& operator<<(std::ostream& output, const RealmSerializeInfo& i) { std::ostream& operator<<(std::ostream& output, const EnvSerializeInfo& i) { output << "{\n" - << "// -- builtins begins --\n" - << i.builtins << ",\n" - << "// -- builtins ends --\n" << "// -- async_hooks begins --\n" << i.async_hooks << ",\n" << "// -- async_hooks ends --\n" @@ -711,6 +711,7 @@ template <> RealmSerializeInfo SnapshotDeserializer::Read() { per_process::Debug(DebugCategory::MKSNAPSHOT, "Read()\n"); RealmSerializeInfo result; + result.builtins = ReadVector(); result.persistent_values = ReadVector(); result.native_objects = ReadVector(); result.context = Read(); @@ -725,7 +726,8 @@ size_t SnapshotSerializer::Write(const RealmSerializeInfo& data) { } // Use += here to ensure order of evaluation. - size_t written_total = WriteVector(data.persistent_values); + size_t written_total = WriteVector(data.builtins); + written_total += WriteVector(data.persistent_values); written_total += WriteVector(data.native_objects); written_total += Write(data.context); @@ -737,7 +739,6 @@ template <> EnvSerializeInfo SnapshotDeserializer::Read() { per_process::Debug(DebugCategory::MKSNAPSHOT, "Read()\n"); EnvSerializeInfo result; - result.builtins = ReadVector(); result.async_hooks = Read(); result.tick_info = Read(); result.immediate_info = Read(); @@ -759,8 +760,7 @@ size_t SnapshotSerializer::Write(const EnvSerializeInfo& data) { } // Use += here to ensure order of evaluation. - size_t written_total = WriteVector(data.builtins); - written_total += Write(data.async_hooks); + size_t written_total = Write(data.async_hooks); written_total += Write(data.tick_info); written_total += Write(data.immediate_info); written_total += Write(data.timeout_info); @@ -1039,10 +1039,10 @@ static const int v8_snapshot_blob_size = )" // -- v8_snapshot_blob_data begins -- { v8_snapshot_blob_data, v8_snapshot_blob_size }, // -- v8_snapshot_blob_data ends -- - // -- isolate_data_indices begins -- + // -- isolate_data_info begins -- )" << data->isolate_data_info << R"( - // -- isolate_data_indices ends -- + // -- isolate_data_info ends -- , // -- env_info begins -- )" << data->env_info @@ -1231,10 +1231,10 @@ int SnapshotBuilder::Generate(SnapshotData* out, #ifdef NODE_USE_NODE_CODE_CACHE // Regenerate all the code cache. - if (!builtins::BuiltinLoader::CompileAllBuiltins(main_context)) { + if (!env->builtin_loader()->CompileAllBuiltins(main_context)) { return UNCAUGHT_EXCEPTION_ERROR; } - builtins::BuiltinLoader::CopyCodeCache(&(out->code_cache)); + env->builtin_loader()->CopyCodeCache(&(out->code_cache)); for (const auto& item : out->code_cache) { std::string size_str = FormatSize(item.data.size()); per_process::Debug(DebugCategory::MKSNAPSHOT, @@ -1308,11 +1308,11 @@ SnapshotableObject::SnapshotableObject(Realm* realm, EmbedderObjectType type) : BaseObject(realm, wrap), type_(type) {} -std::string_view SnapshotableObject::GetTypeName() const { +std::string SnapshotableObject::GetTypeName() const { switch (type_) { #define V(PropertyName, NativeTypeName) \ case EmbedderObjectType::k_##PropertyName: { \ - return NativeTypeName::type_name.as_string_view(); \ + return #NativeTypeName; \ } SERIALIZABLE_OBJECT_TYPES(V) #undef V @@ -1353,7 +1353,7 @@ void DeserializeNodeInternalFields(Local holder, per_process::Debug(DebugCategory::MKSNAPSHOT, \ "Object %p is %s\n", \ (*holder), \ - NativeTypeName::type_name.as_string_view()); \ + #NativeTypeName); \ env_ptr->EnqueueDeserializeRequest( \ NativeTypeName::Deserialize, \ holder, \ @@ -1440,7 +1440,7 @@ void SerializeSnapshotableObjects(Realm* realm, } SnapshotableObject* ptr = static_cast(obj); - std::string type_name{ptr->GetTypeName()}; + std::string type_name = ptr->GetTypeName(); per_process::Debug(DebugCategory::MKSNAPSHOT, "Serialize snapshotable object %i (%p), " "object=%p, type=%s\n", diff --git a/src/node_snapshotable.h b/src/node_snapshotable.h index 190910ced83eed..28d9dd8c0aee14 100644 --- a/src/node_snapshotable.h +++ b/src/node_snapshotable.h @@ -22,20 +22,6 @@ struct PropInfo { SnapshotIndex index; // In the snapshot }; -#define SERIALIZABLE_OBJECT_TYPES(V) \ - V(fs_binding_data, fs::BindingData) \ - V(v8_binding_data, v8_utils::BindingData) \ - V(blob_binding_data, BlobBindingData) \ - V(process_binding_data, process::BindingData) \ - V(url_binding_data, url::BindingData) \ - V(util_weak_reference, util::WeakReference) - -enum class EmbedderObjectType : uint8_t { -#define V(PropertyName, NativeType) k_##PropertyName, - SERIALIZABLE_OBJECT_TYPES(V) -#undef V -}; - typedef size_t SnapshotIndex; // When serializing an embedder object, we'll serialize the native states @@ -102,7 +88,7 @@ class SnapshotableObject : public BaseObject { SnapshotableObject(Realm* realm, v8::Local wrap, EmbedderObjectType type); - std::string_view GetTypeName() const; + std::string GetTypeName() const; // If returns false, the object will not be serialized. virtual bool PrepareForSerialization(v8::Local context, diff --git a/src/node_threadsafe_cow.h b/src/node_threadsafe_cow.h new file mode 100644 index 00000000000000..8cfdd006b12f57 --- /dev/null +++ b/src/node_threadsafe_cow.h @@ -0,0 +1,105 @@ +#ifndef SRC_NODE_THREADSAFE_COW_H_ +#define SRC_NODE_THREADSAFE_COW_H_ + +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#include "util.h" +#include "uv.h" + +#include // std::shared_ptr +#include // std::forward + +namespace node { + +// Copy-on-write utility. Not threadsafe, i.e. there is no synchronization +// of the copy operation with other operations. +template +class CopyOnWrite final { + public: + template + explicit CopyOnWrite(Args&&... args) + : data_(std::make_shared(std::forward(args)...)) {} + + CopyOnWrite(const CopyOnWrite& other) = default; + CopyOnWrite& operator=(const CopyOnWrite& other) = default; + CopyOnWrite(CopyOnWrite&& other) = default; + CopyOnWrite& operator=(CopyOnWrite&& other) = default; + + const T* read() const { return data_.get(); } + T* write(); + + const T& operator*() const { return *read(); } + const T* operator->() const { return read(); } + + private: + std::shared_ptr data_; +}; + +// Threadsafe copy-on-write utility. Consumers need to use the Read and +// Write helpers to access the target data structure. +template +class ThreadsafeCopyOnWrite final { + private: + // Define this early since some of the public members depend on it + // and some compilers need it to be defined first in that case. + struct Impl { + explicit Impl(const T& data) : data(data) {} + explicit Impl(T&& data) : data(std::move(data)) {} + + Impl(const Impl& other); + Impl& operator=(const Impl& other) = delete; + Impl(Impl&& other) = delete; + Impl& operator=(Impl&& other) = delete; + + RwLock mutex; + T data; + }; + + public: + template + ThreadsafeCopyOnWrite(Args&&... args) + : impl_(T(std::forward(args)...)) {} + + ThreadsafeCopyOnWrite(const ThreadsafeCopyOnWrite& other) = default; + ThreadsafeCopyOnWrite& operator=(const ThreadsafeCopyOnWrite& other) = + default; + ThreadsafeCopyOnWrite(ThreadsafeCopyOnWrite&& other) = default; + ThreadsafeCopyOnWrite& operator=(ThreadsafeCopyOnWrite&& other) = default; + + class Read { + public: + explicit Read(const ThreadsafeCopyOnWrite* cow); + + const T& operator*() const; + const T* operator->() const; + + private: + const ThreadsafeCopyOnWrite* cow_; + RwLock::ScopedReadLock lock_; + }; + + class Write { + public: + explicit Write(ThreadsafeCopyOnWrite* cow); + + T& operator*(); + T* operator->(); + + private: + ThreadsafeCopyOnWrite* cow_; + typename ThreadsafeCopyOnWrite::Impl* impl_; + RwLock::ScopedLock lock_; + }; + + Read read() const { return Read(this); } + Write write() { return Write(this); } + + private: + CopyOnWrite impl_; +}; + +} // namespace node + +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#endif // SRC_NODE_THREADSAFE_COW_H_ diff --git a/src/node_url.cc b/src/node_url.cc index 30a1a6ec9876ba..4d3c8108fa68dc 100644 --- a/src/node_url.cc +++ b/src/node_url.cc @@ -95,6 +95,11 @@ void BindingData::DomainToUnicode(const FunctionCallbackInfo& args) { CHECK(args[0]->IsString()); std::string input = Utf8Value(env->isolate(), args[0]).ToString(); + if (input.empty()) { + return args.GetReturnValue().Set( + String::NewFromUtf8(env->isolate(), "").ToLocalChecked()); + } + // It is important to have an initial value that contains a special scheme. // Since it will change the implementation of `set_hostname` according to URL // spec. @@ -163,7 +168,7 @@ void BindingData::Format(const FunctionCallbackInfo& args) { out->hash = std::nullopt; } - if (unicode) { + if (unicode && out->has_hostname()) { out->host = ada::idna::to_unicode(out->get_hostname()); } diff --git a/src/node_url.h b/src/node_url.h index dd543a97c2e9b4..63b4bccbe3b465 100644 --- a/src/node_url.h +++ b/src/node_url.h @@ -37,9 +37,7 @@ class BindingData : public SnapshotableObject { using InternalFieldInfo = InternalFieldInfoBase; SERIALIZABLE_OBJECT_METHODS() - static constexpr FastStringKey type_name{"node::url::BindingData"}; - static constexpr EmbedderObjectType type_int = - EmbedderObjectType::k_url_binding_data; + SET_BINDING_ID(url_binding_data) void MemoryInfo(MemoryTracker* tracker) const override; SET_SELF_SIZE(BindingData) diff --git a/src/node_util.cc b/src/node_util.cc index f7467caf899d9c..c9b77cb4d2b98b 100644 --- a/src/node_util.cc +++ b/src/node_util.cc @@ -31,6 +31,8 @@ using v8::PropertyFilter; using v8::Proxy; using v8::SKIP_STRINGS; using v8::SKIP_SYMBOLS; +using v8::StackFrame; +using v8::StackTrace; using v8::String; using v8::Uint32; using v8::Value; @@ -137,6 +139,24 @@ static void GetProxyDetails(const FunctionCallbackInfo& args) { } } +static void GetCallerLocation(const FunctionCallbackInfo& args) { + Isolate* isolate = args.GetIsolate(); + Local trace = StackTrace::CurrentStackTrace(isolate, 2); + + // This function is frame zero. The caller is frame one. If there aren't two + // stack frames, return undefined. + if (trace->GetFrameCount() != 2) { + return; + } + + Local frame = trace->GetFrame(isolate, 1); + Local ret[] = {Integer::New(isolate, frame->GetLineNumber()), + Integer::New(isolate, frame->GetColumn()), + frame->GetScriptNameOrSourceURL()}; + + args.GetReturnValue().Set(Array::New(args.GetIsolate(), ret, arraysize(ret))); +} + static void IsArrayBufferDetached(const FunctionCallbackInfo& args) { if (args[0]->IsArrayBuffer()) { auto buffer = args[0].As(); @@ -262,18 +282,13 @@ void WeakReference::Get(const FunctionCallbackInfo& args) { args.GetReturnValue().Set(weak_ref->target_.Get(isolate)); } -void WeakReference::GetRef(const FunctionCallbackInfo& args) { - WeakReference* weak_ref = Unwrap(args.Holder()); - Isolate* isolate = args.GetIsolate(); - args.GetReturnValue().Set( - v8::Number::New(isolate, weak_ref->reference_count_)); -} - void WeakReference::IncRef(const FunctionCallbackInfo& args) { WeakReference* weak_ref = Unwrap(args.Holder()); weak_ref->reference_count_++; if (weak_ref->target_.IsEmpty()) return; if (weak_ref->reference_count_ == 1) weak_ref->target_.ClearWeak(); + args.GetReturnValue().Set( + v8::Number::New(args.GetIsolate(), weak_ref->reference_count_)); } void WeakReference::DecRef(const FunctionCallbackInfo& args) { @@ -282,6 +297,8 @@ void WeakReference::DecRef(const FunctionCallbackInfo& args) { weak_ref->reference_count_--; if (weak_ref->target_.IsEmpty()) return; if (weak_ref->reference_count_ == 0) weak_ref->target_.SetWeak(); + args.GetReturnValue().Set( + v8::Number::New(args.GetIsolate(), weak_ref->reference_count_)); } static void GuessHandleType(const FunctionCallbackInfo& args) { @@ -356,6 +373,7 @@ static void ToUSVString(const FunctionCallbackInfo& args) { void RegisterExternalReferences(ExternalReferenceRegistry* registry) { registry->Register(GetPromiseDetails); registry->Register(GetProxyDetails); + registry->Register(GetCallerLocation); registry->Register(IsArrayBufferDetached); registry->Register(PreviewEntries); registry->Register(GetOwnNonIndexProperties); @@ -365,7 +383,6 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { registry->Register(ArrayBufferViewHasBuffer); registry->Register(WeakReference::New); registry->Register(WeakReference::Get); - registry->Register(WeakReference::GetRef); registry->Register(WeakReference::IncRef); registry->Register(WeakReference::DecRef); registry->Register(GuessHandleType); @@ -430,6 +447,8 @@ void Initialize(Local target, SetMethodNoSideEffect( context, target, "getPromiseDetails", GetPromiseDetails); SetMethodNoSideEffect(context, target, "getProxyDetails", GetProxyDetails); + SetMethodNoSideEffect( + context, target, "getCallerLocation", GetCallerLocation); SetMethodNoSideEffect( context, target, "isArrayBufferDetached", IsArrayBufferDetached); SetMethodNoSideEffect(context, target, "previewEntries", PreviewEntries); @@ -457,7 +476,6 @@ void Initialize(Local target, WeakReference::kInternalFieldCount); weak_ref->Inherit(BaseObject::GetConstructorTemplate(env)); SetProtoMethod(isolate, weak_ref, "get", WeakReference::Get); - SetProtoMethod(isolate, weak_ref, "getRef", WeakReference::GetRef); SetProtoMethod(isolate, weak_ref, "incRef", WeakReference::IncRef); SetProtoMethod(isolate, weak_ref, "decRef", WeakReference::DecRef); SetConstructorFunction(context, target, "WeakReference", weak_ref); diff --git a/src/node_util.h b/src/node_util.h index 7192e080f2b08e..715686856db879 100644 --- a/src/node_util.h +++ b/src/node_util.h @@ -14,16 +14,13 @@ class WeakReference : public SnapshotableObject { public: SERIALIZABLE_OBJECT_METHODS() - static constexpr FastStringKey type_name{"node::util::WeakReference"}; - static constexpr EmbedderObjectType type_int = - EmbedderObjectType::k_util_weak_reference; + SET_OBJECT_ID(util_weak_reference) WeakReference(Realm* realm, v8::Local object, v8::Local target); static void New(const v8::FunctionCallbackInfo& args); static void Get(const v8::FunctionCallbackInfo& args); - static void GetRef(const v8::FunctionCallbackInfo& args); static void IncRef(const v8::FunctionCallbackInfo& args); static void DecRef(const v8::FunctionCallbackInfo& args); diff --git a/src/node_v8.cc b/src/node_v8.cc index f4900328cfe553..82ae6caa952be7 100644 --- a/src/node_v8.cc +++ b/src/node_v8.cc @@ -20,6 +20,7 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. #include "node_v8.h" +#include "aliased_buffer-inl.h" #include "base_object-inl.h" #include "env-inl.h" #include "memory_tracker-inl.h" diff --git a/src/node_v8.h b/src/node_v8.h index 2d95002bcfc473..002f506d20833e 100644 --- a/src/node_v8.h +++ b/src/node_v8.h @@ -23,9 +23,7 @@ class BindingData : public SnapshotableObject { using InternalFieldInfo = InternalFieldInfoBase; SERIALIZABLE_OBJECT_METHODS() - static constexpr FastStringKey type_name{"node::v8::BindingData"}; - static constexpr EmbedderObjectType type_int = - EmbedderObjectType::k_v8_binding_data; + SET_BINDING_ID(v8_binding_data) AliasedFloat64Array heap_statistics_buffer; AliasedFloat64Array heap_space_statistics_buffer; diff --git a/src/node_version.h b/src/node_version.h index 1886d105d7330c..8115df5681d482 100644 --- a/src/node_version.h +++ b/src/node_version.h @@ -23,13 +23,13 @@ #define SRC_NODE_VERSION_H_ #define NODE_MAJOR_VERSION 18 -#define NODE_MINOR_VERSION 18 -#define NODE_PATCH_VERSION 3 +#define NODE_MINOR_VERSION 19 +#define NODE_PATCH_VERSION 0 #define NODE_VERSION_IS_LTS 1 #define NODE_VERSION_LTS_CODENAME "Hydrogen" -#define NODE_VERSION_IS_RELEASE 0 +#define NODE_VERSION_IS_RELEASE 1 #ifndef NODE_STRINGIFY #define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n) diff --git a/src/node_worker.cc b/src/node_worker.cc index 6a49144ec4f205..eef7bc1737aff1 100644 --- a/src/node_worker.cc +++ b/src/node_worker.cc @@ -445,6 +445,8 @@ Worker::~Worker() { void Worker::New(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); + auto is_internal = args[5]; + CHECK(is_internal->IsBoolean()); Isolate* isolate = args.GetIsolate(); CHECK(args.IsConstructCall()); @@ -468,9 +470,9 @@ void Worker::New(const FunctionCallbackInfo& args) { url.append(value.out(), value.length()); } - if (!args[5]->IsNullOrUndefined()) { + if (!args[6]->IsNullOrUndefined()) { Utf8Value value( - isolate, args[5]->ToString(env->context()).FromMaybe(Local())); + isolate, args[6]->ToString(env->context()).FromMaybe(Local())); name.append(value.out(), value.length()); } diff --git a/src/undici_version.h b/src/undici_version.h index 31a28ae20d3510..59e33f5a40b31e 100644 --- a/src/undici_version.h +++ b/src/undici_version.h @@ -2,5 +2,5 @@ // Refer to tools/update-undici.sh #ifndef SRC_UNDICI_VERSION_H_ #define SRC_UNDICI_VERSION_H_ -#define UNDICI_VERSION "5.26.3" +#define UNDICI_VERSION "5.26.4" #endif // SRC_UNDICI_VERSION_H_ diff --git a/src/util.cc b/src/util.cc index 443bbb1e3afe3a..a1d756f67efaf4 100644 --- a/src/util.cc +++ b/src/util.cc @@ -358,6 +358,23 @@ void SetMethod(Local context, function->SetName(name_string); // NODE_SET_METHOD() compatibility. } +void SetMethod(v8::Isolate* isolate, + v8::Local that, + const char* name, + v8::FunctionCallback callback) { + Local t = + NewFunctionTemplate(isolate, + callback, + Local(), + v8::ConstructorBehavior::kThrow, + v8::SideEffectType::kHasSideEffect); + // kInternalized strings are created in the old space. + const v8::NewStringType type = v8::NewStringType::kInternalized; + Local name_string = + v8::String::NewFromUtf8(isolate, name, type).ToLocalChecked(); + that->Set(name_string, t); +} + void SetFastMethod(Local context, Local that, const char* name, diff --git a/src/util.h b/src/util.h index e218d9b62a1eb5..d8fcfe1978052f 100644 --- a/src/util.h +++ b/src/util.h @@ -568,12 +568,6 @@ struct OnScopeLeaveImpl { : fn_(std::move(other.fn_)), active_(other.active_) { other.active_ = false; } - OnScopeLeaveImpl& operator=(OnScopeLeaveImpl&& other) { - if (this == &other) return *this; - this->~OnScopeLeave(); - new (this)OnScopeLeaveImpl(std::move(other)); - return *this; - } }; // Run a function when exiting the current scope. Used like this: @@ -869,6 +863,11 @@ void SetMethod(v8::Local context, v8::Local that, const char* name, v8::FunctionCallback callback); +// Similar to SetProtoMethod but without receiver signature checks. +void SetMethod(v8::Isolate* isolate, + v8::Local that, + const char* name, + v8::FunctionCallback callback); void SetFastMethod(v8::Local context, v8::Local that, diff --git a/test/abort/test-addon-uv-handle-leak.js b/test/abort/test-addon-uv-handle-leak.js index e494b12f2de558..d2c4f8e646f457 100644 --- a/test/abort/test-addon-uv-handle-leak.js +++ b/test/abort/test-addon-uv-handle-leak.js @@ -78,6 +78,7 @@ if (process.argv[2] === 'child') { if (!(common.isFreeBSD || common.isAIX || + common.isIBMi || (common.isLinux && !isGlibc()) || common.isWindows)) { assert(stderr.includes('ExampleOwnerClass'), stderr); diff --git a/test/async-hooks/async-hooks.status b/test/async-hooks/async-hooks.status index 673883e4fe3d4d..dbcb29baed84a0 100644 --- a/test/async-hooks/async-hooks.status +++ b/test/async-hooks/async-hooks.status @@ -21,3 +21,5 @@ test-callback-error: PASS, FLAKY [$system==freebsd] [$system==aix] +# https://github.com/nodejs/node/issues/50245 +test-emit-after-on-destroyed: PASS, FLAKY diff --git a/test/cctest/test_aliased_buffer.cc b/test/cctest/test_aliased_buffer.cc index ba947700c1bf27..6d62444d42c7cc 100644 --- a/test/cctest/test_aliased_buffer.cc +++ b/test/cctest/test_aliased_buffer.cc @@ -1,6 +1,6 @@ -#include "v8.h" -#include "aliased_buffer.h" +#include "aliased_buffer-inl.h" #include "node_test_fixture.h" +#include "v8.h" using node::AliasedBufferBase; diff --git a/test/cctest/test_node_crypto_env.cc b/test/cctest/test_node_crypto_env.cc index b42cdc107e8a94..001867720f5e80 100644 --- a/test/cctest/test_node_crypto_env.cc +++ b/test/cctest/test_node_crypto_env.cc @@ -23,8 +23,9 @@ TEST_F(NodeCryptoEnv, LoadBIO) { Local key = String::NewFromUtf8(isolate_, "abcdef").ToLocalChecked(); node::crypto::BIOPointer bio(node::crypto::LoadBIO(*env, key)); #if OPENSSL_VERSION_NUMBER >= 0x30000000L - BIO_seek(bio.get(), 2); - ASSERT_EQ(BIO_tell(bio.get()), 2); + const int ofs = 2; + ASSERT_EQ(BIO_seek(bio.get(), ofs), ofs); + ASSERT_EQ(BIO_tell(bio.get()), ofs); #endif ASSERT_EQ(ERR_peek_error(), 0UL) << "There should not have left " "any errors on the OpenSSL error stack\n"; diff --git a/test/cctest/test_per_process.cc b/test/cctest/test_per_process.cc index 1e3dff7114e337..34cf163add7904 100644 --- a/test/cctest/test_per_process.cc +++ b/test/cctest/test_per_process.cc @@ -1,4 +1,5 @@ #include "node_builtins.h" +#include "node_threadsafe_cow-inl.h" #include "gtest/gtest.h" #include "node_test_fixture.h" @@ -11,7 +12,7 @@ using node::builtins::BuiltinSourceMap; class PerProcessTest : public ::testing::Test { protected: static const BuiltinSourceMap get_sources_for_test() { - return BuiltinLoader::instance_.source_; + return *BuiltinLoader().source_.read(); } }; diff --git a/test/common/README.md b/test/common/README.md index 86c6e4208a648d..3f68c5d8f5788f 100644 --- a/test/common/README.md +++ b/test/common/README.md @@ -6,6 +6,7 @@ This directory contains modules used to test the Node.js implementation. * [ArrayStream module](#arraystream-module) * [Benchmark module](#benchmark-module) +* [Child process module](#child-process-module) * [Common module API](#common-module-api) * [Countdown module](#countdown-module) * [CPU Profiler module](#cpu-profiler-module) @@ -35,6 +36,42 @@ The `benchmark` module is used by tests to run benchmarks. * `env` [\][] Environment variables to be applied during the run. +## Child Process Module + +The `child_process` module is used by tests that launch child processes. + +### `expectSyncExit(child, options)` + +Checks if a _synchronous_ child process runs in the way expected. If it does +not, print the stdout and stderr output from the child process and additional +information about it to the stderr of the current process before throwing +and error. This helps gathering more information about test failures +coming from child processes. + +* `child` [\][]: a `ChildProcess` instance + returned by `child_process.spawnSync()`. +* `options` [\][] + * `status` [\][] Expected `child.status` + * `signal` [\][] | `null` Expected `child.signal` + * `stderr` [\][] | [\][] | + [\][] Optional. If it's a string, check that the output + to the stderr of the child process is exactly the same as the string. If + it's a regular expression, check that the stderr matches it. If it's a + function, invoke it with the stderr output as a string and check + that it returns true. The function can just throw errors (e.g. assertion + errors) to provide more information if the check fails. + * `stdout` [\][] | [\][] | + [\][] Optional. Similar to `stderr` but for the stdout. + * `trim` [\][] Optional. Whether this method should trim + out the whitespace characters when checking `stderr` and `stdout` outputs. + Defaults to `false`. + +### `expectSyncExitWithoutError(child[, options])` + +Similar to `expectSyncExit()` with the `status` expected to be 0 and +`signal` expected to be `null`. Any other optional options are passed +into `expectSyncExit()`. + ## Common Module API The `common` module is used by tests for consistency across repeated @@ -1011,6 +1048,16 @@ The `tmpdir` module supports the use of a temporary directory for testing. The realpath of the testing temporary directory. +### `fileURL([...paths])` + +* `...paths` [\][] +* return [\][] + +Resolves a sequence of paths into absolute url in the temporary directory. + +When called without arguments, returns absolute url of the testing +temporary directory with explicit trailing `/`. + ### `refresh()` Deletes and recreates the testing temporary directory. @@ -1076,10 +1123,12 @@ See [the WPT tests README][] for details. []: https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView []: https://nodejs.org/api/buffer.html#buffer_class_buffer []: https://developer.mozilla.org/en-US/docs/Web/API/BufferSource +[]: ../../doc/api/child_process.md#class-childprocess []: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error []: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function []: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object []: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp +[]: https://developer.mozilla.org/en-US/docs/Web/API/URL []: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Data_types []: https://github.com/tc39/proposal-bigint []: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type diff --git a/test/common/assertSnapshot.js b/test/common/assertSnapshot.js index c403751ac3ef5e..88f40281e069b7 100644 --- a/test/common/assertSnapshot.js +++ b/test/common/assertSnapshot.js @@ -5,9 +5,13 @@ const test = require('node:test'); const fs = require('node:fs/promises'); const assert = require('node:assert/strict'); -const stackFramesRegexp = /(\s+)((.+?)\s+\()?(?:\(?(.+?):(\d+)(?::(\d+))?)\)?(\s+\{)?(\[\d+m)?(\n|$)/g; +const stackFramesRegexp = /(?<=\n)(\s+)((.+?)\s+\()?(?:\(?(.+?):(\d+)(?::(\d+))?)\)?(\s+\{)?(\[\d+m)?(\n|$)/g; const windowNewlineRegexp = /\r/g; +function replaceNodeVersion(str) { + return str.replaceAll(process.version, '*'); +} + function replaceStackTrace(str, replacement = '$1*$7$8\n') { return str.replace(stackFramesRegexp, replacement); } @@ -17,7 +21,11 @@ function replaceWindowsLineEndings(str) { } function replaceWindowsPaths(str) { - return str.replaceAll(path.win32.sep, path.posix.sep); + return common.isWindows ? str.replaceAll(path.win32.sep, path.posix.sep) : str; +} + +function replaceFullPaths(str) { + return str.replaceAll(process.cwd(), ''); } function transform(...args) { @@ -34,7 +42,17 @@ async function assertSnapshot(actual, filename = process.argv[1]) { if (process.env.NODE_REGENERATE_SNAPSHOTS) { await fs.writeFile(snapshot, actual); } else { - const expected = await fs.readFile(snapshot, 'utf8'); + let expected; + try { + expected = await fs.readFile(snapshot, 'utf8'); + } catch (e) { + if (e.code === 'ENOENT') { + console.log( + 'Snapshot file does not exist. You can create a new one by running the test with NODE_REGENERATE_SNAPSHOTS=1', + ); + } + throw e; + } assert.strictEqual(actual, replaceWindowsLineEndings(expected)); } } @@ -69,6 +87,8 @@ async function spawnAndAssert(filename, transform = (x) => x, { tty = false, ... module.exports = { assertSnapshot, getSnapshotPath, + replaceFullPaths, + replaceNodeVersion, replaceStackTrace, replaceWindowsLineEndings, replaceWindowsPaths, diff --git a/test/common/child_process.js b/test/common/child_process.js index 799c963a7ed7dc..a53dddc19f3216 100644 --- a/test/common/child_process.js +++ b/test/common/child_process.js @@ -2,6 +2,7 @@ const assert = require('assert'); const common = require('./'); +const util = require('util'); // Workaround for Windows Server 2008R2 // When CMD is used to launch a process and CMD is killed too quickly, the @@ -41,9 +42,88 @@ function logAfterTime(time) { }, time); } +function checkOutput(str, check) { + if ((check instanceof RegExp && !check.test(str)) || + (typeof check === 'string' && check !== str)) { + return { passed: false, reason: `did not match ${util.inspect(check)}` }; + } + if (typeof check === 'function') { + try { + check(str); + } catch (error) { + return { + passed: false, + reason: `did not match expectation, checker throws:\n${util.inspect(error)}`, + }; + } + } + return { passed: true }; +} + +function expectSyncExit(child, { + status, + signal, + stderr: stderrCheck, + stdout: stdoutCheck, + trim = false, +}) { + const failures = []; + let stderrStr, stdoutStr; + if (status !== undefined && child.status !== status) { + failures.push(`- process terminated with status ${child.status}, expected ${status}`); + } + if (signal !== undefined && child.signal !== signal) { + failures.push(`- process terminated with signal ${child.signal}, expected ${signal}`); + } + + function logAndThrow() { + const tag = `[process ${child.pid}]:`; + console.error(`${tag} --- stderr ---`); + console.error(stderrStr === undefined ? child.stderr.toString() : stderrStr); + console.error(`${tag} --- stdout ---`); + console.error(stdoutStr === undefined ? child.stdout.toString() : stdoutStr); + console.error(`${tag} status = ${child.status}, signal = ${child.signal}`); + throw new Error(`${failures.join('\n')}`); + } + + // If status and signal are not matching expectations, fail early. + if (failures.length !== 0) { + logAndThrow(); + } + + if (stderrCheck !== undefined) { + stderrStr = child.stderr.toString(); + const { passed, reason } = checkOutput(trim ? stderrStr.trim() : stderrStr, stderrCheck); + if (!passed) { + failures.push(`- stderr ${reason}`); + } + } + if (stdoutCheck !== undefined) { + stdoutStr = child.stdout.toString(); + const { passed, reason } = checkOutput(trim ? stdoutStr.trim() : stdoutStr, stdoutCheck); + if (!passed) { + failures.push(`- stdout ${reason}`); + } + } + if (failures.length !== 0) { + logAndThrow(); + } + return { child, stderr: stderrStr, stdout: stdoutStr }; +} + +function expectSyncExitWithoutError(child, options) { + return expectSyncExit(child, { + status: 0, + signal: null, + ...options, + }); +} + module.exports = { cleanupStaleProcess, logAfterTime, kExpiringChildRunTime, kExpiringParentTimer, + expectSyncExit, + expectSyncExitWithoutError, }; diff --git a/test/common/crypto.js b/test/common/crypto.js index 8919b54d1fc632..ba47285df49a43 100644 --- a/test/common/crypto.js +++ b/test/common/crypto.js @@ -6,6 +6,14 @@ if (!common.hasCrypto) const assert = require('assert'); const crypto = require('crypto'); +const { + createSign, + createVerify, + publicEncrypt, + privateDecrypt, + sign, + verify, +} = crypto; // The values below (modp2/modp2buf) are for a 1024 bits long prime from // RFC 2412 E.2, see https://tools.ietf.org/html/rfc2412. */ @@ -42,7 +50,83 @@ function testDH({ publicKey: alicePublicKey, privateKey: alicePrivateKey }, assert.deepStrictEqual(buf1, expectedValue); } +// Asserts that the size of the given key (in chars or bytes) is within 10% of +// the expected size. +function assertApproximateSize(key, expectedSize) { + const u = typeof key === 'string' ? 'chars' : 'bytes'; + const min = Math.floor(0.9 * expectedSize); + const max = Math.ceil(1.1 * expectedSize); + assert(key.length >= min, + `Key (${key.length} ${u}) is shorter than expected (${min} ${u})`); + assert(key.length <= max, + `Key (${key.length} ${u}) is longer than expected (${max} ${u})`); +} + +// Tests that a key pair can be used for encryption / decryption. +function testEncryptDecrypt(publicKey, privateKey) { + const message = 'Hello Node.js world!'; + const plaintext = Buffer.from(message, 'utf8'); + for (const key of [publicKey, privateKey]) { + const ciphertext = publicEncrypt(key, plaintext); + const received = privateDecrypt(privateKey, ciphertext); + assert.strictEqual(received.toString('utf8'), message); + } +} + +// Tests that a key pair can be used for signing / verification. +function testSignVerify(publicKey, privateKey) { + const message = Buffer.from('Hello Node.js world!'); + + function oldSign(algo, data, key) { + return createSign(algo).update(data).sign(key); + } + + function oldVerify(algo, data, key, signature) { + return createVerify(algo).update(data).verify(key, signature); + } + + for (const signFn of [sign, oldSign]) { + const signature = signFn('SHA256', message, privateKey); + for (const verifyFn of [verify, oldVerify]) { + for (const key of [publicKey, privateKey]) { + const okay = verifyFn('SHA256', message, key, signature); + assert(okay); + } + } + } +} + +// Constructs a regular expression for a PEM-encoded key with the given label. +function getRegExpForPEM(label, cipher) { + const head = `\\-\\-\\-\\-\\-BEGIN ${label}\\-\\-\\-\\-\\-`; + const rfc1421Header = cipher == null ? '' : + `\nProc-Type: 4,ENCRYPTED\nDEK-Info: ${cipher},[^\n]+\n`; + const body = '([a-zA-Z0-9\\+/=]{64}\n)*[a-zA-Z0-9\\+/=]{1,64}'; + const end = `\\-\\-\\-\\-\\-END ${label}\\-\\-\\-\\-\\-`; + return new RegExp(`^${head}${rfc1421Header}\n${body}\n${end}\n$`); +} + +const pkcs1PubExp = getRegExpForPEM('RSA PUBLIC KEY'); +const pkcs1PrivExp = getRegExpForPEM('RSA PRIVATE KEY'); +const pkcs1EncExp = (cipher) => getRegExpForPEM('RSA PRIVATE KEY', cipher); +const spkiExp = getRegExpForPEM('PUBLIC KEY'); +const pkcs8Exp = getRegExpForPEM('PRIVATE KEY'); +const pkcs8EncExp = getRegExpForPEM('ENCRYPTED PRIVATE KEY'); +const sec1Exp = getRegExpForPEM('EC PRIVATE KEY'); +const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher); + module.exports = { modp2buf, testDH, + assertApproximateSize, + testEncryptDecrypt, + testSignVerify, + pkcs1PubExp, + pkcs1PrivExp, + pkcs1EncExp, // used once + spkiExp, + pkcs8Exp, // used once + pkcs8EncExp, // used once + sec1Exp, + sec1EncExp, }; diff --git a/test/common/index.js b/test/common/index.js index e0c6e7aa0c996e..e25b861cce1cd6 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -56,7 +56,10 @@ const hasCrypto = Boolean(process.versions.openssl) && !process.env.NODE_SKIP_CRYPTO; const hasOpenSSL3 = hasCrypto && - require('crypto').constants.OPENSSL_VERSION_NUMBER >= 805306368; + require('crypto').constants.OPENSSL_VERSION_NUMBER >= 0x30000000; + +const hasOpenSSL31 = hasCrypto && + require('crypto').constants.OPENSSL_VERSION_NUMBER >= 0x30100000; const hasQuic = hasCrypto && !!process.config.variables.openssl_quic; @@ -119,7 +122,6 @@ if (process.argv.length === 2 && } const isWindows = process.platform === 'win32'; -const isAIX = process.platform === 'aix'; const isSunOS = process.platform === 'sunos'; const isFreeBSD = process.platform === 'freebsd'; const isOpenBSD = process.platform === 'openbsd'; @@ -262,7 +264,7 @@ function platformTimeout(ms) { if (process.features.debug) ms = multipliers.two * ms; - if (isAIX) + if (exports.isAIX || exports.isIBMi) return multipliers.two * ms; // Default localhost speed is slower on AIX if (isPi) @@ -899,10 +901,10 @@ const common = { hasIntl, hasCrypto, hasOpenSSL3, + hasOpenSSL31, hasQuic, hasMultiLocalhost, invalidArgTypeHelper, - isAIX, isAlive, isAsan, isDumbTerminal, @@ -946,7 +948,14 @@ const common = { get hasIPv6() { const iFaces = require('os').networkInterfaces(); - const re = isWindows ? /Loopback Pseudo-Interface/ : /lo/; + let re; + if (isWindows) { + re = /Loopback Pseudo-Interface/; + } else if (this.isIBMi) { + re = /\*LOOPBACK/; + } else { + re = /lo/; + } return Object.keys(iFaces).some((name) => { return re.test(name) && iFaces[name].some(({ family }) => family === 'IPv6'); @@ -966,7 +975,12 @@ const common = { }, // On IBMi, process.platform and os.platform() both return 'aix', + // when built with Python versions earlier than 3.9. // It is not enough to differentiate between IBMi and real AIX system. + get isAIX() { + return require('os').type() === 'AIX'; + }, + get isIBMi() { return require('os').type() === 'OS400'; }, diff --git a/test/common/index.mjs b/test/common/index.mjs index 6b4cd00e410d78..ca2994f6e1360f 100644 --- a/test/common/index.mjs +++ b/test/common/index.mjs @@ -4,105 +4,105 @@ const require = createRequire(import.meta.url); const common = require('./index.js'); const { - isMainThread, - isWindows, + allowGlobals, + buildType, + canCreateSymLink, + checkoutEOL, + childShouldThrowAndAbort, + createZeroFilledFile, + enoughTestMem, + expectsError, + expectWarning, + getArrayBufferViews, + getBufferSources, + getCallSite, + getTTYfd, + hasCrypto, + hasIPv6, + hasMultiLocalhost, isAIX, - isIBMi, - isLinuxPPCBE, - isSunOS, + isAlive, isDumbTerminal, isFreeBSD, - isOpenBSD, + isIBMi, isLinux, + isLinuxPPCBE, + isMainThread, + isOpenBSD, isOSX, - enoughTestMem, - buildType, + isSunOS, + isWindows, localIPv6Hosts, - opensslCli, - PIPE, - hasCrypto, - hasIPv6, - childShouldThrowAndAbort, - checkoutEOL, - createZeroFilledFile, - platformTimeout, - allowGlobals, mustCall, mustCallAtLeast, - mustSucceed, - hasMultiLocalhost, - skipIfDumbTerminal, - skipIfEslintMissing, - canCreateSymLink, - getCallSite, mustNotCall, mustNotMutateObjectDeep, + mustSucceed, + nodeProcessAborted, + opensslCli, parseTestFlags, + PIPE, + platformTimeout, printSkipMessage, + runWithInvalidFD, skip, - nodeProcessAborted, - isAlive, - expectWarning, - expectsError, - skipIfInspectorDisabled, skipIf32Bits, - getArrayBufferViews, - getBufferSources, - getTTYfd, - runWithInvalidFD, + skipIfDumbTerminal, + skipIfEslintMissing, + skipIfInspectorDisabled, spawnPromisified, } = common; const getPort = () => common.PORT; export { - isMainThread, - isWindows, + allowGlobals, + buildType, + canCreateSymLink, + checkoutEOL, + childShouldThrowAndAbort, + createRequire, + createZeroFilledFile, + enoughTestMem, + expectsError, + expectWarning, + getArrayBufferViews, + getBufferSources, + getCallSite, + getPort, + getTTYfd, + hasCrypto, + hasIPv6, + hasMultiLocalhost, isAIX, - isIBMi, - isLinuxPPCBE, - isSunOS, + isAlive, isDumbTerminal, isFreeBSD, - isOpenBSD, + isIBMi, isLinux, + isLinuxPPCBE, + isMainThread, + isOpenBSD, isOSX, - enoughTestMem, - buildType, + isSunOS, + isWindows, localIPv6Hosts, - opensslCli, - PIPE, - hasCrypto, - hasIPv6, - childShouldThrowAndAbort, - checkoutEOL, - createZeroFilledFile, - platformTimeout, - allowGlobals, mustCall, mustCallAtLeast, - mustSucceed, - hasMultiLocalhost, - skipIfDumbTerminal, - skipIfEslintMissing, - canCreateSymLink, - getCallSite, mustNotCall, mustNotMutateObjectDeep, + mustSucceed, + nodeProcessAborted, + opensslCli, parseTestFlags, + PIPE, + platformTimeout, printSkipMessage, + runWithInvalidFD, skip, - nodeProcessAborted, - isAlive, - expectWarning, - expectsError, - skipIfInspectorDisabled, skipIf32Bits, - getArrayBufferViews, - getBufferSources, - getTTYfd, - runWithInvalidFD, - createRequire, + skipIfDumbTerminal, + skipIfEslintMissing, + skipIfInspectorDisabled, spawnPromisified, - getPort, }; diff --git a/test/common/package.json b/test/common/package.json new file mode 100644 index 00000000000000..5bbefffbabee39 --- /dev/null +++ b/test/common/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/test/common/tmpdir.js b/test/common/tmpdir.js index decfa97a892771..19e997e937559f 100644 --- a/test/common/tmpdir.js +++ b/test/common/tmpdir.js @@ -2,6 +2,7 @@ const fs = require('fs'); const path = require('path'); +const { pathToFileURL } = require('url'); const { isMainThread } = require('worker_threads'); function rmSync(pathname) { @@ -64,9 +65,17 @@ function hasEnoughSpace(size) { return bavail >= Math.ceil(size / bsize); } +function fileURL(...paths) { + // When called without arguments, add explicit trailing slash + const fullPath = path.resolve(tmpPath + path.sep, ...paths); + + return pathToFileURL(fullPath); +} + module.exports = { + fileURL, + hasEnoughSpace, path: tmpPath, refresh, - hasEnoughSpace, resolve, }; diff --git a/test/common/wpt.js b/test/common/wpt.js index 976668b69bfde3..f7511f3c06814f 100644 --- a/test/common/wpt.js +++ b/test/common/wpt.js @@ -408,7 +408,7 @@ class WPTRunner { this.resource = new ResourceLoader(path); this.flags = []; - this.dummyGlobalThisScript = null; + this.globalThisInitScripts = []; this.initScript = null; this.status = new StatusLoader(path); @@ -463,17 +463,17 @@ class WPTRunner { initScript = `${initScript}\n\n//===\nglobalThis.location.search = "${locationSearchString}";`; } - if (initScript === null && this.dummyGlobalThisScript === null) { - return null; + if (this.globalThisInitScripts.length === null) { + return initScript; } + const globalThisInitScript = this.globalThisInitScripts.join('\n\n//===\n'); + if (initScript === null) { - return this.dummyGlobalThisScript; - } else if (this.dummyGlobalThisScript === null) { - return initScript; + return globalThisInitScript; } - return `${this.dummyGlobalThisScript}\n\n//===\n${initScript}`; + return `${globalThisInitScript}\n\n//===\n${initScript}`; } /** @@ -484,8 +484,10 @@ class WPTRunner { pretendGlobalThisAs(name) { switch (name) { case 'Window': { - this.dummyGlobalThisScript = - 'global.Window = Object.getPrototypeOf(globalThis).constructor;'; + this.globalThisInitScripts.push( + `global.Window = Object.getPrototypeOf(globalThis).constructor; + self.GLOBAL.isWorker = () => false;`); + this.loadLazyGlobals(); break; } @@ -499,6 +501,32 @@ class WPTRunner { } } + loadLazyGlobals() { + const lazyProperties = [ + 'DOMException', + 'Performance', 'PerformanceEntry', 'PerformanceMark', 'PerformanceMeasure', + 'PerformanceObserver', 'PerformanceObserverEntryList', 'PerformanceResourceTiming', + 'Blob', 'atob', 'btoa', + 'MessageChannel', 'MessagePort', 'MessageEvent', + 'EventTarget', 'Event', + 'AbortController', 'AbortSignal', + 'performance', + 'TransformStream', 'TransformStreamDefaultController', + 'WritableStream', 'WritableStreamDefaultController', 'WritableStreamDefaultWriter', + 'ReadableStream', 'ReadableStreamDefaultReader', + 'ReadableStreamBYOBReader', 'ReadableStreamBYOBRequest', + 'ReadableByteStreamController', 'ReadableStreamDefaultController', + 'ByteLengthQueuingStrategy', 'CountQueuingStrategy', + 'TextEncoderStream', 'TextDecoderStream', + 'CompressionStream', 'DecompressionStream', + ]; + if (Boolean(process.versions.openssl) && !process.env.NODE_SKIP_CRYPTO) { + lazyProperties.push('crypto'); + } + const script = lazyProperties.map((name) => `globalThis.${name};`).join('\n'); + this.globalThisInitScripts.push(script); + } + // TODO(joyeecheung): work with the upstream to port more tests in .html // to .js. async runJsTests() { diff --git a/test/es-module/test-cjs-esm-warn.js b/test/es-module/test-cjs-esm-warn.js index c1d60a209502bb..7ac85fd58c5f18 100644 --- a/test/es-module/test-cjs-esm-warn.js +++ b/test/es-module/test-cjs-esm-warn.js @@ -31,7 +31,7 @@ describe('CJS ↔︎ ESM interop warnings', { concurrency: true }, () => { ); assert.ok( stderr.replaceAll('\r', '').includes( - `Instead rename ${basename} to end in .cjs, change the requiring ` + + `Instead either rename ${basename} to end in .cjs, change the requiring ` + 'code to use dynamic import() which is available in all CommonJS ' + `modules, or change "type": "module" to "type": "commonjs" in ${pjson} to ` + 'treat all .js files as CommonJS (using .mjs for all ES modules ' + diff --git a/test/es-module/test-esm-dynamic-import-assertion.js b/test/es-module/test-esm-dynamic-import-attribute.js similarity index 100% rename from test/es-module/test-esm-dynamic-import-assertion.js rename to test/es-module/test-esm-dynamic-import-attribute.js diff --git a/test/es-module/test-esm-dynamic-import-assertion.mjs b/test/es-module/test-esm-dynamic-import-attribute.mjs similarity index 100% rename from test/es-module/test-esm-dynamic-import-assertion.mjs rename to test/es-module/test-esm-dynamic-import-attribute.mjs diff --git a/test/es-module/test-esm-dynamic-import-mutating-fs.js b/test/es-module/test-esm-dynamic-import-mutating-fs.js new file mode 100644 index 00000000000000..b3e3bd899a93e8 --- /dev/null +++ b/test/es-module/test-esm-dynamic-import-mutating-fs.js @@ -0,0 +1,22 @@ +'use strict'; +const common = require('../common'); +const tmpdir = require('../common/tmpdir'); + +const assert = require('node:assert'); +const fs = require('node:fs/promises'); + +tmpdir.refresh(); +const target = tmpdir.fileURL(`${Math.random()}.mjs`); + +(async () => { + + await assert.rejects(import(target), { code: 'ERR_MODULE_NOT_FOUND' }); + + await fs.writeFile(target, 'export default "actual target"\n'); + + const moduleRecord = await import(target); + + await fs.rm(target); + + assert.strictEqual(await import(target), moduleRecord); +})().then(common.mustCall()); diff --git a/test/es-module/test-esm-dynamic-import-mutating-fs.mjs b/test/es-module/test-esm-dynamic-import-mutating-fs.mjs new file mode 100644 index 00000000000000..74a75ddd1c4824 --- /dev/null +++ b/test/es-module/test-esm-dynamic-import-mutating-fs.mjs @@ -0,0 +1,39 @@ +import { spawnPromisified } from '../common/index.mjs'; +import tmpdir from '../common/tmpdir.js'; + +import assert from 'node:assert'; +import fs from 'node:fs/promises'; +import { execPath } from 'node:process'; + +tmpdir.refresh(); +const target = tmpdir.fileURL(`${Math.random()}.mjs`); + +await assert.rejects(import(target), { code: 'ERR_MODULE_NOT_FOUND' }); + +await fs.writeFile(target, 'export default "actual target"\n'); + +const moduleRecord = await import(target); + +await fs.rm(target); + +assert.strictEqual(await import(target), moduleRecord); + +// Add the file back, it should be deleted by the subprocess. +await fs.writeFile(target, 'export default "actual target"\n'); + +assert.deepStrictEqual( + await spawnPromisified(execPath, [ + '--input-type=module', + '--eval', + [`import * as d from${JSON.stringify(target)};`, + 'import{rm}from"node:fs/promises";', + `await rm(new URL(${JSON.stringify(target)}));`, + 'import{strictEqual}from"node:assert";', + `strictEqual(JSON.stringify(await import(${JSON.stringify(target)})),JSON.stringify(d));`].join(''), + ]), + { + code: 0, + signal: null, + stderr: '', + stdout: '', + }); diff --git a/test/es-module/test-esm-dynamic-import.js b/test/es-module/test-esm-dynamic-import.js index ac6b35ebc1bc15..d246841c2a6d8b 100644 --- a/test/es-module/test-esm-dynamic-import.js +++ b/test/es-module/test-esm-dynamic-import.js @@ -1,11 +1,11 @@ 'use strict'; const common = require('../common'); +const { pathToFileURL } = require('url'); const assert = require('assert'); const relativePath = '../fixtures/es-modules/test-esm-ok.mjs'; -const absolutePath = require.resolve('../fixtures/es-modules/test-esm-ok.mjs'); -const targetURL = new URL('file:///'); -targetURL.pathname = absolutePath; +const absolutePath = require.resolve(relativePath); +const targetURL = pathToFileURL(absolutePath); function expectModuleError(result, code, message) { Promise.resolve(result).catch(common.mustCall((error) => { @@ -41,7 +41,7 @@ function expectFsNamespace(result) { // expectOkNamespace(import(relativePath)); expectOkNamespace(eval(`import("${relativePath}")`)); expectOkNamespace(eval(`import("${relativePath}")`)); - expectOkNamespace(eval(`import("${targetURL}")`)); + expectOkNamespace(eval(`import(${JSON.stringify(targetURL)})`)); // Importing a built-in, both direct & via eval expectFsNamespace(import('fs')); diff --git a/test/es-module/test-esm-experimental-warnings.mjs b/test/es-module/test-esm-experimental-warnings.mjs index fc167c63584b87..68a48f2d697bcf 100644 --- a/test/es-module/test-esm-experimental-warnings.mjs +++ b/test/es-module/test-esm-experimental-warnings.mjs @@ -24,15 +24,19 @@ describe('ESM: warn for obsolete hooks provided', { concurrency: true }, () => { describe('experimental warnings for enabled experimental feature', () => { for ( - const [experiment, arg] of [ - [/Custom ESM Loaders/, `--experimental-loader=${fileURL('es-module-loaders', 'hooks-custom.mjs')}`], + const [experiment, ...args] of [ + [ + /`--experimental-loader` may be removed in the future/, + '--experimental-loader', + fileURL('es-module-loaders', 'hooks-custom.mjs'), + ], [/Network Imports/, '--experimental-network-imports'], [/specifier resolution/, '--experimental-specifier-resolution=node'], ] ) { it(`should print for ${experiment.toString().replaceAll('/', '')}`, async () => { const { code, signal, stderr } = await spawnPromisified(execPath, [ - arg, + ...args, '--input-type=module', '--eval', `import ${JSON.stringify(fileURL('es-module-loaders', 'module-named-exports.mjs'))}`, diff --git a/test/es-module/test-esm-extension-lookup-deprecation.mjs b/test/es-module/test-esm-extension-lookup-deprecation.mjs index e8da1a8b176bc7..dc391486f7edc2 100644 --- a/test/es-module/test-esm-extension-lookup-deprecation.mjs +++ b/test/es-module/test-esm-extension-lookup-deprecation.mjs @@ -1,5 +1,5 @@ import { spawnPromisified } from '../common/index.mjs'; -import * as tmpdir from '../common/tmpdir.js'; +import tmpdir from '../common/tmpdir.js'; import assert from 'node:assert'; import { mkdir, writeFile } from 'node:fs/promises'; diff --git a/test/es-module/test-esm-extensionless-esm-and-wasm.mjs b/test/es-module/test-esm-extensionless-esm-and-wasm.mjs new file mode 100644 index 00000000000000..db20bc047feec1 --- /dev/null +++ b/test/es-module/test-esm-extensionless-esm-and-wasm.mjs @@ -0,0 +1,106 @@ +// Flags: --experimental-wasm-modules +import { mustNotCall, spawnPromisified } from '../common/index.mjs'; +import * as fixtures from '../common/fixtures.mjs'; +import { describe, it } from 'node:test'; +import { match, ok, strictEqual } from 'node:assert'; + +describe('extensionless ES modules within a "type": "module" package scope', { concurrency: true }, () => { + it('should run as the entry point', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + fixtures.path('es-modules/package-type-module/noext-esm'), + ]); + + strictEqual(stderr, ''); + strictEqual(stdout, 'executed\n'); + strictEqual(code, 0); + strictEqual(signal, null); + }); + + it('should be importable', async () => { + const { default: defaultExport } = + await import(fixtures.fileURL('es-modules/package-type-module/noext-esm')); + strictEqual(defaultExport, 'module'); + }); + + it('should be importable from a module scope under node_modules', async () => { + const { default: defaultExport } = + await import(fixtures.fileURL( + 'es-modules/package-type-module/node_modules/dep-with-package-json-type-module/noext-esm')); + strictEqual(defaultExport, 'module'); + }); +}); +describe('extensionless Wasm modules within a "type": "module" package scope', { concurrency: true }, () => { + it('should run as the entry point', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-wasm-modules', + '--no-warnings', + fixtures.path('es-modules/package-type-module/noext-wasm'), + ]); + + strictEqual(stderr, ''); + strictEqual(stdout, 'executed\n'); + strictEqual(code, 0); + strictEqual(signal, null); + }); + + it('should be importable', async () => { + const { add } = await import(fixtures.fileURL('es-modules/package-type-module/noext-wasm')); + strictEqual(add(1, 2), 3); + }); + + it('should be importable from a module scope under node_modules', async () => { + const { add } = await import(fixtures.fileURL( + 'es-modules/package-type-module/node_modules/dep-with-package-json-type-module/noext-wasm')); + strictEqual(add(1, 2), 3); + }); +}); + +describe('extensionless ES modules within no package scope', { concurrency: true }, () => { + // This succeeds with `--experimental-default-type=module` + it('should error as the entry point', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + fixtures.path('es-modules/noext-esm'), + ]); + + match(stderr, /SyntaxError/); + strictEqual(stdout, ''); + strictEqual(code, 1); + strictEqual(signal, null); + }); + + // This succeeds with `--experimental-default-type=module` + it('should error on import', async () => { + try { + await import(fixtures.fileURL('es-modules/noext-esm')); + mustNotCall(); + } catch (err) { + ok(err instanceof SyntaxError); + } + }); +}); + +describe('extensionless Wasm within no package scope', { concurrency: true }, () => { + // This succeeds with `--experimental-default-type=module` + it('should error as the entry point', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-wasm-modules', + '--no-warnings', + fixtures.path('es-modules/noext-wasm'), + ]); + + match(stderr, /SyntaxError/); + strictEqual(stdout, ''); + strictEqual(code, 1); + strictEqual(signal, null); + }); + + // This succeeds with `--experimental-default-type=module` + it('should error on import', async () => { + try { + await import(fixtures.fileURL('es-modules/noext-wasm')); + mustNotCall(); + } catch (err) { + ok(err instanceof SyntaxError); + } + }); +}); diff --git a/test/es-module/test-esm-import-assertion-2.mjs b/test/es-module/test-esm-import-assertion-2.mjs deleted file mode 100644 index 8001c29772b1f0..00000000000000 --- a/test/es-module/test-esm-import-assertion-2.mjs +++ /dev/null @@ -1,6 +0,0 @@ -import '../common/index.mjs'; -import { strictEqual } from 'assert'; - -import secret from '../fixtures/experimental.json' assert { type: 'json', unsupportedAssertion: 'should ignore' }; - -strictEqual(secret.ofLife, 42); diff --git a/test/es-module/test-esm-import-assertion-4.mjs b/test/es-module/test-esm-import-assertion-4.mjs deleted file mode 100644 index 547983e51f449a..00000000000000 --- a/test/es-module/test-esm-import-assertion-4.mjs +++ /dev/null @@ -1,11 +0,0 @@ -import '../common/index.mjs'; -import { strictEqual } from 'assert'; - -import secret0 from '../fixtures/experimental.json' assert { type: 'json' }; -const secret1 = await import('../fixtures/experimental.json', { - assert: { type: 'json' }, - }); - -strictEqual(secret0.ofLife, 42); -strictEqual(secret1.default.ofLife, 42); -strictEqual(secret1.default, secret0); diff --git a/test/es-module/test-esm-import-assertion-errors.js b/test/es-module/test-esm-import-assertion-errors.js deleted file mode 100644 index e2abd3fb43976d..00000000000000 --- a/test/es-module/test-esm-import-assertion-errors.js +++ /dev/null @@ -1,57 +0,0 @@ -'use strict'; -const common = require('../common'); -const { rejects } = require('assert'); - -const jsModuleDataUrl = 'data:text/javascript,export{}'; -const jsonModuleDataUrl = 'data:application/json,""'; - -common.expectWarning( - 'ExperimentalWarning', - 'Import assertions are not a stable feature of the JavaScript language. ' + - 'Avoid relying on their current behavior and syntax as those might change ' + - 'in a future version of Node.js.' -); - -async function test() { - await rejects( - import('data:text/css,', { assert: { type: 'css' } }), - { code: 'ERR_UNKNOWN_MODULE_FORMAT' } - ); - - await rejects( - import(`data:text/javascript,import${JSON.stringify(jsModuleDataUrl)}assert{type:"json"}`), - { code: 'ERR_IMPORT_ASSERTION_TYPE_FAILED' } - ); - - await rejects( - import(jsModuleDataUrl, { assert: { type: 'json' } }), - { code: 'ERR_IMPORT_ASSERTION_TYPE_FAILED' } - ); - - await rejects( - import(jsModuleDataUrl, { assert: { type: 'unsupported' } }), - { code: 'ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED' } - ); - - await rejects( - import(jsonModuleDataUrl), - { code: 'ERR_IMPORT_ASSERTION_TYPE_MISSING' } - ); - - await rejects( - import(jsonModuleDataUrl, { assert: {} }), - { code: 'ERR_IMPORT_ASSERTION_TYPE_MISSING' } - ); - - await rejects( - import(jsonModuleDataUrl, { assert: { foo: 'bar' } }), - { code: 'ERR_IMPORT_ASSERTION_TYPE_MISSING' } - ); - - await rejects( - import(jsonModuleDataUrl, { assert: { type: 'unsupported' }}), - { code: 'ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED' } - ); -} - -test().then(common.mustCall()); diff --git a/test/es-module/test-esm-import-assertion-errors.mjs b/test/es-module/test-esm-import-assertion-errors.mjs deleted file mode 100644 index 9cc08c06528fc6..00000000000000 --- a/test/es-module/test-esm-import-assertion-errors.mjs +++ /dev/null @@ -1,55 +0,0 @@ -import { expectWarning } from '../common/index.mjs'; -import { rejects } from 'assert'; - -const jsModuleDataUrl = 'data:text/javascript,export{}'; -const jsonModuleDataUrl = 'data:application/json,""'; - -expectWarning( - 'ExperimentalWarning', - 'Import assertions are not a stable feature of the JavaScript language. ' + - 'Avoid relying on their current behavior and syntax as those might change ' + - 'in a future version of Node.js.' -); - - -await rejects( - // This rejects because of the unsupported MIME type, not because of the - // unsupported assertion. - import('data:text/css,', { assert: { type: 'css' } }), - { code: 'ERR_UNKNOWN_MODULE_FORMAT' } -); - -await rejects( - import(`data:text/javascript,import${JSON.stringify(jsModuleDataUrl)}assert{type:"json"}`), - { code: 'ERR_IMPORT_ASSERTION_TYPE_FAILED' } -); - -await rejects( - import(jsModuleDataUrl, { assert: { type: 'json' } }), - { code: 'ERR_IMPORT_ASSERTION_TYPE_FAILED' } -); - -await rejects( - import(import.meta.url, { assert: { type: 'unsupported' } }), - { code: 'ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED' } -); - -await rejects( - import(jsonModuleDataUrl), - { code: 'ERR_IMPORT_ASSERTION_TYPE_MISSING' } -); - -await rejects( - import(jsonModuleDataUrl, { assert: {} }), - { code: 'ERR_IMPORT_ASSERTION_TYPE_MISSING' } -); - -await rejects( - import(jsonModuleDataUrl, { assert: { foo: 'bar' } }), - { code: 'ERR_IMPORT_ASSERTION_TYPE_MISSING' } -); - -await rejects( - import(jsonModuleDataUrl, { assert: { type: 'unsupported' }}), - { code: 'ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED' } -); diff --git a/test/es-module/test-esm-import-assertion-validation.js b/test/es-module/test-esm-import-assertion-validation.js deleted file mode 100644 index ec2d2a2c08f7b5..00000000000000 --- a/test/es-module/test-esm-import-assertion-validation.js +++ /dev/null @@ -1,45 +0,0 @@ -// Flags: --expose-internals -'use strict'; -const common = require('../common'); - -const assert = require('assert'); - -const { validateAssertions } = require('internal/modules/esm/assert'); - -common.expectWarning( - 'ExperimentalWarning', - 'Import assertions are not a stable feature of the JavaScript language. ' + - 'Avoid relying on their current behavior and syntax as those might change ' + - 'in a future version of Node.js.' -); - - -const url = 'test://'; - -assert.ok(validateAssertions(url, 'builtin', {})); -assert.ok(validateAssertions(url, 'commonjs', {})); -assert.ok(validateAssertions(url, 'json', { type: 'json' })); -assert.ok(validateAssertions(url, 'module', {})); -assert.ok(validateAssertions(url, 'wasm', {})); - -assert.throws(() => validateAssertions(url, 'json', {}), { - code: 'ERR_IMPORT_ASSERTION_TYPE_MISSING', -}); - -assert.throws(() => validateAssertions(url, 'module', { type: 'json' }), { - code: 'ERR_IMPORT_ASSERTION_TYPE_FAILED', -}); - -// The HTML spec specifically disallows this for now, while Wasm module import -// and whether it will require a type assertion is still an open question. -assert.throws(() => validateAssertions(url, 'module', { type: 'javascript' }), { - code: 'ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED', -}); - -assert.throws(() => validateAssertions(url, 'module', { type: 'css' }), { - code: 'ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED', -}); - -assert.throws(() => validateAssertions(url, 'module', { type: false }), { - code: 'ERR_INVALID_ARG_TYPE', -}); diff --git a/test/es-module/test-esm-import-assertion-warning.mjs b/test/es-module/test-esm-import-assertion-warning.mjs index 0b18d8ff9eaf62..a11b5164cebffc 100644 --- a/test/es-module/test-esm-import-assertion-warning.mjs +++ b/test/es-module/test-esm-import-assertion-warning.mjs @@ -1,10 +1,37 @@ -import { expectWarning } from '../common/index.mjs'; +import { spawnPromisified } from '../common/index.mjs'; +import assert from 'node:assert'; +import { execPath } from 'node:process'; -expectWarning( - 'ExperimentalWarning', - 'Import assertions are not a stable feature of the JavaScript language. ' + - 'Avoid relying on their current behavior and syntax as those might change ' + - 'in a future version of Node.js.' -); +await Promise.all([ + // Using importAssertions in the resolve hook should warn but still work. + `data:text/javascript,export ${encodeURIComponent(function resolve() { + return { shortCircuit: true, url: 'data:application/json,1', importAssertions: { type: 'json' } }; + })}`, + // Setting importAssertions on the context object of the load hook should warn but still work. + `data:text/javascript,export ${encodeURIComponent(function load(u, c, n) { + c.importAssertions = { type: 'json' }; + return n('data:application/json,1', c); + })}`, + // Creating a new context object with importAssertions in the load hook should warn but still work. + `data:text/javascript,export ${encodeURIComponent(function load(u, c, n) { + return n('data:application/json,1', { importAssertions: { type: 'json' } }); + })}`, +].map(async (loaderURL) => { + const { stdout, stderr, code } = await spawnPromisified(execPath, [ + '--input-type=module', + '--eval', ` + import assert from 'node:assert'; + import { register } from 'node:module'; + + register(${JSON.stringify(loaderURL)}); + + assert.deepStrictEqual( + { ...await import('data:') }, + { default: 1 } + );`, + ]); -await import('data:text/javascript,', { assert: { someUnsupportedKey: 'value' } }); + assert.match(stderr, /Use `importAttributes` instead of `importAssertions`/); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 0); +})); diff --git a/test/es-module/test-esm-import-assertion-1.mjs b/test/es-module/test-esm-import-attributes-1.mjs similarity index 100% rename from test/es-module/test-esm-import-assertion-1.mjs rename to test/es-module/test-esm-import-attributes-1.mjs diff --git a/test/es-module/test-esm-import-attributes-2.mjs b/test/es-module/test-esm-import-attributes-2.mjs new file mode 100644 index 00000000000000..1b4669ac276474 --- /dev/null +++ b/test/es-module/test-esm-import-attributes-2.mjs @@ -0,0 +1,11 @@ +import '../common/index.mjs'; +import { strictEqual } from 'assert'; + +import secret0 from '../fixtures/experimental.json' assert { type: 'json' }; +const secret1 = await import('../fixtures/experimental.json', { + assert: { type: 'json' }, +}); + +strictEqual(secret0.ofLife, 42); +strictEqual(secret1.default.ofLife, 42); +strictEqual(secret1.default, secret0); diff --git a/test/es-module/test-esm-import-assertion-3.mjs b/test/es-module/test-esm-import-attributes-3.mjs similarity index 100% rename from test/es-module/test-esm-import-assertion-3.mjs rename to test/es-module/test-esm-import-attributes-3.mjs diff --git a/test/es-module/test-esm-import-attributes-errors.js b/test/es-module/test-esm-import-attributes-errors.js new file mode 100644 index 00000000000000..f6e57f19b6b432 --- /dev/null +++ b/test/es-module/test-esm-import-attributes-errors.js @@ -0,0 +1,55 @@ +'use strict'; +const common = require('../common'); +const { rejects } = require('assert'); + +const jsModuleDataUrl = 'data:text/javascript,export{}'; +const jsonModuleDataUrl = 'data:application/json,""'; + +async function test() { + await rejects( + import('data:text/css,', { assert: { type: 'css' } }), + { code: 'ERR_UNKNOWN_MODULE_FORMAT' } + ); + + await rejects( + import('data:text/css,', { assert: { unsupportedAttribute: 'value' } }), + { code: 'ERR_IMPORT_ATTRIBUTE_UNSUPPORTED' } + ); + + await rejects( + import(`data:text/javascript,import${JSON.stringify(jsModuleDataUrl)}assert{type:"json"}`), + { code: 'ERR_IMPORT_ASSERTION_TYPE_FAILED' } + ); + + await rejects( + import(jsModuleDataUrl, { assert: { type: 'json' } }), + { code: 'ERR_IMPORT_ASSERTION_TYPE_FAILED' } + ); + + await rejects( + import(jsModuleDataUrl, { assert: { type: 'unsupported' } }), + { code: 'ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED' } + ); + + await rejects( + import(jsonModuleDataUrl), + { code: 'ERR_IMPORT_ASSERTION_TYPE_MISSING' } + ); + + await rejects( + import(jsonModuleDataUrl, { assert: {} }), + { code: 'ERR_IMPORT_ASSERTION_TYPE_MISSING' } + ); + + await rejects( + import(jsonModuleDataUrl, { assert: { foo: 'bar' } }), + { code: 'ERR_IMPORT_ASSERTION_TYPE_MISSING' } + ); + + await rejects( + import(jsonModuleDataUrl, { assert: { type: 'unsupported' } }), + { code: 'ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED' } + ); +} + +test().then(common.mustCall()); diff --git a/test/es-module/test-esm-import-attributes-errors.mjs b/test/es-module/test-esm-import-attributes-errors.mjs new file mode 100644 index 00000000000000..6621585be412e0 --- /dev/null +++ b/test/es-module/test-esm-import-attributes-errors.mjs @@ -0,0 +1,47 @@ +import '../common/index.mjs'; +import { rejects } from 'assert'; + +const jsModuleDataUrl = 'data:text/javascript,export{}'; +const jsonModuleDataUrl = 'data:application/json,""'; + +await rejects( + // This rejects because of the unsupported MIME type, not because of the + // unsupported assertion. + import('data:text/css,', { assert: { type: 'css' } }), + { code: 'ERR_UNKNOWN_MODULE_FORMAT' } +); + +await rejects( + import(`data:text/javascript,import${JSON.stringify(jsModuleDataUrl)}assert{type:"json"}`), + { code: 'ERR_IMPORT_ASSERTION_TYPE_FAILED' } +); + +await rejects( + import(jsModuleDataUrl, { assert: { type: 'json' } }), + { code: 'ERR_IMPORT_ASSERTION_TYPE_FAILED' } +); + +await rejects( + import(import.meta.url, { assert: { type: 'unsupported' } }), + { code: 'ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED' } +); + +await rejects( + import(jsonModuleDataUrl), + { code: 'ERR_IMPORT_ASSERTION_TYPE_MISSING' } +); + +await rejects( + import(jsonModuleDataUrl, { assert: {} }), + { code: 'ERR_IMPORT_ASSERTION_TYPE_MISSING' } +); + +await rejects( + import(jsonModuleDataUrl, { assert: { foo: 'bar' } }), + { code: 'ERR_IMPORT_ASSERTION_TYPE_MISSING' } +); + +await rejects( + import(jsonModuleDataUrl, { assert: { type: 'unsupported' } }), + { code: 'ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED' } +); diff --git a/test/es-module/test-esm-import-attributes-validation.js b/test/es-module/test-esm-import-attributes-validation.js new file mode 100644 index 00000000000000..f436f7073126d7 --- /dev/null +++ b/test/es-module/test-esm-import-attributes-validation.js @@ -0,0 +1,45 @@ +// Flags: --expose-internals +'use strict'; +require('../common'); + +const assert = require('assert'); + +const { validateAttributes } = require('internal/modules/esm/assert'); + +const url = 'test://'; + +assert.ok(validateAttributes(url, 'builtin', {})); +assert.ok(validateAttributes(url, 'commonjs', {})); +assert.ok(validateAttributes(url, 'json', { type: 'json' })); +assert.ok(validateAttributes(url, 'module', {})); +assert.ok(validateAttributes(url, 'wasm', {})); + +assert.throws(() => validateAttributes(url, 'json', {}), { + code: 'ERR_IMPORT_ASSERTION_TYPE_MISSING', +}); + +assert.throws(() => validateAttributes(url, 'json', { type: 'json', unsupportedAttribute: 'value' }), { + code: 'ERR_IMPORT_ATTRIBUTE_UNSUPPORTED', +}); + +assert.throws(() => validateAttributes(url, 'module', { unsupportedAttribute: 'value' }), { + code: 'ERR_IMPORT_ATTRIBUTE_UNSUPPORTED', +}); + +assert.throws(() => validateAttributes(url, 'module', { type: 'json' }), { + code: 'ERR_IMPORT_ASSERTION_TYPE_FAILED', +}); + +// The HTML spec specifically disallows this for now, while Wasm module import +// and whether it will require a type assertion is still an open question. +assert.throws(() => validateAttributes(url, 'module', { type: 'javascript' }), { + code: 'ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED', +}); + +assert.throws(() => validateAttributes(url, 'module', { type: 'css' }), { + code: 'ERR_IMPORT_ASSERTION_TYPE_UNSUPPORTED', +}); + +assert.throws(() => validateAttributes(url, 'module', { type: false }), { + code: 'ERR_INVALID_ARG_TYPE', +}); diff --git a/test/es-module/test-esm-import-meta-resolve.mjs b/test/es-module/test-esm-import-meta-resolve.mjs index 69ec84291d3cd6..7bd1a65fbb71df 100644 --- a/test/es-module/test-esm-import-meta-resolve.mjs +++ b/test/es-module/test-esm-import-meta-resolve.mjs @@ -1,38 +1,68 @@ // Flags: --experimental-import-meta-resolve -import { mustCall } from '../common/index.mjs'; +import '../common/index.mjs'; import assert from 'assert'; +import { spawn } from 'child_process'; +import { execPath } from 'process'; const dirname = import.meta.url.slice(0, import.meta.url.lastIndexOf('/') + 1); const fixtures = dirname.slice(0, dirname.lastIndexOf('/', dirname.length - 2) + 1) + 'fixtures/'; -(async () => { - assert.strictEqual(await import.meta.resolve('./test-esm-import-meta.mjs'), - dirname + 'test-esm-import-meta.mjs'); - try { - await import.meta.resolve('./notfound.mjs'); - assert.fail(); - } catch (e) { - assert.strictEqual(e.code, 'ERR_MODULE_NOT_FOUND'); - } - assert.strictEqual( - await import.meta.resolve('../fixtures/empty-with-bom.txt'), - fixtures + 'empty-with-bom.txt'); - assert.strictEqual(await import.meta.resolve('../fixtures/'), fixtures); - assert.strictEqual( - await import.meta.resolve('../fixtures/', import.meta.url), - fixtures); - assert.strictEqual( - await import.meta.resolve('../fixtures/', new URL(import.meta.url)), - fixtures); - await Promise.all( - [[], {}, Symbol(), 0, 1, 1n, 1.1, () => {}, true, false].map((arg) => - assert.rejects(import.meta.resolve('../fixtures/', arg), { - code: 'ERR_INVALID_ARG_TYPE', - }) - ) - ); - assert.strictEqual(await import.meta.resolve('http://some-absolute/url'), 'http://some-absolute/url'); - assert.strictEqual(await import.meta.resolve('some://weird/protocol'), 'some://weird/protocol'); - assert.strictEqual(await import.meta.resolve('baz/', fixtures), - fixtures + 'node_modules/baz/'); -})().then(mustCall()); +assert.strictEqual(import.meta.resolve('./test-esm-import-meta.mjs'), + dirname + 'test-esm-import-meta.mjs'); +assert.strictEqual(import.meta.resolve('./notfound.mjs'), new URL('./notfound.mjs', import.meta.url).href); +assert.strictEqual(import.meta.resolve('./asset'), new URL('./asset', import.meta.url).href); +try { + import.meta.resolve('does-not-exist'); + assert.fail(); +} catch (e) { + assert.strictEqual(e.code, 'ERR_MODULE_NOT_FOUND'); +} +assert.strictEqual( + import.meta.resolve('../fixtures/empty-with-bom.txt'), + fixtures + 'empty-with-bom.txt'); +assert.strictEqual(import.meta.resolve('../fixtures/'), fixtures); +assert.strictEqual( + import.meta.resolve('../fixtures/', import.meta.url), + fixtures); +assert.strictEqual( + import.meta.resolve('../fixtures/', new URL(import.meta.url)), + fixtures); +[[], {}, Symbol(), 0, 1, 1n, 1.1, () => {}, true, false].map((arg) => + assert.throws(() => import.meta.resolve('../fixtures/', arg), { + code: 'ERR_INVALID_ARG_TYPE', + }) +); +assert.strictEqual(import.meta.resolve('baz/', fixtures), + fixtures + 'node_modules/baz/'); + +{ + const cp = spawn(execPath, [ + '--input-type=module', + '--eval', 'console.log(typeof import.meta.resolve)', + ]); + assert.match((await cp.stdout.toArray()).toString(), /^function\r?\n$/); +} + +{ + const cp = spawn(execPath, [ + '--input-type=module', + ]); + cp.stdin.end('console.log(typeof import.meta.resolve)'); + assert.match((await cp.stdout.toArray()).toString(), /^function\r?\n$/); +} + +{ + const cp = spawn(execPath, [ + '--input-type=module', + '--eval', 'import "data:text/javascript,console.log(import.meta.resolve(%22node:os%22))"', + ]); + assert.match((await cp.stdout.toArray()).toString(), /^node:os\r?\n$/); +} + +{ + const cp = spawn(execPath, [ + '--input-type=module', + ]); + cp.stdin.end('import "data:text/javascript,console.log(import.meta.resolve(%22node:os%22))"'); + assert.match((await cp.stdout.toArray()).toString(), /^node:os\r?\n$/); +} diff --git a/test/es-module/test-esm-import-meta.mjs b/test/es-module/test-esm-import-meta.mjs index 0151177b21c302..4c5aa902d4a970 100644 --- a/test/es-module/test-esm-import-meta.mjs +++ b/test/es-module/test-esm-import-meta.mjs @@ -3,7 +3,7 @@ import assert from 'assert'; assert.strictEqual(Object.getPrototypeOf(import.meta), null); -const keys = ['url']; +const keys = ['resolve', 'url']; assert.deepStrictEqual(Reflect.ownKeys(import.meta), keys); const descriptors = Object.getOwnPropertyDescriptors(import.meta); diff --git a/test/es-module/test-esm-initialization.mjs b/test/es-module/test-esm-initialization.mjs index aa946a50152d40..f03a47d5d3791a 100644 --- a/test/es-module/test-esm-initialization.mjs +++ b/test/es-module/test-esm-initialization.mjs @@ -8,22 +8,23 @@ import { describe, it } from 'node:test'; describe('ESM: ensure initialization happens only once', { concurrency: true }, () => { it(async () => { const { code, stderr, stdout } = await spawnPromisified(execPath, [ + '--experimental-import-meta-resolve', '--loader', fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), '--no-warnings', fixtures.path('es-modules', 'runmain.mjs'), ]); - // Length minus 1 because the first match is the needle. - const resolveHookRunCount = (stdout.match(/resolve passthru/g)?.length ?? 0) - 1; - assert.strictEqual(stderr, ''); /** * resolveHookRunCount = 2: * 1. fixtures/…/runmain.mjs * 2. node:module (imported by fixtures/…/runmain.mjs) + * 3. doesnt-matter.mjs (first import.meta.resolve call) + * 4. fixtures/…/runmain.mjs (entry point) + * 5. doesnt-matter.mjs (second import.meta.resolve call) */ - assert.strictEqual(resolveHookRunCount, 2); + assert.strictEqual(stdout.match(/resolve passthru/g)?.length, 5); assert.strictEqual(code, 0); }); }); diff --git a/test/es-module/test-esm-invalid-data-urls.js b/test/es-module/test-esm-invalid-data-urls.js index e434c895a2e37d..6eafe75e7d7ed7 100644 --- a/test/es-module/test-esm-invalid-data-urls.js +++ b/test/es-module/test-esm-invalid-data-urls.js @@ -18,4 +18,7 @@ const assert = require('assert'); code: 'ERR_UNKNOWN_MODULE_FORMAT', message: 'Unknown module format: text/css for URL data:text/css,.error { color: red; }', }); + await assert.rejects(import('data:WRONGtext/javascriptFORMAT,console.log("hello!");'), { + code: 'ERR_UNKNOWN_MODULE_FORMAT', + }); })().then(common.mustCall()); diff --git a/test/es-module/test-esm-json.mjs b/test/es-module/test-esm-json.mjs index 2740c0097f77da..e5a0ab9f74e2cf 100644 --- a/test/es-module/test-esm-json.mjs +++ b/test/es-module/test-esm-json.mjs @@ -2,7 +2,10 @@ import { spawnPromisified } from '../common/index.mjs'; import * as fixtures from '../common/fixtures.mjs'; import assert from 'node:assert'; import { execPath } from 'node:process'; -import { describe, it } from 'node:test'; +import { describe, it, test } from 'node:test'; + +import { mkdir, rm, writeFile } from 'node:fs/promises'; +import * as tmpdir from '../common/tmpdir.js'; import secret from '../fixtures/experimental.json' assert { type: 'json' }; @@ -17,8 +20,64 @@ describe('ESM: importing JSON', () => { ]); assert.match(stderr, /ExperimentalWarning: Importing JSON modules/); - assert.match(stderr, /ExperimentalWarning: Import assertions/); assert.strictEqual(code, 0); assert.strictEqual(signal, null); }); + + test('should load different modules when the URL is different', async (t) => { + const root = tmpdir.fileURL(`./test-esm-json-${Math.random()}/`); + try { + await mkdir(root, { recursive: true }); + + await t.test('json', async () => { + let i = 0; + const url = new URL('./foo.json', root); + await writeFile(url, JSON.stringify({ id: i++ })); + const absoluteURL = await import(`${url}`, { + assert: { type: 'json' }, + }); + await writeFile(url, JSON.stringify({ id: i++ })); + const queryString = await import(`${url}?a=2`, { + assert: { type: 'json' }, + }); + await writeFile(url, JSON.stringify({ id: i++ })); + const hash = await import(`${url}#a=2`, { + assert: { type: 'json' }, + }); + await writeFile(url, JSON.stringify({ id: i++ })); + const queryStringAndHash = await import(`${url}?a=2#a=2`, { + assert: { type: 'json' }, + }); + + assert.notDeepStrictEqual(absoluteURL, queryString); + assert.notDeepStrictEqual(absoluteURL, hash); + assert.notDeepStrictEqual(queryString, hash); + assert.notDeepStrictEqual(absoluteURL, queryStringAndHash); + assert.notDeepStrictEqual(queryString, queryStringAndHash); + assert.notDeepStrictEqual(hash, queryStringAndHash); + }); + + await t.test('js', async () => { + let i = 0; + const url = new URL('./foo.mjs', root); + await writeFile(url, `export default ${JSON.stringify({ id: i++ })}\n`); + const absoluteURL = await import(`${url}`); + await writeFile(url, `export default ${JSON.stringify({ id: i++ })}\n`); + const queryString = await import(`${url}?a=1`); + await writeFile(url, `export default ${JSON.stringify({ id: i++ })}\n`); + const hash = await import(`${url}#a=1`); + await writeFile(url, `export default ${JSON.stringify({ id: i++ })}\n`); + const queryStringAndHash = await import(`${url}?a=1#a=1`); + + assert.notDeepStrictEqual(absoluteURL, queryString); + assert.notDeepStrictEqual(absoluteURL, hash); + assert.notDeepStrictEqual(queryString, hash); + assert.notDeepStrictEqual(absoluteURL, queryStringAndHash); + assert.notDeepStrictEqual(queryString, queryStringAndHash); + assert.notDeepStrictEqual(hash, queryStringAndHash); + }); + } finally { + await rm(root, { force: true, recursive: true }); + } + }); }); diff --git a/test/es-module/test-esm-loader-chaining.mjs b/test/es-module/test-esm-loader-chaining.mjs index c8244bc5012377..b43ac740500cd8 100644 --- a/test/es-module/test-esm-loader-chaining.mjs +++ b/test/es-module/test-esm-loader-chaining.mjs @@ -4,7 +4,6 @@ import assert from 'node:assert'; import { execPath } from 'node:process'; import { describe, it } from 'node:test'; - const setupArgs = [ '--no-warnings', '--input-type=module', @@ -253,6 +252,23 @@ describe('ESM: loader chaining', { concurrency: true }, () => { assert.strictEqual(code, 0); }); + it('should allow loaders to influence subsequent loader resolutions', async () => { + const { code, stderr } = await spawnPromisified( + execPath, + [ + '--loader', + fixtures.fileURL('es-module-loaders', 'loader-resolve-strip-xxx.mjs'), + '--loader', + 'xxx/loader-resolve-strip-yyy.mjs', + ...commonArgs, + ], + { encoding: 'utf8', cwd: fixtures.path('es-module-loaders') }, + ); + + assert.strictEqual(stderr, ''); + assert.strictEqual(code, 0); + }); + it('should throw when the resolve chain is broken', async () => { const { code, stderr, stdout } = await spawnPromisified( execPath, @@ -454,4 +470,38 @@ describe('ESM: loader chaining', { concurrency: true }, () => { assert.match(stderr, /'load' hook's nextLoad\(\) context/); assert.strictEqual(code, 1); }); + + it('should allow loaders to influence subsequent loader `import()` calls in `resolve`', async () => { + const { code, stderr, stdout } = await spawnPromisified( + execPath, + [ + '--loader', + fixtures.fileURL('es-module-loaders', 'loader-resolve-strip-xxx.mjs'), + '--loader', + fixtures.fileURL('es-module-loaders', 'loader-resolve-dynamic-import.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, + ); + assert.strictEqual(stderr, ''); + assert.match(stdout, /resolve dynamic import/); // It did go thru resolve-dynamic + assert.strictEqual(code, 0); + }); + + it('should allow loaders to influence subsequent loader `import()` calls in `load`', async () => { + const { code, stderr, stdout } = await spawnPromisified( + execPath, + [ + '--loader', + fixtures.fileURL('es-module-loaders', 'loader-resolve-strip-xxx.mjs'), + '--loader', + fixtures.fileURL('es-module-loaders', 'loader-load-dynamic-import.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, + ); + assert.strictEqual(stderr, ''); + assert.match(stdout, /load dynamic import/); // It did go thru load-dynamic + assert.strictEqual(code, 0); + }); }); diff --git a/test/es-module/test-esm-loader-default-resolver.mjs b/test/es-module/test-esm-loader-default-resolver.mjs index 27320fcfcfe862..2a69010e05047f 100644 --- a/test/es-module/test-esm-loader-default-resolver.mjs +++ b/test/es-module/test-esm-loader-default-resolver.mjs @@ -49,4 +49,18 @@ describe('default resolver', () => { assert.strictEqual(stdout.trim(), 'index.byoe!'); assert.strictEqual(stderr, ''); }); + + it('should identify the parent module of an invalid URL host in import specifier', async () => { + if (process.platform === 'win32') return; + + const { code, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + fixtures.path('es-modules', 'invalid-posix-host.mjs'), + ]); + + assert.match(stderr, /ERR_INVALID_FILE_URL_HOST/); + assert.match(stderr, /file:\/\/hmm\.js/); + assert.match(stderr, /invalid-posix-host\.mjs/); + assert.strictEqual(code, 1); + }); }); diff --git a/test/es-module/test-esm-loader-globalpreload-hook.mjs b/test/es-module/test-esm-loader-globalpreload-hook.mjs new file mode 100644 index 00000000000000..87def31fb3d0ea --- /dev/null +++ b/test/es-module/test-esm-loader-globalpreload-hook.mjs @@ -0,0 +1,149 @@ +import { spawnPromisified } from '../common/index.mjs'; +import * as fixtures from '../common/fixtures.mjs'; +import assert from 'node:assert'; +import os from 'node:os'; +import { execPath } from 'node:process'; +import { describe, it } from 'node:test'; + +describe('globalPreload hook', () => { + it('should not emit deprecation warning when initialize is supplied', async () => { + const { stderr } = await spawnPromisified(execPath, [ + '--experimental-loader', + 'data:text/javascript,export function globalPreload(){}export function initialize(){}', + fixtures.path('empty.js'), + ]); + + assert.doesNotMatch(stderr, /`globalPreload` is an experimental feature/); + }); + + it('should handle globalPreload returning undefined', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,export function globalPreload(){}', + fixtures.path('empty.js'), + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); + + it('should handle loading node:test', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,export function globalPreload(){return `getBuiltin("node:test")()`}', + fixtures.path('empty.js'), + ]); + + assert.strictEqual(stderr, ''); + assert.match(stdout, /\n# pass 1\r?\n/); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); + + it('should handle loading node:os with node: prefix', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,export function globalPreload(){return `console.log(getBuiltin("node:os").arch())`}', + fixtures.path('empty.js'), + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(stdout.trim(), os.arch()); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); + + // `os` is used here because it's simple and not mocked (the builtin module otherwise doesn't matter). + it('should handle loading builtin module without node: prefix', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,export function globalPreload(){return `console.log(getBuiltin("os").arch())`}', + fixtures.path('empty.js'), + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(stdout.trim(), os.arch()); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); + + it('should throw when loading node:test without node: prefix', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,export function globalPreload(){return `getBuiltin("test")()`}', + fixtures.path('empty.js'), + ]); + + assert.match(stderr, /ERR_UNKNOWN_BUILTIN_MODULE/); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + }); + + it('should register globals set from globalPreload', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,export function globalPreload(){return "this.myGlobal=4"}', + '--print', 'myGlobal', + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(stdout.trim(), '4'); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); + + it('should log console.log calls returned from globalPreload', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,export function globalPreload(){return `console.log("Hello from globalPreload")`}', + fixtures.path('empty.js'), + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(stdout.trim(), 'Hello from globalPreload'); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); + + it('should crash if globalPreload returns code that throws', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,export function globalPreload(){return `throw new Error("error from globalPreload")`}', + fixtures.path('empty.js'), + ]); + + assert.match(stderr, /error from globalPreload/); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + }); + + it('should have a `this` value that is not bound to the loader instance', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + `data:text/javascript,export ${function globalPreload() { + if (this != null) { + throw new Error('hook function must not be bound to ESMLoader instance'); + } + }}`, + fixtures.path('empty.js'), + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); +}); diff --git a/test/es-module/test-esm-loader-hooks.mjs b/test/es-module/test-esm-loader-hooks.mjs index 63cffdf40daf56..3dac3677bb804b 100644 --- a/test/es-module/test-esm-loader-hooks.mjs +++ b/test/es-module/test-esm-loader-hooks.mjs @@ -9,8 +9,8 @@ describe('Loader hooks', { concurrency: true }, () => { const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ '--no-warnings', '--experimental-loader', - fixtures.fileURL('/es-module-loaders/hooks-input.mjs'), - fixtures.path('/es-modules/json-modules.mjs'), + fixtures.fileURL('es-module-loaders/hooks-input.mjs'), + fixtures.path('es-modules/json-modules.mjs'), ]); assert.strictEqual(stderr, ''); @@ -22,6 +22,32 @@ describe('Loader hooks', { concurrency: true }, () => { assert.match(lines[1], /{"source":{"type":"Buffer","data":\[.*\]},"format":"module","shortCircuit":true}/); assert.match(lines[2], /{"url":"file:\/\/\/.*\/experimental\.json","format":"test","shortCircuit":true}/); assert.match(lines[3], /{"source":{"type":"Buffer","data":\[.*\]},"format":"json","shortCircuit":true}/); + assert.strictEqual(lines[4], ''); + assert.strictEqual(lines.length, 5); + }); + + it('are called with all expected arguments using register function', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader=data:text/javascript,', + '--input-type=module', + '--eval', + "import { register } from 'node:module';" + + `register(${JSON.stringify(fixtures.fileURL('es-module-loaders/hooks-input.mjs'))});` + + `await import(${JSON.stringify(fixtures.fileURL('es-modules/json-modules.mjs'))});`, + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + + const lines = stdout.split('\n'); + assert.match(lines[0], /{"url":"file:\/\/\/.*\/json-modules\.mjs","format":"test","shortCircuit":true}/); + assert.match(lines[1], /{"source":{"type":"Buffer","data":\[.*\]},"format":"module","shortCircuit":true}/); + assert.match(lines[2], /{"url":"file:\/\/\/.*\/experimental\.json","format":"test","shortCircuit":true}/); + assert.match(lines[3], /{"source":{"type":"Buffer","data":\[.*\]},"format":"json","shortCircuit":true}/); + assert.strictEqual(lines[4], ''); + assert.strictEqual(lines.length, 5); }); describe('should handle never-settling hooks in ESM files', { concurrency: true }, () => { @@ -71,7 +97,6 @@ describe('Loader hooks', { concurrency: true }, () => { it('import.meta.resolve of a never-settling resolve', async () => { const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-import-meta-resolve', '--experimental-loader', fixtures.fileURL('es-module-loaders/never-settling-resolve-step/loader.mjs'), fixtures.path('es-module-loaders/never-settling-resolve-step/import.meta.never-resolve.mjs'), @@ -132,7 +157,6 @@ describe('Loader hooks', { concurrency: true }, () => { it('should not leak internals or expose import.meta.resolve', async () => { const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ '--no-warnings', - '--experimental-import-meta-resolve', '--experimental-loader', fixtures.fileURL('es-module-loaders/loader-edge-cases.mjs'), fixtures.path('empty.js'), @@ -143,4 +167,479 @@ describe('Loader hooks', { concurrency: true }, () => { assert.strictEqual(code, 0); assert.strictEqual(signal, null); }); + + it('should be fine to call `process.exit` from a custom async hook', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,export function load(a,b,next){if(a==="data:exit")process.exit(42);return next(a,b)}', + '--input-type=module', + '--eval', + 'import "data:exit"', + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 42); + assert.strictEqual(signal, null); + }); + + it('should be fine to call `process.exit` from a custom sync hook', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,export function resolve(a,b,next){if(a==="exit:")process.exit(42);return next(a,b)}', + '--input-type=module', + '--eval', + 'import "data:text/javascript,import.meta.resolve(%22exit:%22)"', + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 42); + assert.strictEqual(signal, null); + }); + + it('should be fine to call `process.exit` from the loader thread top-level', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,process.exit(42)', + fixtures.path('empty.js'), + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 42); + assert.strictEqual(signal, null); + }); + + describe('should handle a throwing top-level body', () => { + it('should handle regular Error object', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,throw new Error("error message")', + fixtures.path('empty.js'), + ]); + + assert.match(stderr, /Error: error message\r?\n/); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + }); + + it('should handle null', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,throw null', + fixtures.path('empty.js'), + ]); + + assert.match(stderr, /\nnull\r?\n/); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + }); + + it('should handle undefined', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,throw undefined', + fixtures.path('empty.js'), + ]); + + assert.match(stderr, /\nundefined\r?\n/); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + }); + + it('should handle boolean', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,throw true', + fixtures.path('empty.js'), + ]); + + assert.match(stderr, /\ntrue\r?\n/); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + }); + + it('should handle empty plain object', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,throw {}', + fixtures.path('empty.js'), + ]); + + assert.match(stderr, /\n\{\}\r?\n/); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + }); + + it('should handle plain object', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,throw {fn(){},symbol:Symbol("symbol"),u:undefined}', + fixtures.path('empty.js'), + ]); + + assert.match(stderr, /\n\{ fn: \[Function: fn\], symbol: Symbol\(symbol\), u: undefined \}\r?\n/); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + }); + + it('should handle number', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,throw 1', + fixtures.path('empty.js'), + ]); + + assert.match(stderr, /\n1\r?\n/); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + }); + + it('should handle bigint', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,throw 1n', + fixtures.path('empty.js'), + ]); + + assert.match(stderr, /\n1\r?\n/); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + }); + + it('should handle string', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,throw "literal string"', + fixtures.path('empty.js'), + ]); + + assert.match(stderr, /\nliteral string\r?\n/); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + }); + + it('should handle symbol', async () => { + const { code, signal, stdout } = await spawnPromisified(execPath, [ + '--experimental-loader', + 'data:text/javascript,throw Symbol("symbol descriptor")', + fixtures.path('empty.js'), + ]); + + // Throwing a symbol doesn't produce any output + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + }); + + it('should handle function', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,throw function fnName(){}', + fixtures.path('empty.js'), + ]); + + assert.match(stderr, /\n\[Function: fnName\]\r?\n/); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + }); + }); + + describe('globalPreload', () => { + it('should emit warning', async () => { + const { stderr } = await spawnPromisified(execPath, [ + '--experimental-loader', + 'data:text/javascript,export function globalPreload(){}', + '--experimental-loader', + 'data:text/javascript,export function globalPreload(){return""}', + fixtures.path('empty.js'), + ]); + + assert.strictEqual(stderr.match(/`globalPreload` is an experimental feature/g).length, 1); + }); + }); + + it('should be fine to call `process.removeAllListeners("beforeExit")` from the main thread', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + 'data:text/javascript,export function load(a,b,c){return new Promise(d=>setTimeout(()=>d(c(a,b)),99))}', + '--input-type=module', + '--eval', + 'setInterval(() => process.removeAllListeners("beforeExit"),1).unref();await import("data:text/javascript,")', + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); + + describe('`initialize`/`register`', () => { + it('should invoke `initialize` correctly', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + fixtures.fileURL('es-module-loaders/hooks-initialize.mjs'), + '--input-type=module', + '--eval', + 'import os from "node:os";', + ]); + + assert.strictEqual(stderr, ''); + assert.deepStrictEqual(stdout.split('\n'), ['hooks initialize 1', '']); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); + + it('should allow communicating with loader via `register` ports', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--input-type=module', + '--eval', + ` + import {MessageChannel} from 'node:worker_threads'; + import {register} from 'node:module'; + import {once} from 'node:events'; + const {port1, port2} = new MessageChannel(); + port1.on('message', (msg) => { + console.log('message', msg); + }); + const result = register( + ${JSON.stringify(fixtures.fileURL('es-module-loaders/hooks-initialize-port.mjs'))}, + {data: port2, transferList: [port2]}, + ); + console.log('register', result); + + const timeout = setTimeout(() => {}, 2**31 - 1); // to keep the process alive. + await Promise.all([ + once(port1, 'message').then(() => once(port1, 'message')), + import('node:os'), + ]); + clearTimeout(timeout); + port1.close(); + `, + ]); + + assert.strictEqual(stderr, ''); + assert.deepStrictEqual(stdout.split('\n'), [ 'register undefined', + 'message initialize', + 'message resolve node:os', + '' ]); + + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); + + it('should have `register` accept URL objects as `parentURL`', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--import', + `data:text/javascript,${encodeURIComponent( + 'import{ register } from "node:module";' + + 'import { pathToFileURL } from "node:url";' + + 'register("./hooks-initialize.mjs", pathToFileURL("./"));' + )}`, + '--input-type=module', + '--eval', + ` + import {register} from 'node:module'; + register( + ${JSON.stringify(fixtures.fileURL('es-module-loaders/loader-load-foo-or-42.mjs'))}, + new URL('data:'), + ); + + import('node:os').then((result) => { + console.log(JSON.stringify(result)); + }); + `, + ], { cwd: fixtures.fileURL('es-module-loaders/') }); + + assert.strictEqual(stderr, ''); + assert.deepStrictEqual(stdout.split('\n').sort(), ['hooks initialize 1', '{"default":"foo"}', ''].sort()); + + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); + + it('should have `register` work with cjs', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--input-type=commonjs', + '--eval', + ` + 'use strict'; + const {register} = require('node:module'); + register( + ${JSON.stringify(fixtures.fileURL('es-module-loaders/hooks-initialize.mjs'))}, + ); + register( + ${JSON.stringify(fixtures.fileURL('es-module-loaders/loader-load-foo-or-42.mjs'))}, + ); + + import('node:os').then((result) => { + console.log(JSON.stringify(result)); + }); + `, + ]); + + assert.strictEqual(stderr, ''); + assert.deepStrictEqual(stdout.split('\n').sort(), ['hooks initialize 1', '{"default":"foo"}', ''].sort()); + + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); + + it('`register` should work with `require`', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--require', + fixtures.path('es-module-loaders/register-loader.cjs'), + '--input-type=module', + '--eval', + 'import "node:os";', + ]); + + assert.strictEqual(stderr, ''); + assert.deepStrictEqual(stdout.split('\n'), ['resolve passthru', 'resolve passthru', '']); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); + + it('`register` should work with `import`', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--import', + fixtures.fileURL('es-module-loaders/register-loader.mjs'), + '--input-type=module', + '--eval', + 'import "node:os"', + ]); + + assert.strictEqual(stderr, ''); + assert.deepStrictEqual(stdout.split('\n'), ['resolve passthru', '']); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); + + it('should execute `initialize` in sequence', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--input-type=module', + '--eval', + ` + import {register} from 'node:module'; + console.log('result 1', register( + ${JSON.stringify(fixtures.fileURL('es-module-loaders/hooks-initialize.mjs'))} + )); + console.log('result 2', register( + ${JSON.stringify(fixtures.fileURL('es-module-loaders/hooks-initialize.mjs'))} + )); + + await import('node:os'); + `, + ]); + + assert.strictEqual(stderr, ''); + assert.deepStrictEqual(stdout.split('\n'), [ 'hooks initialize 1', + 'result 1 undefined', + 'hooks initialize 2', + 'result 2 undefined', + '' ]); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); + + it('should handle `initialize` returning never-settling promise', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--input-type=module', + '--eval', + ` + import {register} from 'node:module'; + register('data:text/javascript,export function initialize(){return new Promise(()=>{})}'); + `, + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 13); + assert.strictEqual(signal, null); + }); + + it('should handle `initialize` returning rejecting promise', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--input-type=module', + '--eval', + ` + import {register} from 'node:module'; + register('data:text/javascript,export function initialize(){return Promise.reject()}'); + `, + ]); + + assert.match(stderr, /undefined\r?\n/); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + }); + + it('should handle `initialize` throwing null', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--input-type=module', + '--eval', + ` + import {register} from 'node:module'; + register('data:text/javascript,export function initialize(){throw null}'); + `, + ]); + + assert.match(stderr, /null\r?\n/); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + }); + + it('should be fine to call `process.exit` from a initialize hook', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--input-type=module', + '--eval', + ` + import {register} from 'node:module'; + register('data:text/javascript,export function initialize(){process.exit(42);}'); + `, + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 42); + assert.strictEqual(signal, null); + }); + }); }); diff --git a/test/es-module/test-esm-loader-mock.mjs b/test/es-module/test-esm-loader-mock.mjs new file mode 100644 index 00000000000000..164d0ac3775039 --- /dev/null +++ b/test/es-module/test-esm-loader-mock.mjs @@ -0,0 +1,42 @@ +import '../common/index.mjs'; +import assert from 'node:assert/strict'; +import { mock } from '../fixtures/es-module-loaders/mock.mjs'; + +mock('node:events', { + EventEmitter: 'This is mocked!' +}); + +// This resolves to node:events +// It is intercepted by mock-loader and doesn't return the normal value +assert.deepStrictEqual(await import('events'), Object.defineProperty({ + __proto__: null, + EventEmitter: 'This is mocked!' +}, Symbol.toStringTag, { + enumerable: false, + value: 'Module' +})); + +const mutator = mock('node:events', { + EventEmitter: 'This is mocked v2!' +}); + +// It is intercepted by mock-loader and doesn't return the normal value. +// This is resolved separately from the import above since the specifiers +// are different. +const mockedV2 = await import('node:events'); +assert.deepStrictEqual(mockedV2, Object.defineProperty({ + __proto__: null, + EventEmitter: 'This is mocked v2!' +}, Symbol.toStringTag, { + enumerable: false, + value: 'Module' +})); + +mutator.EventEmitter = 'This is mocked v3!'; +assert.deepStrictEqual(mockedV2, Object.defineProperty({ + __proto__: null, + EventEmitter: 'This is mocked v3!' +}, Symbol.toStringTag, { + enumerable: false, + value: 'Module' +})); diff --git a/test/es-module/test-esm-loader-modulemap.js b/test/es-module/test-esm-loader-modulemap.js index 190676ec725cd2..860775df0a2ce8 100644 --- a/test/es-module/test-esm-loader-modulemap.js +++ b/test/es-module/test-esm-loader-modulemap.js @@ -4,8 +4,8 @@ require('../common'); const { strictEqual, throws } = require('assert'); -const { ESMLoader } = require('internal/modules/esm/loader'); -const ModuleMap = require('internal/modules/esm/module_map'); +const { createModuleLoader } = require('internal/modules/esm/loader'); +const { LoadCache, ResolveCache } = require('internal/modules/esm/module_map'); const ModuleJob = require('internal/modules/esm/module_job'); const createDynamicModule = require( 'internal/modules/esm/create_dynamic_module'); @@ -16,7 +16,7 @@ const jsonModuleDataUrl = 'data:application/json,""'; const stubJsModule = createDynamicModule([], ['default'], jsModuleDataUrl); const stubJsonModule = createDynamicModule([], ['default'], jsonModuleDataUrl); -const loader = new ESMLoader(); +const loader = createModuleLoader(false); const jsModuleJob = new ModuleJob(loader, stubJsModule.module, undefined, () => new Promise(() => {})); const jsonModuleJob = new ModuleJob(loader, stubJsonModule.module, @@ -24,11 +24,11 @@ const jsonModuleJob = new ModuleJob(loader, stubJsonModule.module, () => new Promise(() => {})); -// ModuleMap.set and ModuleMap.get store and retrieve module jobs for a -// specified url/type tuple; ModuleMap.has correctly reports whether such jobs +// LoadCache.set and LoadCache.get store and retrieve module jobs for a +// specified url/type tuple; LoadCache.has correctly reports whether such jobs // are stored in the map. { - const moduleMap = new ModuleMap(); + const moduleMap = new LoadCache(); moduleMap.set(jsModuleDataUrl, undefined, jsModuleJob); moduleMap.set(jsonModuleDataUrl, 'json', jsonModuleJob); @@ -50,10 +50,10 @@ const jsonModuleJob = new ModuleJob(loader, stubJsonModule.module, strictEqual(moduleMap.has(jsonModuleDataUrl, 'unknown'), false); } -// ModuleMap.get, ModuleMap.has and ModuleMap.set should only accept string +// LoadCache.get, LoadCache.has and LoadCache.set should only accept string // values as url argument. { - const moduleMap = new ModuleMap(); + const moduleMap = new LoadCache(); const errorObj = { code: 'ERR_INVALID_ARG_TYPE', @@ -68,10 +68,10 @@ const jsonModuleJob = new ModuleJob(loader, stubJsonModule.module, }); } -// ModuleMap.get, ModuleMap.has and ModuleMap.set should only accept string +// LoadCache.get, LoadCache.has and LoadCache.set should only accept string // values (or the kAssertType symbol) as type argument. { - const moduleMap = new ModuleMap(); + const moduleMap = new LoadCache(); const errorObj = { code: 'ERR_INVALID_ARG_TYPE', @@ -86,9 +86,9 @@ const jsonModuleJob = new ModuleJob(loader, stubJsonModule.module, }); } -// ModuleMap.set should only accept ModuleJob values as job argument. +// LoadCache.set should only accept ModuleJob values as job argument. { - const moduleMap = new ModuleMap(); + const moduleMap = new LoadCache(); [{}, [], true, 1].forEach((value) => { throws(() => moduleMap.set('', undefined, value), { @@ -98,3 +98,21 @@ const jsonModuleJob = new ModuleJob(loader, stubJsonModule.module, }); }); } + +{ + const resolveMap = new ResolveCache(); + + strictEqual(resolveMap.serializeKey('./file', { __proto__: null }), './file::'); + strictEqual(resolveMap.serializeKey('./file', { __proto__: null, type: 'json' }), './file::"type""json"'); + strictEqual(resolveMap.serializeKey('./file::"type""json"', { __proto__: null }), './file::"type""json"::'); + strictEqual(resolveMap.serializeKey('./file', { __proto__: null, c: 'd', a: 'b' }), './file::"a""b","c""d"'); + strictEqual(resolveMap.serializeKey('./s', { __proto__: null, c: 'd', a: 'b', b: 'c' }), './s::"a""b","b""c","c""d"'); + + resolveMap.set('key1', 'parent1', 1); + resolveMap.set('key2', 'parent1', 2); + resolveMap.set('key2', 'parent2', 3); + + strictEqual(resolveMap.get('key1', 'parent1'), 1); + strictEqual(resolveMap.get('key2', 'parent1'), 2); + strictEqual(resolveMap.get('key2', 'parent2'), 3); +} diff --git a/test/es-module/test-esm-loader-obsolete-hooks.mjs b/test/es-module/test-esm-loader-obsolete-hooks.mjs deleted file mode 100644 index fa0baef8a216b7..00000000000000 --- a/test/es-module/test-esm-loader-obsolete-hooks.mjs +++ /dev/null @@ -1,28 +0,0 @@ -import { spawnPromisified } from '../common/index.mjs'; -import { fileURL, path } from '../common/fixtures.mjs'; -import { match, notStrictEqual } from 'node:assert'; -import { execPath } from 'node:process'; -import { describe, it } from 'node:test'; - - -describe('ESM: deprecation warnings for obsolete hooks', { concurrency: true }, () => { - it(async () => { - const { code, stderr } = await spawnPromisified(execPath, [ - '--no-warnings', - '--throw-deprecation', - '--experimental-loader', - fileURL('es-module-loaders', 'hooks-obsolete.mjs').href, - path('print-error-message.js'), - ]); - - // DeprecationWarning: Obsolete loader hook(s) supplied and will be ignored: - // dynamicInstantiate, getFormat, getSource, transformSource - match(stderr, /DeprecationWarning:/); - match(stderr, /dynamicInstantiate/); - match(stderr, /getFormat/); - match(stderr, /getSource/); - match(stderr, /transformSource/); - - notStrictEqual(code, 0); - }); -}); diff --git a/test/es-module/test-esm-loader-programmatically.mjs b/test/es-module/test-esm-loader-programmatically.mjs new file mode 100644 index 00000000000000..8d70b110ebbfda --- /dev/null +++ b/test/es-module/test-esm-loader-programmatically.mjs @@ -0,0 +1,251 @@ +import { spawnPromisified } from '../common/index.mjs'; +import * as fixtures from '../common/fixtures.js'; +import assert from 'node:assert'; +import { execPath } from 'node:process'; +import { describe, it } from 'node:test'; + +// This test ensures that the register function can register loaders +// programmatically. + +const commonArgs = [ + '--no-warnings', + '--input-type=module', + '--loader=data:text/javascript,', +]; + +const commonEvals = { + import: (module) => `await import(${JSON.stringify(module)});`, + register: (loader, parentURL = 'file:///') => `register(${JSON.stringify(loader)}, ${JSON.stringify(parentURL)});`, + dynamicImport: (module) => `await import(${JSON.stringify(`data:text/javascript,${encodeURIComponent(module)}`)});`, + staticImport: (module) => `import ${JSON.stringify(`data:text/javascript,${encodeURIComponent(module)}`)};`, +}; + +describe('ESM: programmatically register loaders', { concurrency: true }, () => { + it('works with only a dummy CLI argument', async () => { + const parentURL = fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'); + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + ...commonArgs, + '--eval', + "import { register } from 'node:module';" + + commonEvals.register(fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs')) + + commonEvals.register(fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs')) + + `register(${JSON.stringify('./loader-resolve-passthru.mjs')}, ${JSON.stringify({ parentURL })});` + + `register(${JSON.stringify('./loader-load-passthru.mjs')}, ${JSON.stringify({ parentURL })});` + + commonEvals.dynamicImport('console.log("Hello from dynamic import");'), + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + + const lines = stdout.split('\n'); + + assert.match(lines[0], /resolve passthru/); + assert.match(lines[1], /resolve passthru/); + assert.match(lines[2], /load passthru/); + assert.match(lines[3], /load passthru/); + assert.match(lines[4], /Hello from dynamic import/); + + assert.strictEqual(lines[5], ''); + }); + + describe('registering via --import', { concurrency: true }, () => { + for (const moduleType of ['mjs', 'cjs']) { + it(`should programmatically register a loader from a ${moduleType.toUpperCase()} file`, async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + ...commonArgs, + '--import', fixtures.fileURL('es-module-loaders', `register-loader.${moduleType}`).href, + '--eval', commonEvals.staticImport('console.log("entry point")'), + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + + const [ + passthruStdout, + entryPointStdout, + ] = stdout.split('\n'); + + assert.match(passthruStdout, /resolve passthru/); + assert.match(entryPointStdout, /entry point/); + }); + } + }); + + it('programmatically registered loaders are appended to an existing chaining', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + ...commonArgs, + '--loader', + fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + '--eval', + "import { register } from 'node:module';" + + commonEvals.register(fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs')) + + commonEvals.dynamicImport('console.log("Hello from dynamic import");'), + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + + const lines = stdout.split('\n'); + + assert.match(lines[0], /resolve passthru/); + assert.match(lines[1], /resolve passthru/); + assert.match(lines[2], /load passthru/); + assert.match(lines[3], /Hello from dynamic import/); + + assert.strictEqual(lines[4], ''); + }); + + it('works registering loaders across files', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + ...commonArgs, + '--eval', + commonEvals.import(fixtures.fileURL('es-module-loaders', 'register-programmatically-loader-load.mjs')) + + commonEvals.import(fixtures.fileURL('es-module-loaders', 'register-programmatically-loader-resolve.mjs')) + + commonEvals.dynamicImport('console.log("Hello from dynamic import");'), + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + + const lines = stdout.split('\n'); + + assert.match(lines[0], /resolve passthru/); + assert.match(lines[1], /load passthru/); + assert.match(lines[2], /Hello from dynamic import/); + + assert.strictEqual(lines[3], ''); + }); + + it('works registering loaders across virtual files', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + ...commonArgs, + '--eval', + commonEvals.import(fixtures.fileURL('es-module-loaders', 'register-programmatically-loader-load.mjs')) + + commonEvals.dynamicImport( + commonEvals.import(fixtures.fileURL('es-module-loaders', 'register-programmatically-loader-resolve.mjs')) + + commonEvals.dynamicImport('console.log("Hello from dynamic import");'), + ), + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + + const lines = stdout.split('\n'); + + assert.match(lines[0], /resolve passthru/); + assert.match(lines[1], /load passthru/); + assert.match(lines[2], /Hello from dynamic import/); + + assert.strictEqual(lines[3], ''); + }); + + it('works registering the same loaders more them once', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + ...commonArgs, + '--eval', + "import { register } from 'node:module';" + + commonEvals.register(fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs')) + + commonEvals.register(fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs')) + + commonEvals.register(fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs')) + + commonEvals.register(fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs')) + + commonEvals.dynamicImport('console.log("Hello from dynamic import");'), + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + + const lines = stdout.split('\n'); + + assert.match(lines[0], /resolve passthru/); + assert.match(lines[1], /resolve passthru/); + assert.match(lines[2], /load passthru/); + assert.match(lines[3], /load passthru/); + assert.match(lines[4], /Hello from dynamic import/); + + assert.strictEqual(lines[5], ''); + }); + + it('works registering loaders as package name', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + ...commonArgs, + '--eval', + "import { register } from 'node:module';" + + commonEvals.register('resolve', fixtures.fileURL('es-module-loaders', 'package.json')) + + commonEvals.register('load', fixtures.fileURL('es-module-loaders', 'package.json')) + + commonEvals.dynamicImport('console.log("Hello from dynamic import");'), + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + + const lines = stdout.split('\n'); + + // Resolve occurs twice because it is first used to resolve the `load` loader + // _AND THEN_ the `register` module. + assert.match(lines[0], /resolve passthru/); + assert.match(lines[1], /resolve passthru/); + assert.match(lines[2], /load passthru/); + assert.match(lines[3], /Hello from dynamic import/); + + assert.strictEqual(lines[4], ''); + }); + + it('works without a CLI flag', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--input-type=module', + '--eval', + "import { register } from 'node:module';" + + commonEvals.register(fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs')) + + commonEvals.dynamicImport('console.log("Hello from dynamic import");'), + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + + const lines = stdout.split('\n'); + + assert.match(lines[0], /load passthru/); + assert.match(lines[1], /Hello from dynamic import/); + + assert.strictEqual(lines[2], ''); + }); + + it('does not work with a loader specifier that does not exist', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + ...commonArgs, + '--eval', + "import { register } from 'node:module';" + + commonEvals.register('./not-found.mjs', import.meta.url) + + commonEvals.dynamicImport('console.log("Hello from dynamic import");'), + ]); + + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + assert.match(stderr, /ERR_MODULE_NOT_FOUND/); + }); + + it('does not work with a loader that got syntax errors', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + ...commonArgs, + '--eval', + "import { register } from 'node:module';" + + commonEvals.register(fixtures.fileURL('es-module-loaders', 'syntax-error.mjs')) + + commonEvals.dynamicImport('console.log("Hello from dynamic import");'), + ]); + + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + assert.match(stderr, /SyntaxError/); + }); +}); diff --git a/test/es-module/test-esm-loader-resolve-type.mjs b/test/es-module/test-esm-loader-resolve-type.mjs index 482320c664c5d8..4c5e7aede8fccc 100644 --- a/test/es-module/test-esm-loader-resolve-type.mjs +++ b/test/es-module/test-esm-loader-resolve-type.mjs @@ -1,44 +1,46 @@ -// Flags: --loader ./test/fixtures/es-module-loaders/hook-resolve-type.mjs -import { allowGlobals } from '../common/index.mjs'; +import { spawnPromisified } from '../common/index.mjs'; +import * as tmpdir from '../common/tmpdir.js'; import * as fixtures from '../common/fixtures.mjs'; -import { strict as assert } from 'assert'; -import * as fs from 'fs'; - -allowGlobals(global.getModuleTypeStats); - -const { importedESM: importedESMBefore, - importedCJS: importedCJSBefore } = await global.getModuleTypeStats(); - -const basePath = - new URL('./node_modules/', import.meta.url); - -const rel = (file) => new URL(file, basePath); -const createDir = (path) => { - if (!fs.existsSync(path)) { - fs.mkdirSync(path); - } -}; +import { deepStrictEqual } from 'node:assert'; +import { mkdir, rm, cp } from 'node:fs/promises'; +import { execPath } from 'node:process'; +const base = tmpdir.fileURL(`test-esm-loader-resolve-type-${(Math.random() * Date.now()).toFixed(0)}`); const moduleName = 'module-counter-by-type'; -const moduleDir = rel(`${moduleName}`); +const moduleURL = new URL(`${base}/node_modules/${moduleName}`); try { - createDir(basePath); - createDir(moduleDir); - fs.cpSync( - fixtures.path('es-modules', moduleName), - moduleDir, + await mkdir(moduleURL, { recursive: true }); + await cp( + fixtures.path('es-modules', 'module-counter-by-type'), + moduleURL, { recursive: true } ); + const output = await spawnPromisified( + execPath, + [ + '--no-warnings', + '--input-type=module', + '--eval', + `import { getModuleTypeStats } from ${JSON.stringify(fixtures.fileURL('es-module-loaders', 'hook-resolve-type.mjs'))}; + const before = getModuleTypeStats(); + await import(${JSON.stringify(moduleName)}); + const after = getModuleTypeStats(); + console.log(JSON.stringify({ before, after }));`, + ], + { cwd: base }, + ); - await import(`${moduleName}`); + deepStrictEqual(output, { + code: 0, + signal: null, + stderr: '', + stdout: JSON.stringify({ + before: { importedESM: 0, importedCJS: 0 }, + // Dynamic import in the eval script should increment ESM counter but not CJS counter + after: { importedESM: 1, importedCJS: 0 }, + }) + '\n', + }); } finally { - fs.rmSync(basePath, { recursive: true, force: true }); + await rm(base, { recursive: true, force: true }); } - -const { importedESM: importedESMAfter, - importedCJS: importedCJSAfter } = await global.getModuleTypeStats(); - -// Dynamic import above should increment ESM counter but not CJS counter -assert.strictEqual(importedESMBefore + 1, importedESMAfter); -assert.strictEqual(importedCJSBefore, importedCJSAfter); diff --git a/test/es-module/test-esm-loader-search.js b/test/es-module/test-esm-loader-search.js index 0440d3d7775cff..3c451409b356db 100644 --- a/test/es-module/test-esm-loader-search.js +++ b/test/es-module/test-esm-loader-search.js @@ -10,8 +10,8 @@ const { defaultResolve: resolve } = require('internal/modules/esm/resolve'); -assert.rejects( - resolve('target'), +assert.throws( + () => resolve('target'), { code: 'ERR_MODULE_NOT_FOUND', name: 'Error', diff --git a/test/es-module/test-esm-loader-spawn-promisified.mjs b/test/es-module/test-esm-loader-spawn-promisified.mjs index 3a107ea64816b2..162316ade410b9 100644 --- a/test/es-module/test-esm-loader-spawn-promisified.mjs +++ b/test/es-module/test-esm-loader-spawn-promisified.mjs @@ -28,7 +28,7 @@ describe('Loader hooks throwing errors', { concurrency: true }, () => { fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'), '--input-type=module', '--eval', - `import '${fixtures.fileURL('/es-modules/file.unknown')}'`, + `import ${JSON.stringify(fixtures.fileURL('/es-modules/file.unknown'))}`, ]); assert.match(stderr, /ERR_UNKNOWN_FILE_EXTENSION/); @@ -142,7 +142,7 @@ describe('Loader hooks throwing errors', { concurrency: true }, () => { `import assert from 'node:assert'; await Promise.allSettled([ import('nonexistent/file.mjs'), - import('${fixtures.fileURL('/es-modules/file.unknown')}'), + import(${JSON.stringify(fixtures.fileURL('/es-modules/file.unknown'))}), import('esmHook/badReturnVal.mjs'), import('esmHook/format.false'), import('esmHook/format.true'), @@ -170,7 +170,7 @@ describe('Loader hooks parsing modules', { concurrency: true }, () => { '--input-type=module', '--eval', `import assert from 'node:assert'; - await import('${fixtures.fileURL('/es-module-loaders/js-as-esm.js')}') + await import(${JSON.stringify(fixtures.fileURL('/es-module-loaders/js-as-esm.js'))}) .then((parsedModule) => { assert.strictEqual(typeof parsedModule, 'object'); assert.strictEqual(parsedModule.namedExport, 'named-export'); @@ -191,7 +191,7 @@ describe('Loader hooks parsing modules', { concurrency: true }, () => { '--input-type=module', '--eval', `import assert from 'node:assert'; - await import('${fixtures.fileURL('/es-modules/file.ext')}') + await import(${JSON.stringify(fixtures.fileURL('/es-modules/file.ext'))}) .then((parsedModule) => { assert.strictEqual(typeof parsedModule, 'object'); const { default: defaultExport } = parsedModule; @@ -258,7 +258,7 @@ describe('Loader hooks parsing modules', { concurrency: true }, () => { '--input-type=module', '--eval', `import assert from 'node:assert'; - await import('${fixtures.fileURL('/es-modules/stateful.mjs')}') + await import(${JSON.stringify(fixtures.fileURL('/es-modules/stateful.mjs'))}) .then(({ default: count }) => { assert.strictEqual(count(), 1); });`, diff --git a/test/es-module/test-esm-loader-with-syntax-error.mjs b/test/es-module/test-esm-loader-with-syntax-error.mjs index 0ed995ad510ee7..02a96b5b9470a8 100644 --- a/test/es-module/test-esm-loader-with-syntax-error.mjs +++ b/test/es-module/test-esm-loader-with-syntax-error.mjs @@ -13,7 +13,7 @@ describe('ESM: loader with syntax error', { concurrency: true }, () => { path('print-error-message.js'), ]); - match(stderr, /SyntaxError:/); + match(stderr, /SyntaxError \[Error\]:/); ok(!stderr.includes('Bad command or file name')); notStrictEqual(code, 0); }); diff --git a/test/es-module/test-esm-main-lookup.mjs b/test/es-module/test-esm-main-lookup.mjs index 4694d1c8e626e0..4f4f1c378914d7 100644 --- a/test/es-module/test-esm-main-lookup.mjs +++ b/test/es-module/test-esm-main-lookup.mjs @@ -1,24 +1,22 @@ -import '../common/index.mjs'; +import { mustNotCall } from '../common/index.mjs'; +import * as fixtures from '../common/fixtures.mjs'; import assert from 'assert'; -async function main() { - let mod; - try { - mod = await import('../fixtures/es-modules/pjson-main'); - } catch (e) { - assert.strictEqual(e.code, 'ERR_UNSUPPORTED_DIR_IMPORT'); - } +Object.defineProperty(Error.prototype, 'url', { + get: mustNotCall('get %Error.prototype%.url'), + set: mustNotCall('set %Error.prototype%.url'), +}); +Object.defineProperty(Object.prototype, 'url', { + get: mustNotCall('get %Object.prototype%.url'), + set: mustNotCall('set %Object.prototype%.url'), +}); - assert.strictEqual(mod, undefined); +await assert.rejects(import('../fixtures/es-modules/pjson-main'), { + code: 'ERR_UNSUPPORTED_DIR_IMPORT', + url: fixtures.fileURL('es-modules/pjson-main').href, +}); - try { - mod = await import('../fixtures/es-modules/pjson-main/main.mjs'); - } catch (e) { - console.log(e); - assert.fail(); - } - - assert.strictEqual(mod.main, 'main'); -} - -main(); +assert.deepStrictEqual( + { ...await import('../fixtures/es-modules/pjson-main/main.mjs') }, + { main: 'main' }, +); diff --git a/test/es-module/test-esm-named-exports.mjs b/test/es-module/test-esm-named-exports.mjs index ce8599e68b1bf5..bbe9c96b92d9b8 100644 --- a/test/es-module/test-esm-named-exports.mjs +++ b/test/es-module/test-esm-named-exports.mjs @@ -1,4 +1,4 @@ -// Flags: --experimental-loader ./test/fixtures/es-module-loaders/builtin-named-exports-loader.mjs +// Flags: --import ./test/fixtures/es-module-loaders/builtin-named-exports.mjs import '../common/index.mjs'; import { readFile, __fromLoader } from 'fs'; import assert from 'assert'; diff --git a/test/es-module/test-esm-resolve-type.mjs b/test/es-module/test-esm-resolve-type.mjs index f594e56cf18510..7a0527ff59e554 100644 --- a/test/es-module/test-esm-resolve-type.mjs +++ b/test/es-module/test-esm-resolve-type.mjs @@ -37,16 +37,16 @@ try { * ensure that resolving by full path does not return the format * with the defaultResolver */ - await Promise.all([ + [ [ '/es-modules/package-type-module/index.js', 'module' ], [ '/es-modules/package-type-commonjs/index.js', 'commonjs' ], [ '/es-modules/package-without-type/index.js', 'commonjs' ], [ '/es-modules/package-without-pjson/index.js', 'commonjs' ], - ].map(async ([ testScript, expectedType ]) => { + ].forEach(([ testScript, expectedType ]) => { const resolvedPath = path.resolve(fixtures.path(testScript)); - const resolveResult = await resolve(url.pathToFileURL(resolvedPath)); + const resolveResult = resolve(url.pathToFileURL(resolvedPath)); assert.strictEqual(resolveResult.format, expectedType); - })); + }); /** * create a test module and try to resolve it by module name. @@ -85,7 +85,7 @@ try { fs.writeFileSync(script, 'export function esm-resolve-tester() {return 42}'); - const resolveResult = await resolve(`${moduleName}`); + const resolveResult = resolve(`${moduleName}`); assert.strictEqual(resolveResult.format, expectedResolvedType); fs.rmSync(nmDir, { recursive: true, force: true }); @@ -168,14 +168,14 @@ try { ); // test the resolve - const resolveResult = await resolve(`${moduleName}`); + const resolveResult = resolve(`${moduleName}`); assert.strictEqual(resolveResult.format, 'module'); assert.ok(resolveResult.url.includes('my-dual-package/es/index.js')); } // TestParameters are ModuleName, mainRequireScript, mainImportScript, // mainPackageType, subdirPkgJsonType, expectedResolvedFormat, mainSuffix - await Promise.all([ + [ [ 'mjs-mod-mod', 'index.js', 'index.mjs', 'module', 'module', 'module'], [ 'mjs-com-com', 'idx.js', 'idx.mjs', 'commonjs', 'commonjs', 'module'], [ 'mjs-mod-com', 'index.js', 'imp.mjs', 'module', 'commonjs', 'module'], @@ -186,7 +186,7 @@ try { [ 'hmod', 'index.js', 'imp.js', 'commonjs', 'module', 'module', '#Key'], [ 'qhmod', 'index.js', 'imp.js', 'commonjs', 'module', 'module', '?k=v#h'], [ 'ts-mod-com', 'index.js', 'imp.ts', 'module', 'commonjs', undefined], - ].map(async (testVariant) => { + ].forEach((testVariant) => { const [ moduleName, mainRequireScript, @@ -234,10 +234,10 @@ try { ); // test the resolve - const resolveResult = await resolve(`${moduleName}`); + const resolveResult = resolve(`${moduleName}`); assert.strictEqual(resolveResult.format, expectedResolvedFormat); assert.ok(resolveResult.url.endsWith(`${moduleName}/subdir/${mainImportScript}${mainSuffix}`)); - })); + }); } finally { process.chdir(previousCwd); diff --git a/test/es-module/test-esm-type-flag-errors.js b/test/es-module/test-esm-type-field-errors.js similarity index 100% rename from test/es-module/test-esm-type-flag-errors.js rename to test/es-module/test-esm-type-field-errors.js diff --git a/test/es-module/test-esm-type-flag.mjs b/test/es-module/test-esm-type-field.mjs similarity index 100% rename from test/es-module/test-esm-type-flag.mjs rename to test/es-module/test-esm-type-field.mjs diff --git a/test/es-module/test-esm-type-flag-cli-entry.mjs b/test/es-module/test-esm-type-flag-cli-entry.mjs new file mode 100644 index 00000000000000..002840751532ff --- /dev/null +++ b/test/es-module/test-esm-type-flag-cli-entry.mjs @@ -0,0 +1,92 @@ +import { spawnPromisified } from '../common/index.mjs'; +import * as fixtures from '../common/fixtures.mjs'; +import { describe, it } from 'node:test'; +import { match, strictEqual } from 'node:assert'; + +describe('--experimental-default-type=module should not support extension searching', { concurrency: true }, () => { + it('should support extension searching under --experimental-default-type=commonjs', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-default-type=commonjs', + 'index', + ], { + cwd: fixtures.path('es-modules/package-without-type'), + }); + + strictEqual(stdout, 'package-without-type\n'); + strictEqual(stderr, ''); + strictEqual(code, 0); + strictEqual(signal, null); + }); + + it('should error with implicit extension under --experimental-default-type=module', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-default-type=module', + 'index', + ], { + cwd: fixtures.path('es-modules/package-without-type'), + }); + + match(stderr, /ENOENT.*Did you mean to import .*index\.js\?/s); + strictEqual(stdout, ''); + strictEqual(code, 1); + strictEqual(signal, null); + }); +}); + +describe('--experimental-default-type=module should not parse paths as URLs', { concurrency: true }, () => { + it('should not parse a `?` in a filename as starting a query string', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-default-type=module', + 'file#1.js', + ], { + cwd: fixtures.path('es-modules/package-without-type'), + }); + + strictEqual(stderr, ''); + strictEqual(stdout, 'file#1\n'); + strictEqual(code, 0); + strictEqual(signal, null); + }); + + it('should resolve `..`', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-default-type=module', + '../package-without-type/file#1.js', + ], { + cwd: fixtures.path('es-modules/package-without-type'), + }); + + strictEqual(stderr, ''); + strictEqual(stdout, 'file#1\n'); + strictEqual(code, 0); + strictEqual(signal, null); + }); + + it('should allow a leading `./`', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-default-type=module', + './file#1.js', + ], { + cwd: fixtures.path('es-modules/package-without-type'), + }); + + strictEqual(stderr, ''); + strictEqual(stdout, 'file#1\n'); + strictEqual(code, 0); + strictEqual(signal, null); + }); + + it('should not require a leading `./`', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-default-type=module', + 'file#1.js', + ], { + cwd: fixtures.path('es-modules/package-without-type'), + }); + + strictEqual(stderr, ''); + strictEqual(stdout, 'file#1\n'); + strictEqual(code, 0); + strictEqual(signal, null); + }); +}); diff --git a/test/es-module/test-esm-type-flag-errors.mjs b/test/es-module/test-esm-type-flag-errors.mjs new file mode 100644 index 00000000000000..6d54eff94763ef --- /dev/null +++ b/test/es-module/test-esm-type-flag-errors.mjs @@ -0,0 +1,31 @@ +import { spawnPromisified } from '../common/index.mjs'; +import * as fixtures from '../common/fixtures.mjs'; +import { describe, it } from 'node:test'; +import { match, strictEqual } from 'node:assert'; + +describe('--experimental-default-type=module should not affect the interpretation of files with unknown extensions', + { concurrency: true }, () => { + it('should error on an entry point with an unknown extension', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-default-type=module', + fixtures.path('es-modules/package-type-module/extension.unknown'), + ]); + + match(stderr, /ERR_UNKNOWN_FILE_EXTENSION/); + strictEqual(stdout, ''); + strictEqual(code, 1); + strictEqual(signal, null); + }); + + it('should error on an import with an unknown extension', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-default-type=module', + fixtures.path('es-modules/package-type-module/imports-unknownext.mjs'), + ]); + + match(stderr, /ERR_UNKNOWN_FILE_EXTENSION/); + strictEqual(stdout, ''); + strictEqual(code, 1); + strictEqual(signal, null); + }); + }); diff --git a/test/es-module/test-esm-type-flag-loose-files.mjs b/test/es-module/test-esm-type-flag-loose-files.mjs new file mode 100644 index 00000000000000..ed95e1807f57c7 --- /dev/null +++ b/test/es-module/test-esm-type-flag-loose-files.mjs @@ -0,0 +1,75 @@ +// Flags: --experimental-default-type=module --experimental-wasm-modules +import { spawnPromisified } from '../common/index.mjs'; +import * as fixtures from '../common/fixtures.mjs'; +import { describe, it } from 'node:test'; +import { strictEqual } from 'node:assert'; + +describe('the type flag should change the interpretation of certain files outside of any package scope', + { concurrency: true }, () => { + it('should run as ESM a .js file that is outside of any package scope', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-default-type=module', + fixtures.path('es-modules/loose.js'), + ]); + + strictEqual(stderr, ''); + strictEqual(stdout, 'executed\n'); + strictEqual(code, 0); + strictEqual(signal, null); + }); + + it('should run as ESM an extensionless JavaScript file that is outside of any package scope', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-default-type=module', + fixtures.path('es-modules/noext-esm'), + ]); + + strictEqual(stderr, ''); + strictEqual(stdout, 'executed\n'); + strictEqual(code, 0); + strictEqual(signal, null); + }); + + it('should run as Wasm an extensionless Wasm file that is outside of any package scope', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-default-type=module', + '--experimental-wasm-modules', + '--no-warnings', + fixtures.path('es-modules/noext-wasm'), + ]); + + strictEqual(stderr, ''); + strictEqual(stdout, ''); + strictEqual(code, 0); + strictEqual(signal, null); + }); + + it('should import as ESM a .js file that is outside of any package scope', async () => { + const { default: defaultExport } = await import(fixtures.fileURL('es-modules/loose.js')); + strictEqual(defaultExport, 'module'); + }); + + it('should import as ESM an extensionless JavaScript file that is outside of any package scope', + async () => { + const { default: defaultExport } = await import(fixtures.fileURL('es-modules/noext-esm')); + strictEqual(defaultExport, 'module'); + }); + + it('should import as Wasm an extensionless Wasm file that is outside of any package scope', async () => { + const { add } = await import(fixtures.fileURL('es-modules/noext-wasm')); + strictEqual(add(1, 2), 3); + }); + + it('should check as ESM input passed via --check', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-default-type=module', + '--check', + fixtures.path('es-modules/loose.js'), + ]); + + strictEqual(stderr, ''); + strictEqual(stdout, ''); + strictEqual(code, 0); + strictEqual(signal, null); + }); + }); diff --git a/test/es-module/test-esm-type-flag-package-scopes.mjs b/test/es-module/test-esm-type-flag-package-scopes.mjs new file mode 100644 index 00000000000000..bf9d7d7ca4944c --- /dev/null +++ b/test/es-module/test-esm-type-flag-package-scopes.mjs @@ -0,0 +1,167 @@ +// Flags: --experimental-default-type=module --experimental-wasm-modules +import { spawnPromisified } from '../common/index.mjs'; +import * as fixtures from '../common/fixtures.mjs'; +import { describe, it } from 'node:test'; +import { strictEqual } from 'node:assert'; + +describe('the type flag should change the interpretation of certain files within a "type": "module" package scope', + { concurrency: true }, () => { + it('should run as ESM an extensionless JavaScript file within a "type": "module" scope', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-default-type=module', + fixtures.path('es-modules/package-type-module/noext-esm'), + ]); + + strictEqual(stderr, ''); + strictEqual(stdout, 'executed\n'); + strictEqual(code, 0); + strictEqual(signal, null); + }); + + it('should import an extensionless JavaScript file within a "type": "module" scope', async () => { + const { default: defaultExport } = + await import(fixtures.fileURL('es-modules/package-type-module/noext-esm')); + strictEqual(defaultExport, 'module'); + }); + + it('should import an extensionless JavaScript file within a "type": "module" scope under node_modules', + async () => { + const { default: defaultExport } = + await import(fixtures.fileURL( + 'es-modules/package-type-module/node_modules/dep-with-package-json-type-module/noext-esm')); + strictEqual(defaultExport, 'module'); + }); + + it('should run as Wasm an extensionless Wasm file within a "type": "module" scope', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-default-type=module', + '--experimental-wasm-modules', + '--no-warnings', + fixtures.path('es-modules/package-type-module/noext-wasm'), + ]); + + strictEqual(stderr, ''); + strictEqual(stdout, 'executed\n'); + strictEqual(code, 0); + strictEqual(signal, null); + }); + + it('should import as Wasm an extensionless Wasm file within a "type": "module" scope', async () => { + const { add } = await import(fixtures.fileURL('es-modules/package-type-module/noext-wasm')); + strictEqual(add(1, 2), 3); + }); + + it('should import an extensionless Wasm file within a "type": "module" scope under node_modules', + async () => { + const { add } = await import(fixtures.fileURL( + 'es-modules/package-type-module/node_modules/dep-with-package-json-type-module/noext-wasm')); + strictEqual(add(1, 2), 3); + }); + }); + +describe(`the type flag should change the interpretation of certain files within a package scope that lacks a +"type" field and is not under node_modules`, { concurrency: true }, () => { + it('should run as ESM a .js file within package scope that has no defined "type" and is not under node_modules', + async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-default-type=module', + fixtures.path('es-modules/package-without-type/module.js'), + ]); + + strictEqual(stderr, ''); + strictEqual(stdout, 'executed\n'); + strictEqual(code, 0); + strictEqual(signal, null); + }); + + it(`should run as ESM an extensionless JavaScript file within a package scope that has no defined "type" and is not +under node_modules`, async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-default-type=module', + fixtures.path('es-modules/package-without-type/noext-esm'), + ]); + + strictEqual(stderr, ''); + strictEqual(stdout, 'executed\n'); + strictEqual(code, 0); + strictEqual(signal, null); + }); + + it(`should run as Wasm an extensionless Wasm file within a package scope that has no defined "type" and is not under + node_modules`, async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-default-type=module', + '--experimental-wasm-modules', + '--no-warnings', + fixtures.path('es-modules/noext-wasm'), + ]); + + strictEqual(stderr, ''); + strictEqual(stdout, ''); + strictEqual(code, 0); + strictEqual(signal, null); + }); + + it('should import as ESM a .js file within package scope that has no defined "type" and is not under node_modules', + async () => { + const { default: defaultExport } = await import(fixtures.fileURL('es-modules/package-without-type/module.js')); + strictEqual(defaultExport, 'module'); + }); + + it(`should import as ESM an extensionless JavaScript file within a package scope that has no defined "type" and is + not under node_modules`, async () => { + const { default: defaultExport } = await import(fixtures.fileURL('es-modules/package-without-type/noext-esm')); + strictEqual(defaultExport, 'module'); + }); + + it(`should import as Wasm an extensionless Wasm file within a package scope that has no defined "type" and is not + under node_modules`, async () => { + const { add } = await import(fixtures.fileURL('es-modules/noext-wasm')); + strictEqual(add(1, 2), 3); + }); +}); + +describe(`the type flag should NOT change the interpretation of certain files within a package scope that lacks a +"type" field and is under node_modules`, { concurrency: true }, () => { + it('should run as CommonJS a .js file within package scope that has no defined "type" and is under node_modules', + async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-default-type=module', + fixtures.path('es-modules/package-type-module/node_modules/dep-with-package-json-without-type/run.js'), + ]); + + strictEqual(stderr, ''); + strictEqual(stdout, 'executed\n'); + strictEqual(code, 0); + strictEqual(signal, null); + }); + + it(`should import as CommonJS a .js file within a package scope that has no defined "type" and is under + node_modules`, async () => { + const { default: defaultExport } = + await import(fixtures.fileURL( + 'es-modules/package-type-module/node_modules/dep-with-package-json-without-type/run.js')); + strictEqual(defaultExport, 42); + }); + + it(`should run as CommonJS an extensionless JavaScript file within a package scope that has no defined "type" and is + under node_modules`, async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-default-type=module', + fixtures.path('es-modules/package-type-module/node_modules/dep-with-package-json-without-type/noext-cjs'), + ]); + + strictEqual(stderr, ''); + strictEqual(stdout, 'executed\n'); + strictEqual(code, 0); + strictEqual(signal, null); + }); + + it(`should import as CommonJS an extensionless JavaScript file within a package scope that has no defined "type" and + is under node_modules`, async () => { + const { default: defaultExport } = + await import(fixtures.fileURL( + 'es-modules/package-type-module/node_modules/dep-with-package-json-without-type/noext-cjs')); + strictEqual(defaultExport, 42); + }); +}); diff --git a/test/es-module/test-esm-type-flag-string-input.mjs b/test/es-module/test-esm-type-flag-string-input.mjs new file mode 100644 index 00000000000000..c4236c00c4f28f --- /dev/null +++ b/test/es-module/test-esm-type-flag-string-input.mjs @@ -0,0 +1,44 @@ +import { spawnPromisified } from '../common/index.mjs'; +import { spawn } from 'node:child_process'; +import { describe, it } from 'node:test'; +import { strictEqual, match } from 'node:assert'; + +describe('the type flag should change the interpretation of string input', { concurrency: true }, () => { + it('should run as ESM input passed via --eval', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-default-type=module', + '--eval', + 'import "data:text/javascript,console.log(42)"', + ]); + + strictEqual(stderr, ''); + strictEqual(stdout, '42\n'); + strictEqual(code, 0); + strictEqual(signal, null); + }); + + // ESM is unsupported for --print via --input-type=module + + it('should run as ESM input passed via STDIN', async () => { + const child = spawn(process.execPath, [ + '--experimental-default-type=module', + ]); + child.stdin.end('console.log(typeof import.meta.resolve)'); + + match((await child.stdout.toArray()).toString(), /^function\r?\n$/); + }); + + it('should be overridden by --input-type', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(process.execPath, [ + '--experimental-default-type=module', + '--input-type=commonjs', + '--eval', + 'console.log(require("process").version)', + ]); + + strictEqual(stderr, ''); + strictEqual(stdout, `${process.version}\n`); + strictEqual(code, 0); + strictEqual(signal, null); + }); +}); diff --git a/test/es-module/test-esm-unknown-extension.js b/test/es-module/test-esm-unknown-extension.js new file mode 100644 index 00000000000000..dae9568c523fe5 --- /dev/null +++ b/test/es-module/test-esm-unknown-extension.js @@ -0,0 +1,29 @@ +'use strict'; + +const { spawnPromisified } = require('../common'); +const fixtures = require('../common/fixtures.js'); +const assert = require('node:assert'); +const { execPath } = require('node:process'); +const { describe, it } = require('node:test'); + + +// In a "type": "module" package scope, files with unknown extensions should throw; +// both when used as a main entry point and also when referenced via `import`. +describe('ESM: unknown specifiers', { concurrency: true }, () => { + for ( + const fixturePath of [ + '/es-modules/package-type-module/extension.unknown', + '/es-modules/package-type-module/imports-unknownext.mjs', + ] + ) { + it('should throw', async () => { + const entry = fixtures.path(fixturePath); + const { code, signal, stderr, stdout } = await spawnPromisified(execPath, [entry]); + + assert.strictEqual(code, 1); + assert.strictEqual(signal, null); + assert.strictEqual(stdout, ''); + assert.match(stderr, /ERR_UNKNOWN_FILE_EXTENSION/); + }); + } +}); diff --git a/test/es-module/test-esm-unknown-or-no-extension.js b/test/es-module/test-esm-unknown-or-no-extension.js deleted file mode 100644 index 3f0660e5aa9225..00000000000000 --- a/test/es-module/test-esm-unknown-or-no-extension.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; - -const { spawnPromisified } = require('../common'); -const fixtures = require('../common/fixtures.js'); -const assert = require('node:assert'); -const { execPath } = require('node:process'); -const { describe, it } = require('node:test'); - - -// In a "type": "module" package scope, files with unknown extensions or no -// extensions should throw; both when used as a main entry point and also when -// referenced via `import`. -describe('ESM: extensionless and unknown specifiers', { concurrency: true }, () => { - for ( - const fixturePath of [ - '/es-modules/package-type-module/noext-esm', - '/es-modules/package-type-module/imports-noext.mjs', - '/es-modules/package-type-module/extension.unknown', - '/es-modules/package-type-module/imports-unknownext.mjs', - ] - ) { - it('should throw', async () => { - const entry = fixtures.path(fixturePath); - const { code, signal, stderr, stdout } = await spawnPromisified(execPath, [entry]); - - assert.strictEqual(code, 1); - assert.strictEqual(signal, null); - assert.strictEqual(stdout, ''); - assert.ok(stderr.includes('ERR_UNKNOWN_FILE_EXTENSION')); - if (fixturePath.includes('noext')) { - // Check for explanation to users - assert.ok(stderr.includes('extensionless')); - } - }); - } -}); diff --git a/test/es-module/test-esm-url-extname.js b/test/es-module/test-esm-url-extname.js new file mode 100644 index 00000000000000..d40601243e609a --- /dev/null +++ b/test/es-module/test-esm-url-extname.js @@ -0,0 +1,27 @@ +// Flags: --expose-internals +'use strict'; +require('../common'); +const assert = require('node:assert'); +const path = require('node:path'); +const { extname } = require('node:internal/modules/esm/get_format'); +const { fileURLToPath } = require('node:url'); + +[ + 'file:///c:/path/to/file', + 'file:///c:/path/to/file.ext', + 'file:///c:/path.to/file.ext', + 'file:///c:/path.to/file', + 'file:///c:/path.to/.file', + 'file:///c:/path.to/.file.ext', + 'file:///c:/path/to/f.ext', + 'file:///c:/path/to/..ext', + 'file:///c:/path/to/..', + 'file:///c:/file', + 'file:///c:/file.ext', + 'file:///c:/.file', + 'file:///c:/.file.ext', +].forEach((input) => { + const inputAsURL = new URL(input); + const inputAsPath = fileURLToPath(inputAsURL); + assert.strictEqual(extname(inputAsURL), path.extname(inputAsPath)); +}); diff --git a/test/es-module/test-esm-virtual-json.mjs b/test/es-module/test-esm-virtual-json.mjs new file mode 100644 index 00000000000000..8876eea013ced8 --- /dev/null +++ b/test/es-module/test-esm-virtual-json.mjs @@ -0,0 +1,30 @@ +import '../common/index.mjs'; +import * as fixtures from '../common/fixtures.mjs'; +import { register } from 'node:module'; +import assert from 'node:assert'; + +async function resolve(referrer, context, next) { + const result = await next(referrer, context); + const url = new URL(result.url); + url.searchParams.set('randomSeed', Math.random()); + result.url = url.href; + return result; +} + +function load(url, context, next) { + if (context.importAttributes.type === 'json') { + return { + shortCircuit: true, + format: 'json', + source: JSON.stringify({ data: Math.random() }), + }; + } + return next(url, context); +} + +register(`data:text/javascript,export ${encodeURIComponent(resolve)};export ${encodeURIComponent(load)}`); + +assert.notDeepStrictEqual( + await import(fixtures.fileURL('empty.json'), { assert: { type: 'json' } }), + await import(fixtures.fileURL('empty.json'), { assert: { type: 'json' } }), +); diff --git a/test/es-module/test-loaders-hidden-from-users.js b/test/es-module/test-loaders-hidden-from-users.js index 96d1c44154883e..59e910ad751dbe 100644 --- a/test/es-module/test-loaders-hidden-from-users.js +++ b/test/es-module/test-loaders-hidden-from-users.js @@ -7,16 +7,16 @@ const assert = require('assert'); assert.throws( () => { - require('internal/bootstrap/loaders'); + require('internal/bootstrap/realm'); }, { code: 'MODULE_NOT_FOUND', - message: /Cannot find module 'internal\/bootstrap\/loaders'/ + message: /Cannot find module 'internal\/bootstrap\/realm'/ } ); assert.throws( () => { - const source = 'module.exports = require("internal/bootstrap/loaders")'; + const source = 'module.exports = require("internal/bootstrap/realm")'; const { internalBinding } = require('internal/test/binding'); internalBinding('natives').owo = source; require('owo'); diff --git a/test/es-module/test-loaders-workers-spawned.mjs b/test/es-module/test-loaders-workers-spawned.mjs new file mode 100644 index 00000000000000..bcd651f5ad6c3f --- /dev/null +++ b/test/es-module/test-loaders-workers-spawned.mjs @@ -0,0 +1,83 @@ +import { spawnPromisified } from '../common/index.mjs'; +import * as fixtures from '../common/fixtures.mjs'; +import assert from 'node:assert'; +import { execPath } from 'node:process'; +import { describe, it } from 'node:test'; + +describe('Worker threads do not spawn infinitely', { concurrency: true }, () => { + it('should not trigger an infinite loop when using a loader exports no recognized hooks', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + fixtures.fileURL('empty.js'), + '--eval', + 'setTimeout(() => console.log("hello"),99)', + ]); + + assert.strictEqual(stderr, ''); + assert.match(stdout, /^hello\r?\n$/); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); + + it('should support a CommonJS entry point and a loader that imports a CommonJS module', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + fixtures.fileURL('es-module-loaders/loader-with-dep.mjs'), + fixtures.path('print-delayed.js'), + ]); + + assert.strictEqual(stderr, ''); + assert.match(stdout, /^delayed\r?\n$/); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); + + it('should support --require and --import along with using a loader written in CJS and CJS entry point', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--eval', + 'setTimeout(() => console.log("D"),99)', + '--import', + fixtures.fileURL('printC.js'), + '--experimental-loader', + fixtures.fileURL('printB.js'), + '--require', + fixtures.path('printA.js'), + ]); + + assert.strictEqual(stderr, ''); + // We are validating that: + // 1. the `--require` flag is run first from the main thread (and A is printed). + // 2. the `--require` flag is then run on the loader thread (and A is printed). + // 3. the `--loader` module is executed (and B is printed). + // 4. the `--import` module is evaluated once, on the main thread (and C is printed). + // 5. the user code is finally executed (and D is printed). + // The worker code should always run before the --import, but the console.log might arrive late. + assert.match(stdout, /^A\r?\n(A\r?\nB\r?\nC|A\r?\nC\r?\nB|C\r?\nA\r?\nB)\r?\nD\r?\n$/); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); + + it('should support --require and --import along with using a loader written in ESM and ESM entry point', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--require', + fixtures.path('printA.js'), + '--experimental-loader', + 'data:text/javascript,console.log("B")', + '--import', + fixtures.fileURL('printC.js'), + '--input-type=module', + '--eval', + 'setTimeout(() => console.log("D"),99)', + ]); + + assert.strictEqual(stderr, ''); + // The worker code should always run before the --import, but the console.log might arrive late. + assert.match(stdout, /^A\r?\nA\r?\n(B\r?\nC|C\r?\nB)\r?\nD\r?\n$/); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); +}); diff --git a/test/parallel/test-wasm-memory-out-of-bound.js b/test/es-module/test-wasm-memory-out-of-bound.js similarity index 100% rename from test/parallel/test-wasm-memory-out-of-bound.js rename to test/es-module/test-wasm-memory-out-of-bound.js diff --git a/test/parallel/test-wasm-simple.js b/test/es-module/test-wasm-simple.js similarity index 100% rename from test/parallel/test-wasm-simple.js rename to test/es-module/test-wasm-simple.js diff --git a/test/parallel/test-wasm-web-api.js b/test/es-module/test-wasm-web-api.js similarity index 100% rename from test/parallel/test-wasm-web-api.js rename to test/es-module/test-wasm-web-api.js diff --git a/test/fixtures/errors/force_colors.snapshot b/test/fixtures/errors/force_colors.snapshot index 4c33acbc2d5c12..3624d9f0804545 100644 --- a/test/fixtures/errors/force_colors.snapshot +++ b/test/fixtures/errors/force_colors.snapshot @@ -4,11 +4,11 @@ throw new Error('Should include grayed stack trace') Error: Should include grayed stack trace at Object. (/test*force_colors.js:1:7) - at Module._compile (node:internal*modules*cjs*loader:1256:14) - at Module._extensions..js (node:internal*modules*cjs*loader:1310:10) - at Module.load (node:internal*modules*cjs*loader:1119:32) - at Module._load (node:internal*modules*cjs*loader:960:12) - at Function.executeUserEntryPoint [as runMain] (node:internal*modules*run_main:86:12) - at node:internal*main*run_main_module:23:47 + at * + at * + at * + at * + at * + at * Node.js * diff --git a/test/fixtures/es-module-loaders/assertionless-json-import.mjs b/test/fixtures/es-module-loaders/assertionless-json-import.mjs index 07656d4ec40fa3..3ffc4c1148fe69 100644 --- a/test/fixtures/es-module-loaders/assertionless-json-import.mjs +++ b/test/fixtures/es-module-loaders/assertionless-json-import.mjs @@ -1,17 +1,24 @@ const DATA_URL_PATTERN = /^data:application\/json(?:[^,]*?)(;base64)?,([\s\S]*)$/; -const JSON_URL_PATTERN = /\.json(\?[^#]*)?(#.*)?$/; +const JSON_URL_PATTERN = /^[^?]+\.json(\?[^#]*)?(#.*)?$/; + +export async function resolve(specifier, context, next) { + const noAttributesSpecified = context.importAttributes.type == null; -export function resolve(url, context, next) { // Mutation from resolve hook should be discarded. - context.importAssertions.type = 'whatever'; - return next(url); -} + context.importAttributes.type = 'whatever'; -export function load(url, context, next) { - if (context.importAssertions.type == null && - (DATA_URL_PATTERN.test(url) || JSON_URL_PATTERN.test(url))) { - const { importAssertions } = context; - importAssertions.type = 'json'; + // This fixture assumes that no other resolve hooks in the chain will error on invalid import attributes + // (as defaultResolve doesn't). + const result = await next(specifier, context); + + if (noAttributesSpecified && + (DATA_URL_PATTERN.test(result.url) || JSON_URL_PATTERN.test(result.url))) { + // Clean new import attributes object to ensure that this test isn't passing due to mutation. + result.importAttributes = { + ...(result.importAttributes ?? context.importAttributes), + type: 'json', + }; } - return next(url); + + return result; } diff --git a/test/fixtures/es-module-loaders/builtin-named-exports-loader.mjs b/test/fixtures/es-module-loaders/builtin-named-exports-loader.mjs index 8c317c1b7ce31e..7ee339b47029f9 100644 --- a/test/fixtures/es-module-loaders/builtin-named-exports-loader.mjs +++ b/test/fixtures/es-module-loaders/builtin-named-exports-loader.mjs @@ -1,16 +1,9 @@ -import module from 'module'; - -const GET_BUILTIN = `$__get_builtin_hole_${Date.now()}`; - -export function globalPreload() { - return `Object.defineProperty(globalThis, ${JSON.stringify(GET_BUILTIN)}, { - value: (builtinName) => { - return getBuiltin(builtinName); - }, - enumerable: false, - configurable: false, -}); -`; +import module from 'node:module'; + +/** @type {string} */ +let GET_BUILTIN; +export function initialize(data) { + GET_BUILTIN = data.GET_BUILTIN; } export async function resolve(specifier, context, next) { @@ -20,7 +13,7 @@ export async function resolve(specifier, context, next) { return { shortCircuit: true, url: `custom-${def.url}`, - importAssertions: context.importAssertions, + importAttributes: context.importAttributes, }; } return def; diff --git a/test/fixtures/es-module-loaders/builtin-named-exports.mjs b/test/fixtures/es-module-loaders/builtin-named-exports.mjs new file mode 100644 index 00000000000000..123b12c26bf0c9 --- /dev/null +++ b/test/fixtures/es-module-loaders/builtin-named-exports.mjs @@ -0,0 +1,17 @@ +import * as fixtures from '../../common/fixtures.mjs'; +import { createRequire, register } from 'node:module'; + +const require = createRequire(import.meta.url); + +const GET_BUILTIN = `$__get_builtin_hole_${Date.now()}`; +Object.defineProperty(globalThis, GET_BUILTIN, { + value: builtinName => require(builtinName), + enumerable: false, + configurable: false, +}); + +register(fixtures.fileURL('es-module-loaders/builtin-named-exports-loader.mjs'), { + data: { + GET_BUILTIN, + }, +}); diff --git a/test/fixtures/es-module-loaders/hook-resolve-type-loader.mjs b/test/fixtures/es-module-loaders/hook-resolve-type-loader.mjs new file mode 100644 index 00000000000000..c410401876e448 --- /dev/null +++ b/test/fixtures/es-module-loaders/hook-resolve-type-loader.mjs @@ -0,0 +1,25 @@ +/** @type {Uint8Array} */ +let data; +/** @type {number} */ +let ESM_MODULE_INDEX; +/** @type {number} */ +let CJS_MODULE_INDEX; + +export function initialize({ sab, ESM_MODULE_INDEX:e, CJS_MODULE_INDEX:c }) { + data = new Uint8Array(sab); + ESM_MODULE_INDEX = e; + CJS_MODULE_INDEX = c; +} + +export async function resolve(specifier, context, next) { + const nextResult = await next(specifier, context); + const { format } = nextResult; + + if (format === 'module' || specifier.endsWith('.mjs')) { + Atomics.add(data, ESM_MODULE_INDEX, 1); + } else if (format == null || format === 'commonjs') { + Atomics.add(data, CJS_MODULE_INDEX, 1); + } + + return nextResult; +} diff --git a/test/fixtures/es-module-loaders/hook-resolve-type.mjs b/test/fixtures/es-module-loaders/hook-resolve-type.mjs index a4d87938ad843f..7324a08e84b6c0 100644 --- a/test/fixtures/es-module-loaders/hook-resolve-type.mjs +++ b/test/fixtures/es-module-loaders/hook-resolve-type.mjs @@ -1,44 +1,18 @@ -let importedESM = 0; -let importedCJS = 0; +import * as fixtures from '../../common/fixtures.mjs'; +import { register } from 'node:module'; -export function globalPreload({ port }) { - port.on('message', (int32) => { - port.postMessage({ importedESM, importedCJS }); - Atomics.store(int32, 0, 1); - Atomics.notify(int32, 0); - }); - port.unref(); - return ` - const { receiveMessageOnPort } = getBuiltin('worker_threads'); - global.getModuleTypeStats = async function getModuleTypeStats() { - const sab = new SharedArrayBuffer(4); - const int32 = new Int32Array(sab); - port.postMessage(int32); - // Artificial timeout to keep the event loop alive. - // https://bugs.chromium.org/p/v8/issues/detail?id=13238 - // TODO(targos) Remove when V8 issue is resolved. - const timeout = setTimeout(() => { throw new Error('timeout'); }, 1_000); - await Atomics.waitAsync(int32, 0, 0).value; - clearTimeout(timeout); - return receiveMessageOnPort(port).message; - }; - `; -} - -export async function load(url, context, next) { - return next(url); -} - -export async function resolve(specifier, context, next) { - const nextResult = await next(specifier, context); - const { format } = nextResult; +const sab = new SharedArrayBuffer(2); +const data = new Uint8Array(sab); - if (format === 'module' || specifier.endsWith('.mjs')) { - importedESM++; - } else if (format == null || format === 'commonjs') { - importedCJS++; - } +const ESM_MODULE_INDEX = 0 +const CJS_MODULE_INDEX = 1 - return nextResult; +export function getModuleTypeStats() { + const importedESM = Atomics.load(data, ESM_MODULE_INDEX); + const importedCJS = Atomics.load(data, CJS_MODULE_INDEX); + return { importedESM, importedCJS }; } +register(fixtures.fileURL('es-module-loaders/hook-resolve-type-loader.mjs'), { + data: { sab, ESM_MODULE_INDEX, CJS_MODULE_INDEX }, +}); diff --git a/test/fixtures/es-module-loaders/hooks-custom.mjs b/test/fixtures/es-module-loaders/hooks-custom.mjs index ea2ffaf7e97070..5656f95232b856 100644 --- a/test/fixtures/es-module-loaders/hooks-custom.mjs +++ b/test/fixtures/es-module-loaders/hooks-custom.mjs @@ -6,7 +6,7 @@ import count from '../es-modules/stateful.mjs'; // used to assert node-land and user-land have different contexts count(); -export function resolve(specifier, { importAssertions }, next) { +export function resolve(specifier, { importAttributes }, next) { let format = ''; if (specifier === 'esmHook/format.false') { @@ -24,7 +24,7 @@ export function resolve(specifier, { importAssertions }, next) { format, shortCircuit: true, url: pathToFileURL(specifier).href, - importAssertions, + importAttributes, }; } diff --git a/test/fixtures/es-module-loaders/hooks-initialize-port.mjs b/test/fixtures/es-module-loaders/hooks-initialize-port.mjs new file mode 100644 index 00000000000000..cefe8854297c50 --- /dev/null +++ b/test/fixtures/es-module-loaders/hooks-initialize-port.mjs @@ -0,0 +1,16 @@ +let thePort = null; + +export async function initialize(port) { + port.postMessage('initialize'); + thePort = port; +} + +export async function resolve(specifier, context, next) { + if (specifier === 'node:fs' || specifier.includes('loader')) { + return next(specifier); + } + + thePort.postMessage(`resolve ${specifier}`); + + return next(specifier); +} diff --git a/test/fixtures/es-module-loaders/hooks-initialize.mjs b/test/fixtures/es-module-loaders/hooks-initialize.mjs new file mode 100644 index 00000000000000..7622d982a9d7c5 --- /dev/null +++ b/test/fixtures/es-module-loaders/hooks-initialize.mjs @@ -0,0 +1,7 @@ +import { writeFileSync } from 'node:fs'; + +let counter = 0; + +export async function initialize() { + writeFileSync(1, `hooks initialize ${++counter}\n`); +} diff --git a/test/fixtures/es-module-loaders/hooks-input.mjs b/test/fixtures/es-module-loaders/hooks-input.mjs index 6859cfc07d9b6a..1d3759f458224e 100644 --- a/test/fixtures/es-module-loaders/hooks-input.mjs +++ b/test/fixtures/es-module-loaders/hooks-input.mjs @@ -2,6 +2,7 @@ // node --loader ./test/fixtures/es-module-loaders/hooks-input.mjs ./test/fixtures/es-modules/json-modules.mjs import assert from 'assert'; +import { writeSync } from 'fs'; import { readFile } from 'fs/promises'; import { fileURLToPath } from 'url'; @@ -16,16 +17,17 @@ export async function resolve(specifier, context, next) { if (resolveCalls === 1) { url = new URL(specifier).href; assert.match(specifier, /json-modules\.mjs$/); - assert.strictEqual(context.parentURL, undefined); - assert.deepStrictEqual(context.importAssertions, { - __proto__: null, - }); + + if (!(/\[eval\d*\]$/).test(context.parentURL)) { + assert.strictEqual(context.parentURL, undefined); + } + + assert.deepStrictEqual(context.importAttributes, {}); } else if (resolveCalls === 2) { url = new URL(specifier, context.parentURL).href; assert.match(specifier, /experimental\.json$/); assert.match(context.parentURL, /json-modules\.mjs$/); - assert.deepStrictEqual(context.importAssertions, { - __proto__: null, + assert.deepStrictEqual(context.importAttributes, { type: 'json', }); } @@ -33,7 +35,7 @@ export async function resolve(specifier, context, next) { // Ensure `context` has all and only the properties it's supposed to assert.deepStrictEqual(Reflect.ownKeys(context), [ 'conditions', - 'importAssertions', + 'importAttributes', 'parentURL', ]); assert.ok(Array.isArray(context.conditions)); @@ -45,7 +47,7 @@ export async function resolve(specifier, context, next) { shortCircuit: true, } - console.log(JSON.stringify(returnValue)); // For the test to validate when it parses stdout + writeSync(1, JSON.stringify(returnValue) + '\n'); // For the test to validate when it parses stdout return returnValue; } @@ -57,14 +59,11 @@ export async function load(url, context, next) { if (loadCalls === 1) { assert.match(url, /json-modules\.mjs$/); - assert.deepStrictEqual(context.importAssertions, { - __proto__: null, - }); + assert.deepStrictEqual(context.importAttributes, {}); format = 'module'; } else if (loadCalls === 2) { assert.match(url, /experimental\.json$/); - assert.deepStrictEqual(context.importAssertions, { - __proto__: null, + assert.deepStrictEqual(context.importAttributes, { type: 'json', }); format = 'json'; @@ -74,7 +73,7 @@ export async function load(url, context, next) { // Ensure `context` has all and only the properties it's supposed to assert.deepStrictEqual(Object.keys(context), [ 'format', - 'importAssertions', + 'importAttributes', ]); assert.strictEqual(context.format, 'test'); assert.strictEqual(typeof next, 'function'); @@ -85,7 +84,7 @@ export async function load(url, context, next) { shortCircuit: true, }; - console.log(JSON.stringify(returnValue)); // For the test to validate when it parses stdout + writeSync(1, JSON.stringify(returnValue) + '\n'); // For the test to validate when it parses stdout return returnValue; } diff --git a/test/fixtures/es-module-loaders/hooks-obsolete.mjs b/test/fixtures/es-module-loaders/hooks-obsolete.mjs deleted file mode 100644 index bb10ef8ef4b29a..00000000000000 --- a/test/fixtures/es-module-loaders/hooks-obsolete.mjs +++ /dev/null @@ -1,22 +0,0 @@ -export function dynamicInstantiate() {} -export function getFormat() {} -export function getSource() {} -export function transformSource() {} - - -export function resolve(specifier, context, next) { - if (specifier === 'whatever') return { - url: specifier, - }; - - return next(specifier); -} - -export function load(url, context, next) { - if (url === 'whatever') return { - format: 'module', - source: '', - }; - - return next(url); -} diff --git a/test/fixtures/es-module-loaders/loader-edge-cases.mjs b/test/fixtures/es-module-loaders/loader-edge-cases.mjs index f50df0988194e4..19af0e2bc078c0 100644 --- a/test/fixtures/es-module-loaders/loader-edge-cases.mjs +++ b/test/fixtures/es-module-loaders/loader-edge-cases.mjs @@ -1,15 +1,13 @@ import { strictEqual } from "node:assert"; import { isMainThread, workerData, parentPort } from "node:worker_threads"; -// TODO(aduh95): switch this to `false` when loader hooks are run on a separate thread. -strictEqual(isMainThread, true); +strictEqual(isMainThread, false); // We want to make sure that internals are not leaked on the public module: strictEqual(workerData, null); strictEqual(parentPort, null); -// TODO(aduh95): switch to `"undefined"` when loader hooks are run on a separate thread. // We don't want `import.meta.resolve` being available from loaders // as the sync implementation is not compatible with calling async // functions on the same thread. -strictEqual(typeof import.meta.resolve, 'function'); +strictEqual(typeof import.meta.resolve, 'undefined'); diff --git a/test/fixtures/es-module-loaders/loader-invalid-format.mjs b/test/fixtures/es-module-loaders/loader-invalid-format.mjs index e7dd06c108ba1d..dc61a792b2be8b 100644 --- a/test/fixtures/es-module-loaders/loader-invalid-format.mjs +++ b/test/fixtures/es-module-loaders/loader-invalid-format.mjs @@ -1,4 +1,4 @@ -export async function resolve(specifier, { parentURL, importAssertions }, next) { +export async function resolve(specifier, { parentURL, importAttributes }, next) { if (parentURL && specifier === '../fixtures/es-modules/test-esm-ok.mjs') { return { shortCircuit: true, diff --git a/test/fixtures/es-module-loaders/loader-invalid-url.mjs b/test/fixtures/es-module-loaders/loader-invalid-url.mjs index a54f39521f29ac..aac2b16b6f58fe 100644 --- a/test/fixtures/es-module-loaders/loader-invalid-url.mjs +++ b/test/fixtures/es-module-loaders/loader-invalid-url.mjs @@ -1,9 +1,9 @@ -export async function resolve(specifier, { parentURL, importAssertions }, next) { +export async function resolve(specifier, { parentURL, importAttributes }, next) { if (parentURL && specifier === '../fixtures/es-modules/test-esm-ok.mjs') { return { shortCircuit: true, url: specifier, - importAssertions, + importAttributes, }; } return next(specifier); diff --git a/test/fixtures/es-module-loaders/loader-load-dynamic-import.mjs b/test/fixtures/es-module-loaders/loader-load-dynamic-import.mjs new file mode 100644 index 00000000000000..96af5507d17212 --- /dev/null +++ b/test/fixtures/es-module-loaders/loader-load-dynamic-import.mjs @@ -0,0 +1,14 @@ +import { writeSync } from 'node:fs'; + + +export async function load(url, context, next) { + if (url === 'node:fs' || url.includes('loader')) { + return next(url); + } + + // Here for asserting dynamic import + await import('xxx/loader-load-passthru.mjs'); + + writeSync(1, 'load dynamic import' + '\n'); // Signal that this specific hook ran + return next(url, context); +} diff --git a/test/fixtures/es-module-loaders/loader-load-foo-or-42.mjs b/test/fixtures/es-module-loaders/loader-load-foo-or-42.mjs index 8d408223e66a0a..285b81a910ef5d 100644 --- a/test/fixtures/es-module-loaders/loader-load-foo-or-42.mjs +++ b/test/fixtures/es-module-loaders/loader-load-foo-or-42.mjs @@ -1,4 +1,12 @@ -export async function load(url) { +export async function load(url, context, next) { + // This check is needed to make sure that we don't prevent the + // resolution from follow-up loaders. It wouldn't be a problem + // in real life because loaders aren't supposed to break the + // resolution, but the ones used in our tests do, for convenience. + if (url === 'node:fs' || url.includes('loader')) { + return next(url); + } + const val = url.includes('42') ? '42' : '"foo"'; diff --git a/test/fixtures/es-module-loaders/loader-load-incomplete.mjs b/test/fixtures/es-module-loaders/loader-load-incomplete.mjs index d6242488e5738e..bf6d5ea254dcc6 100644 --- a/test/fixtures/es-module-loaders/loader-load-incomplete.mjs +++ b/test/fixtures/es-module-loaders/loader-load-incomplete.mjs @@ -1,4 +1,12 @@ -export async function load() { +export async function load(url, context, next) { + // This check is needed to make sure that we don't prevent the + // resolution from follow-up loaders. It wouldn't be a problem + // in real life because loaders aren't supposed to break the + // resolution, but the ones used in our tests do, for convenience. + if (url === 'node:fs' || url.includes('loader')) { + return next(url); + } + return { format: 'module', source: 'export default 42', diff --git a/test/fixtures/es-module-loaders/loader-load-passthru.mjs b/test/fixtures/es-module-loaders/loader-load-passthru.mjs index 0de06142007562..72ff6b56122d77 100644 --- a/test/fixtures/es-module-loaders/loader-load-passthru.mjs +++ b/test/fixtures/es-module-loaders/loader-load-passthru.mjs @@ -1,4 +1,14 @@ +import { writeSync } from 'node:fs'; + export async function load(url, context, next) { - console.log('load passthru'); // This log is deliberate + // This check is needed to make sure that we don't prevent the + // resolution from follow-up loaders. It wouldn't be a problem + // in real life because loaders aren't supposed to break the + // resolution, but the ones used in our tests do, for convenience. + if (url === 'node:fs' || url.includes('loader')) { + return next(url); + } + + writeSync(1, 'load passthru' + '\n'); // Signal that this specific hook ran return next(url); } diff --git a/test/fixtures/es-module-loaders/loader-load-receiving-modified-context.mjs b/test/fixtures/es-module-loaders/loader-load-receiving-modified-context.mjs index 2d7bc350bd8775..6e5a1ee7193652 100644 --- a/test/fixtures/es-module-loaders/loader-load-receiving-modified-context.mjs +++ b/test/fixtures/es-module-loaders/loader-load-receiving-modified-context.mjs @@ -1,4 +1,7 @@ +import { writeSync } from 'node:fs'; + + export async function load(url, context, next) { - console.log(context.foo); // This log is deliberate + writeSync(1, context.foo + '\n'); // Expose actual value the hook was called with return next(url, context); } diff --git a/test/fixtures/es-module-loaders/loader-log-args.mjs b/test/fixtures/es-module-loaders/loader-log-args.mjs index 84ed373d6b4de4..b56fddbce5854d 100644 --- a/test/fixtures/es-module-loaders/loader-log-args.mjs +++ b/test/fixtures/es-module-loaders/loader-log-args.mjs @@ -1,10 +1,13 @@ +import { writeSync } from 'node:fs'; +import { inspect } from 'node:util' + export async function resolve(...args) { - console.log(`resolve arg count: ${args.length}`); - console.log({ + writeSync(1, `resolve arg count: ${args.length}\n`); + writeSync(1, inspect({ specifier: args[0], context: args[1], next: args[2], - }); + }) + '\n'); return { shortCircuit: true, @@ -13,12 +16,12 @@ export async function resolve(...args) { } export async function load(...args) { - console.log(`load arg count: ${args.length}`); - console.log({ + writeSync(1, `load arg count: ${args.length}\n`); + writeSync(1, inspect({ url: args[0], context: args[1], next: args[2], - }); + }) + '\n'); return { format: 'module', diff --git a/test/fixtures/es-module-loaders/loader-resolve-42.mjs b/test/fixtures/es-module-loaders/loader-resolve-42.mjs index eaca111998ae23..b571a27a9787e9 100644 --- a/test/fixtures/es-module-loaders/loader-resolve-42.mjs +++ b/test/fixtures/es-module-loaders/loader-resolve-42.mjs @@ -1,6 +1,17 @@ +import { writeSync } from 'node:fs'; + + export async function resolve(specifier, context, next) { - console.log('resolve 42'); // This log is deliberate - console.log('next:', next.name); // This log is deliberate + // This check is needed to make sure that we don't prevent the + // resolution from follow-up loaders. It wouldn't be a problem + // in real life because loaders aren't supposed to break the + // resolution, but the ones used in our tests do, for convenience. + if (specifier === 'node:fs' || specifier.includes('loader')) { + return next(specifier); + } + + writeSync(1, 'resolve 42' + '\n'); // Signal that this specific hook ran + writeSync(1, `next: ${next.name}\n`); // Expose actual value the hook was called with return next('file:///42.mjs'); } diff --git a/test/fixtures/es-module-loaders/loader-resolve-dynamic-import.mjs b/test/fixtures/es-module-loaders/loader-resolve-dynamic-import.mjs new file mode 100644 index 00000000000000..edc2303ed9aa9e --- /dev/null +++ b/test/fixtures/es-module-loaders/loader-resolve-dynamic-import.mjs @@ -0,0 +1,14 @@ +import { writeSync } from 'node:fs'; + + +export async function resolve(specifier, context, next) { + if (specifier === 'node:fs' || specifier.includes('loader')) { + return next(specifier); + } + + // Here for asserting dynamic import + await import('xxx/loader-resolve-passthru.mjs'); + + writeSync(1, 'resolve dynamic import' + '\n'); // Signal that this specific hook ran + return next(specifier); +} diff --git a/test/fixtures/es-module-loaders/loader-resolve-foo.mjs b/test/fixtures/es-module-loaders/loader-resolve-foo.mjs index 7d23d6c49088c9..b5e5a419b99d45 100644 --- a/test/fixtures/es-module-loaders/loader-resolve-foo.mjs +++ b/test/fixtures/es-module-loaders/loader-resolve-foo.mjs @@ -1,4 +1,15 @@ +import { writeSync } from 'node:fs'; + + export async function resolve(specifier, context, next) { - console.log('resolve foo'); // This log is deliberate + // This check is needed to make sure that we don't prevent the + // resolution from follow-up loaders. It wouldn't be a problem + // in real life because loaders aren't supposed to break the + // resolution, but the ones used in our tests do, for convenience. + if (specifier === 'node:fs' || specifier.includes('loader')) { + return next(specifier); + } + + writeSync(1, 'resolve foo' + '\n'); // Signal that this specific hook ran return next('file:///foo.mjs'); } diff --git a/test/fixtures/es-module-loaders/loader-resolve-incomplete.mjs b/test/fixtures/es-module-loaders/loader-resolve-incomplete.mjs index 9eb1617f30130e..cb37a43527186c 100644 --- a/test/fixtures/es-module-loaders/loader-resolve-incomplete.mjs +++ b/test/fixtures/es-module-loaders/loader-resolve-incomplete.mjs @@ -1,4 +1,12 @@ -export async function resolve() { +export async function resolve(specifier, context, next) { + // This check is needed to make sure that we don't prevent the + // resolution from follow-up loaders. It wouldn't be a problem + // in real life because loaders aren't supposed to break the + // resolution, but the ones used in our tests do, for convenience. + if (specifier === 'node:fs' || specifier.includes('loader')) { + return next(specifier); + } + return { url: 'file:///incomplete-resolve-chain.js', }; diff --git a/test/fixtures/es-module-loaders/loader-resolve-next-modified.mjs b/test/fixtures/es-module-loaders/loader-resolve-next-modified.mjs index a973345a82ff21..a6b8e85455d31c 100644 --- a/test/fixtures/es-module-loaders/loader-resolve-next-modified.mjs +++ b/test/fixtures/es-module-loaders/loader-resolve-next-modified.mjs @@ -1,4 +1,12 @@ export async function resolve(url, context, next) { + // This check is needed to make sure that we don't prevent the + // resolution from follow-up loaders. It wouldn't be a problem + // in real life because loaders aren't supposed to break the + // resolution, but the ones used in our tests do, for convenience. + if (url === 'node:fs' || url.includes('loader')) { + return next(url); + } + const { format, url: nextUrl, diff --git a/test/fixtures/es-module-loaders/loader-resolve-passthru.mjs b/test/fixtures/es-module-loaders/loader-resolve-passthru.mjs index 3db5b21bb98793..f388f0db273d02 100644 --- a/test/fixtures/es-module-loaders/loader-resolve-passthru.mjs +++ b/test/fixtures/es-module-loaders/loader-resolve-passthru.mjs @@ -1,4 +1,14 @@ +import { writeSync } from 'node:fs'; + export async function resolve(specifier, context, next) { - console.log('resolve passthru'); // This log is deliberate + // This check is needed to make sure that we don't prevent the + // resolution from follow-up loaders. It wouldn't be a problem + // in real life because loaders aren't supposed to break the + // resolution, but the ones used in our tests do, for convenience. + if (specifier === 'node:fs' || specifier.includes('loader')) { + return next(specifier); + } + + writeSync(1, 'resolve passthru' + '\n'); // Signal that this specific hook ran return next(specifier); } diff --git a/test/fixtures/es-module-loaders/loader-resolve-receiving-modified-context.mjs b/test/fixtures/es-module-loaders/loader-resolve-receiving-modified-context.mjs index 83aa83104e96e4..f6a8fdad53ece3 100644 --- a/test/fixtures/es-module-loaders/loader-resolve-receiving-modified-context.mjs +++ b/test/fixtures/es-module-loaders/loader-resolve-receiving-modified-context.mjs @@ -1,4 +1,7 @@ +import { writeSync } from 'node:fs'; + + export async function resolve(specifier, context, next) { - console.log(context.foo); // This log is deliberate + writeSync(1, context.foo + '\n'); // Expose actual value the hook was called with return next(specifier, context); } diff --git a/test/fixtures/es-module-loaders/loader-resolve-shortcircuit.mjs b/test/fixtures/es-module-loaders/loader-resolve-shortcircuit.mjs index d886b3dfcbf237..00c18e75e2c7c5 100644 --- a/test/fixtures/es-module-loaders/loader-resolve-shortcircuit.mjs +++ b/test/fixtures/es-module-loaders/loader-resolve-shortcircuit.mjs @@ -1,4 +1,12 @@ -export async function resolve(specifier) { +export async function resolve(specifier, context, next) { + // This check is needed to make sure that we don't prevent the + // resolution from follow-up loaders. It wouldn't be a problem + // in real life because loaders aren't supposed to break the + // resolution, but the ones used in our tests do, for convenience. + if (specifier === 'node:fs' || specifier.includes('loader')) { + return next(specifier); + } + return { shortCircuit: true, url: specifier, diff --git a/test/fixtures/es-module-loaders/loader-resolve-strip-xxx.mjs b/test/fixtures/es-module-loaders/loader-resolve-strip-xxx.mjs new file mode 100644 index 00000000000000..996dfd041c0df6 --- /dev/null +++ b/test/fixtures/es-module-loaders/loader-resolve-strip-xxx.mjs @@ -0,0 +1,10 @@ +import { writeSync } from 'node:fs'; +import { inspect } from 'node:util'; + +export async function resolve(specifier, context, nextResolve) { + if (specifier.startsWith('node:')) { + return nextResolve(specifier); + } + writeSync(1, `loader-a ${inspect({specifier})}\n`); + return nextResolve(specifier.replace(/^xxx\//, `./`)); +} diff --git a/test/fixtures/es-module-loaders/loader-resolve-strip-yyy.mjs b/test/fixtures/es-module-loaders/loader-resolve-strip-yyy.mjs new file mode 100644 index 00000000000000..7746469bf817eb --- /dev/null +++ b/test/fixtures/es-module-loaders/loader-resolve-strip-yyy.mjs @@ -0,0 +1,7 @@ +import { writeSync } from 'node:fs'; +import { inspect } from 'node:util'; + +export async function resolve(specifier, context, nextResolve) { + writeSync(1, `loader-b ${inspect({specifier})}\n`); + return nextResolve(specifier.replace(/^yyy\//, `./`)); +} diff --git a/test/fixtures/es-module-loaders/loader-this-value-inside-hook-functions.mjs b/test/fixtures/es-module-loaders/loader-this-value-inside-hook-functions.mjs index c1c80622feea66..2be18c4969ef80 100644 --- a/test/fixtures/es-module-loaders/loader-this-value-inside-hook-functions.mjs +++ b/test/fixtures/es-module-loaders/loader-this-value-inside-hook-functions.mjs @@ -1,14 +1,21 @@ +export function initialize() { + if (this != null) { + throw new Error('hook function must not be bound to loader instance'); + } +} + export function resolve(url, _, next) { - if (this != null) throw new Error('hook function must not be bound to ESMLoader instance'); + if (this != null) { + throw new Error('hook function must not be bound to loader instance'); + } + return next(url); } export function load(url, _, next) { - if (this != null) throw new Error('hook function must not be bound to ESMLoader instance'); - return next(url); -} + if (this != null) { + throw new Error('hook function must not be bound to loader instance'); + } -export function globalPreload() { - if (this != null) throw new Error('hook function must not be bound to ESMLoader instance'); - return ""; + return next(url); } diff --git a/test/fixtures/es-module-loaders/loader-with-dep.mjs b/test/fixtures/es-module-loaders/loader-with-dep.mjs index 1b5fd6c3c1642a..625341eaed7eb2 100644 --- a/test/fixtures/es-module-loaders/loader-with-dep.mjs +++ b/test/fixtures/es-module-loaders/loader-with-dep.mjs @@ -3,9 +3,9 @@ import {createRequire} from '../../common/index.mjs'; const require = createRequire(import.meta.url); const dep = require('./loader-dep.js'); -export async function resolve(specifier, { parentURL, importAssertions }, defaultResolve) { +export async function resolve(specifier, { parentURL, importAttributes }, defaultResolve) { return { - url: (await defaultResolve(specifier, { parentURL, importAssertions }, defaultResolve)).url, + url: (await defaultResolve(specifier, { parentURL, importAttributes }, defaultResolve)).url, format: dep.format }; } diff --git a/test/fixtures/es-module-loaders/mock-loader.mjs b/test/fixtures/es-module-loaders/mock-loader.mjs new file mode 100644 index 00000000000000..3bb349b5385362 --- /dev/null +++ b/test/fixtures/es-module-loaders/mock-loader.mjs @@ -0,0 +1,133 @@ +import { receiveMessageOnPort } from 'node:worker_threads'; +const mockedModuleExports = new Map(); +let currentMockVersion = 0; + +// These hooks enable code running on the application thread to +// swap module resolution results for mocking purposes. It uses this instead +// of import.meta so that CommonJS can still use the functionality. +// +// It does so by allowing non-mocked modules to live in normal URL cache +// locations but creates 'mock-facade:' URL cache location for every time a +// module location is mocked. Since a single URL can be mocked multiple +// times but it cannot be removed from the cache, `mock-facade:` URLs have a +// form of mock-facade:$VERSION:$REPLACING_URL with the parameters being URL +// percent encoded every time a module is resolved. So if a module for +// 'file:///app.js' is mocked it might look like +// 'mock-facade:12:file%3A%2F%2F%2Fapp.js'. This encoding is done to prevent +// problems like mocking URLs with special URL characters like '#' or '?' from +// accidentally being picked up as part of the 'mock-facade:' URL containing +// the mocked URL. +// +// NOTE: due to ESM spec, once a specifier has been resolved in a source text +// it cannot be changed. So things like the following DO NOT WORK: +// +// ```mjs +// import mock from 'test-esm-loader-mock'; // See test-esm-loader-mock.mjs +// mock('file:///app.js', {x:1}); +// const namespace1 = await import('file:///app.js'); +// namespace1.x; // 1 +// mock('file:///app.js', {x:2}); +// const namespace2 = await import('file:///app.js'); +// namespace2.x; // STILL 1, because this source text already set the specifier +// // for 'file:///app.js', a different specifier that resolves +// // to that could still get a new namespace though +// assert(namespace1 === namespace2); +// ``` + +/** + * @param param0 message from the application context + */ +function onPreloadPortMessage({ + mockVersion, resolved, exports +}) { + currentMockVersion = mockVersion; + mockedModuleExports.set(resolved, exports); +} + +/** @type {URL['href']} */ +let mainImportURL; +/** @type {MessagePort} */ +let preloadPort; +export async function initialize(data) { + ({ mainImportURL, port: preloadPort } = data); + + data.port.on('message', onPreloadPortMessage); +} + +/** + * Because Node.js internals use a separate MessagePort for cross-thread + * communication, there could be some messages pending that we should handle + * before continuing. + */ +function doDrainPort() { + let msg; + while (msg = receiveMessageOnPort(preloadPort)) { + onPreloadPortMessage(msg.message); + } +} + +// Rewrites node: loading to mock-facade: so that it can be intercepted +export async function resolve(specifier, context, defaultResolve) { + doDrainPort(); + const def = await defaultResolve(specifier, context); + if (context.parentURL?.startsWith('mock-facade:')) { + // Do nothing, let it get the "real" module + } else if (mockedModuleExports.has(def.url)) { + return { + shortCircuit: true, + url: `mock-facade:${currentMockVersion}:${encodeURIComponent(def.url)}` + }; + }; + return { + shortCircuit: true, + url: def.url, + }; +} + +export async function load(url, context, defaultLoad) { + doDrainPort(); + /** + * Mocked fake module, not going to be handled in default way so it + * generates the source text, then short circuits + */ + if (url.startsWith('mock-facade:')) { + const encodedTargetURL = url.slice(url.lastIndexOf(':') + 1); + return { + shortCircuit: true, + source: generateModule(encodedTargetURL), + format: 'module', + }; + } + return defaultLoad(url, context); +} + +/** + * Generate the source code for a mocked module. + * @param {string} encodedTargetURL the module being mocked + * @returns {string} + */ +function generateModule(encodedTargetURL) { + const exports = mockedModuleExports.get( + decodeURIComponent(encodedTargetURL) + ); + let body = [ + `import { mockedModules } from ${JSON.stringify(mainImportURL)};`, + 'export {};', + 'let mapping = {__proto__: null};', + `const mock = mockedModules.get(${JSON.stringify(encodedTargetURL)});`, + ]; + for (const [i, name] of Object.entries(exports)) { + let key = JSON.stringify(name); + body.push(`var _${i} = mock.namespace[${key}];`); + body.push(`Object.defineProperty(mapping, ${key}, { enumerable: true, set(v) {_${i} = v;}, get() {return _${i};} });`); + body.push(`export {_${i} as ${name}};`); + } + body.push(`mock.listeners.push(${ + () => { + for (var k in mapping) { + mapping[k] = mock.namespace[k]; + } + } + });`); + return body.join('\n'); +} diff --git a/test/fixtures/es-module-loaders/mock.mjs b/test/fixtures/es-module-loaders/mock.mjs new file mode 100644 index 00000000000000..cb167f1d5204c7 --- /dev/null +++ b/test/fixtures/es-module-loaders/mock.mjs @@ -0,0 +1,70 @@ +import { register } from 'node:module'; +import { MessageChannel } from 'node:worker_threads'; + + +const { port1, port2 } = new MessageChannel(); + +register('./mock-loader.mjs', import.meta.url, { + data: { + port: port2, + mainImportURL: import.meta.url, + }, + transferList: [port2], +}); + +/** + * This is the Map that saves *all* the mocked URL -> replacement Module + * mappings + * @type {Map} + */ +export const mockedModules = new Map(); +let mockVersion = 0; + +/** + * @param {string} resolved an absolute URL HREF string + * @param {object} replacementProperties an object to pick properties from + * to act as a module namespace + * @returns {object} a mutator object that can update the module namespace + * since we can't do something like old Object.observe + */ +export function mock(resolved, replacementProperties) { + const exportNames = Object.keys(replacementProperties); + const namespace = { __proto__: null }; + /** + * @type {Array<(name: string)=>void>} functions to call whenever an + * export name is updated + */ + const listeners = []; + for (const name of exportNames) { + let currentValueForPropertyName = replacementProperties[name]; + Object.defineProperty(namespace, name, { + __proto__: null, + enumerable: true, + get() { + return currentValueForPropertyName; + }, + set(v) { + currentValueForPropertyName = v; + for (const fn of listeners) { + try { + fn(name); + } catch { + /* noop */ + } + } + }, + }); + } + mockedModules.set(encodeURIComponent(resolved), { + namespace, + listeners, + }); + mockVersion++; + // Inform the loader that the `resolved` URL should now use the specific + // `mockVersion` and has export names of `exportNames` + // + // This allows the loader to generate a fake module for that version + // and names the next time it resolves a specifier to equal `resolved` + port1.postMessage({ mockVersion, resolved, exports: exportNames }); + return namespace; +} diff --git a/test/fixtures/es-module-loaders/never-settling-resolve-step/import.meta.never-resolve.mjs b/test/fixtures/es-module-loaders/never-settling-resolve-step/import.meta.never-resolve.mjs index 51205a9475889c..fc3a077abe6ddc 100644 --- a/test/fixtures/es-module-loaders/never-settling-resolve-step/import.meta.never-resolve.mjs +++ b/test/fixtures/es-module-loaders/never-settling-resolve-step/import.meta.never-resolve.mjs @@ -1,5 +1,5 @@ console.log('should be output'); -await import.meta.resolve('never-settle-resolve'); +import.meta.resolve('never-settle-resolve'); console.log('should not be output'); diff --git a/test/fixtures/es-module-loaders/node_modules/load/index.mjs b/test/fixtures/es-module-loaders/node_modules/load/index.mjs new file mode 100644 index 00000000000000..db98e8d9f8781c --- /dev/null +++ b/test/fixtures/es-module-loaders/node_modules/load/index.mjs @@ -0,0 +1 @@ +export * from '../../loader-load-passthru.mjs' \ No newline at end of file diff --git a/test/fixtures/es-module-loaders/node_modules/load/package.json b/test/fixtures/es-module-loaders/node_modules/load/package.json new file mode 100644 index 00000000000000..b6629e247888a5 --- /dev/null +++ b/test/fixtures/es-module-loaders/node_modules/load/package.json @@ -0,0 +1,3 @@ +{ + "exports": "./index.mjs" +} diff --git a/test/fixtures/es-module-loaders/node_modules/resolve/index.mjs b/test/fixtures/es-module-loaders/node_modules/resolve/index.mjs new file mode 100644 index 00000000000000..b3769d961359a6 --- /dev/null +++ b/test/fixtures/es-module-loaders/node_modules/resolve/index.mjs @@ -0,0 +1 @@ +export * from '../../loader-resolve-passthru.mjs' \ No newline at end of file diff --git a/test/fixtures/es-module-loaders/node_modules/resolve/package.json b/test/fixtures/es-module-loaders/node_modules/resolve/package.json new file mode 100644 index 00000000000000..b6629e247888a5 --- /dev/null +++ b/test/fixtures/es-module-loaders/node_modules/resolve/package.json @@ -0,0 +1,3 @@ +{ + "exports": "./index.mjs" +} diff --git a/test/fixtures/es-module-loaders/not-found-assert-loader.mjs b/test/fixtures/es-module-loaders/not-found-assert-loader.mjs index ea4c73724298db..1786b7c04fc555 100644 --- a/test/fixtures/es-module-loaders/not-found-assert-loader.mjs +++ b/test/fixtures/es-module-loaders/not-found-assert-loader.mjs @@ -3,7 +3,7 @@ import assert from 'node:assert'; // a loader that asserts that the defaultResolve will throw "not found" // (skipping the top-level main of course) let mainLoad = true; -export async function resolve(specifier, { importAssertions }, next) { +export async function resolve(specifier, { importAttributes }, next) { if (mainLoad) { mainLoad = false; return next(specifier); @@ -15,7 +15,7 @@ export async function resolve(specifier, { importAssertions }, next) { assert.strictEqual(e.code, 'ERR_MODULE_NOT_FOUND'); return { url: 'node:fs', - importAssertions, + importAttributes, }; } assert.fail(`Module resolution for ${specifier} should be throw ERR_MODULE_NOT_FOUND`); diff --git a/test/fixtures/es-module-loaders/register-loader.cjs b/test/fixtures/es-module-loaders/register-loader.cjs new file mode 100644 index 00000000000000..9e18dfa77e2867 --- /dev/null +++ b/test/fixtures/es-module-loaders/register-loader.cjs @@ -0,0 +1,4 @@ +const { register } = require('node:module'); +const fixtures = require('../../common/fixtures.js'); + +register(fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs')); diff --git a/test/fixtures/es-module-loaders/register-loader.mjs b/test/fixtures/es-module-loaders/register-loader.mjs new file mode 100644 index 00000000000000..f3cb2de8da3d0f --- /dev/null +++ b/test/fixtures/es-module-loaders/register-loader.mjs @@ -0,0 +1,4 @@ +import { register } from 'node:module'; +import fixtures from '../../common/fixtures.js'; + +register(fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs')); diff --git a/test/fixtures/es-module-loaders/register-programmatically-loader-load.mjs b/test/fixtures/es-module-loaders/register-programmatically-loader-load.mjs new file mode 100644 index 00000000000000..fe22dc7203e9d4 --- /dev/null +++ b/test/fixtures/es-module-loaders/register-programmatically-loader-load.mjs @@ -0,0 +1,4 @@ +import * as fixtures from '../../common/fixtures.mjs'; +import { register } from 'node:module'; + +register(fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs')); diff --git a/test/fixtures/es-module-loaders/register-programmatically-loader-resolve.mjs b/test/fixtures/es-module-loaders/register-programmatically-loader-resolve.mjs new file mode 100644 index 00000000000000..3ae8841da8345a --- /dev/null +++ b/test/fixtures/es-module-loaders/register-programmatically-loader-resolve.mjs @@ -0,0 +1,3 @@ +import { register } from 'node:module'; + +register('./loader-resolve-passthru.mjs', import.meta.url); diff --git a/test/fixtures/es-module-loaders/string-sources.mjs b/test/fixtures/es-module-loaders/string-sources.mjs index 396d17cb17a75c..39ad32c465fa31 100644 --- a/test/fixtures/es-module-loaders/string-sources.mjs +++ b/test/fixtures/es-module-loaders/string-sources.mjs @@ -23,7 +23,7 @@ const SOURCES = { export function resolve(specifier, context, next) { if (specifier.startsWith('test:')) { return { - importAssertions: context.importAssertions, + importAttributes: context.importAttributes, shortCircuit: true, url: specifier, }; diff --git a/test/fixtures/es-modules/import-resolve-exports.mjs b/test/fixtures/es-modules/import-resolve-exports.mjs index 0bbce4fbc5efc0..e6a840ec996d96 100644 --- a/test/fixtures/es-modules/import-resolve-exports.mjs +++ b/test/fixtures/es-modules/import-resolve-exports.mjs @@ -1,10 +1,4 @@ import { strictEqual } from 'assert'; -(async () => { - const resolved = await import.meta.resolve('pkgexports-sugar'); - strictEqual(typeof resolved, 'string'); -})() -.catch((e) => { - console.error(e); - process.exit(1); -}); +const resolved = import.meta.resolve('pkgexports-sugar'); +strictEqual(typeof resolved, 'string'); diff --git a/test/fixtures/es-modules/imports-loose.mjs b/test/fixtures/es-modules/imports-loose.mjs new file mode 100644 index 00000000000000..13831e5db03e82 --- /dev/null +++ b/test/fixtures/es-modules/imports-loose.mjs @@ -0,0 +1 @@ +import './loose.js'; diff --git a/test/fixtures/es-modules/imports-noext.mjs b/test/fixtures/es-modules/imports-noext.mjs new file mode 100644 index 00000000000000..96eca54521b9d3 --- /dev/null +++ b/test/fixtures/es-modules/imports-noext.mjs @@ -0,0 +1 @@ +import './noext-esm'; diff --git a/test/fixtures/es-modules/invalid-posix-host.mjs b/test/fixtures/es-modules/invalid-posix-host.mjs new file mode 100644 index 00000000000000..65ebb2c0496c15 --- /dev/null +++ b/test/fixtures/es-modules/invalid-posix-host.mjs @@ -0,0 +1 @@ +import "file://hmm.js"; diff --git a/test/fixtures/es-modules/loose.js b/test/fixtures/es-modules/loose.js new file mode 100644 index 00000000000000..69147a3b8ca027 --- /dev/null +++ b/test/fixtures/es-modules/loose.js @@ -0,0 +1,3 @@ +// This file can be run or imported only if `--experimental-default-type=module` is set. +export default 'module'; +console.log('executed'); diff --git a/test/fixtures/es-modules/noext-esm b/test/fixtures/es-modules/noext-esm new file mode 100644 index 00000000000000..251d6e538a1fcf --- /dev/null +++ b/test/fixtures/es-modules/noext-esm @@ -0,0 +1,2 @@ +export default 'module'; +console.log('executed'); diff --git a/test/fixtures/es-modules/noext-wasm b/test/fixtures/es-modules/noext-wasm new file mode 100644 index 00000000000000..9e035904b2e4d0 Binary files /dev/null and b/test/fixtures/es-modules/noext-wasm differ diff --git a/test/fixtures/es-modules/package-type-module/index.js b/test/fixtures/es-modules/package-type-module/index.js index e8f4db3e164302..86d88056422197 100644 --- a/test/fixtures/es-modules/package-type-module/index.js +++ b/test/fixtures/es-modules/package-type-module/index.js @@ -1,4 +1,4 @@ -import 'dep/dep.js'; +import 'dep-without-package-json/dep.js'; const identifier = 'package-type-module'; console.log(identifier); export default identifier; diff --git a/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/noext-esm b/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/noext-esm new file mode 100644 index 00000000000000..251d6e538a1fcf --- /dev/null +++ b/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/noext-esm @@ -0,0 +1,2 @@ +export default 'module'; +console.log('executed'); diff --git a/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/noext-wasm b/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/noext-wasm new file mode 100644 index 00000000000000..9e035904b2e4d0 Binary files /dev/null and b/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/noext-wasm differ diff --git a/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/package.json b/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/package.json new file mode 100644 index 00000000000000..8d155c74efe78a --- /dev/null +++ b/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/package.json @@ -0,0 +1,8 @@ +{ + "name": "dep-with-package-json-type-module", + "type": "module", + "version": "1.0.0", + "exports": { + "./*": "./*" + } +} diff --git a/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/wasm-dep.mjs b/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/wasm-dep.mjs new file mode 100644 index 00000000000000..a0e28aa17b6bd9 --- /dev/null +++ b/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-type-module/wasm-dep.mjs @@ -0,0 +1,15 @@ +import { strictEqual } from 'assert'; + +export function jsFn () { + state = 'WASM JS Function Executed'; + return 42; +} + +export let state = 'JS Function Executed'; + +export function jsInitFn () { + strictEqual(state, 'JS Function Executed'); + state = 'WASM Start Executed'; +} + +console.log('executed'); diff --git a/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/dep.js b/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/dep.js new file mode 100644 index 00000000000000..0d702867cd5ccf --- /dev/null +++ b/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/dep.js @@ -0,0 +1,2 @@ +// Controlling package.json has no "type" field -> should still be CommonJS as it is in node_modules +module.exports = 42; diff --git a/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/noext-cjs b/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/noext-cjs new file mode 100644 index 00000000000000..7712b3bad54497 --- /dev/null +++ b/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/noext-cjs @@ -0,0 +1,3 @@ +// No package.json -> should still be CommonJS as it is in node_modules +module.exports = 42; +console.log('executed'); diff --git a/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/package.json b/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/package.json new file mode 100644 index 00000000000000..1b83367ebe3f5f --- /dev/null +++ b/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/package.json @@ -0,0 +1,7 @@ +{ + "name": "dep-with-package-json-without-type", + "version": "1.0.0", + "exports": { + "./*": "./*" + } +} diff --git a/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/run.js b/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/run.js new file mode 100644 index 00000000000000..7712b3bad54497 --- /dev/null +++ b/test/fixtures/es-modules/package-type-module/node_modules/dep-with-package-json-without-type/run.js @@ -0,0 +1,3 @@ +// No package.json -> should still be CommonJS as it is in node_modules +module.exports = 42; +console.log('executed'); diff --git a/test/fixtures/es-modules/package-type-module/node_modules/dep/dep.js b/test/fixtures/es-modules/package-type-module/node_modules/dep-without-package-json/dep.js similarity index 100% rename from test/fixtures/es-modules/package-type-module/node_modules/dep/dep.js rename to test/fixtures/es-modules/package-type-module/node_modules/dep-without-package-json/dep.js diff --git a/test/fixtures/es-modules/package-type-module/node_modules/dep-without-package-json/noext-cjs b/test/fixtures/es-modules/package-type-module/node_modules/dep-without-package-json/noext-cjs new file mode 100644 index 00000000000000..7712b3bad54497 --- /dev/null +++ b/test/fixtures/es-modules/package-type-module/node_modules/dep-without-package-json/noext-cjs @@ -0,0 +1,3 @@ +// No package.json -> should still be CommonJS as it is in node_modules +module.exports = 42; +console.log('executed'); diff --git a/test/fixtures/es-modules/package-type-module/node_modules/dep-without-package-json/run.js b/test/fixtures/es-modules/package-type-module/node_modules/dep-without-package-json/run.js new file mode 100644 index 00000000000000..7712b3bad54497 --- /dev/null +++ b/test/fixtures/es-modules/package-type-module/node_modules/dep-without-package-json/run.js @@ -0,0 +1,3 @@ +// No package.json -> should still be CommonJS as it is in node_modules +module.exports = 42; +console.log('executed'); diff --git a/test/fixtures/es-modules/package-type-module/noext-wasm b/test/fixtures/es-modules/package-type-module/noext-wasm new file mode 100644 index 00000000000000..9e035904b2e4d0 Binary files /dev/null and b/test/fixtures/es-modules/package-type-module/noext-wasm differ diff --git a/test/fixtures/es-modules/package-type-module/wasm-dep.mjs b/test/fixtures/es-modules/package-type-module/wasm-dep.mjs new file mode 100644 index 00000000000000..a0e28aa17b6bd9 --- /dev/null +++ b/test/fixtures/es-modules/package-type-module/wasm-dep.mjs @@ -0,0 +1,15 @@ +import { strictEqual } from 'assert'; + +export function jsFn () { + state = 'WASM JS Function Executed'; + return 42; +} + +export let state = 'JS Function Executed'; + +export function jsInitFn () { + strictEqual(state, 'JS Function Executed'); + state = 'WASM Start Executed'; +} + +console.log('executed'); diff --git a/test/fixtures/es-modules/package-without-type/file#1.js b/test/fixtures/es-modules/package-without-type/file#1.js new file mode 100644 index 00000000000000..6ab97dbf4b58cf --- /dev/null +++ b/test/fixtures/es-modules/package-without-type/file#1.js @@ -0,0 +1 @@ +console.log('file#1'); diff --git a/test/fixtures/es-modules/package-without-type/module.js b/test/fixtures/es-modules/package-without-type/module.js new file mode 100644 index 00000000000000..69147a3b8ca027 --- /dev/null +++ b/test/fixtures/es-modules/package-without-type/module.js @@ -0,0 +1,3 @@ +// This file can be run or imported only if `--experimental-default-type=module` is set. +export default 'module'; +console.log('executed'); diff --git a/test/fixtures/es-modules/package-without-type/noext-esm b/test/fixtures/es-modules/package-without-type/noext-esm new file mode 100644 index 00000000000000..69147a3b8ca027 --- /dev/null +++ b/test/fixtures/es-modules/package-without-type/noext-esm @@ -0,0 +1,3 @@ +// This file can be run or imported only if `--experimental-default-type=module` is set. +export default 'module'; +console.log('executed'); diff --git a/test/fixtures/es-modules/runmain.mjs b/test/fixtures/es-modules/runmain.mjs index 5ceb86b66c76ce..ee71ff42a81368 100644 --- a/test/fixtures/es-modules/runmain.mjs +++ b/test/fixtures/es-modules/runmain.mjs @@ -1,7 +1,7 @@ import { runMain } from 'node:module'; -try { await import.meta.resolve('doesnt-matter.mjs') } catch {} +try { import.meta.resolve('doesnt-matter.mjs') } catch {} runMain(); -try { await import.meta.resolve('doesnt-matter.mjs') } catch {} +try { import.meta.resolve('doesnt-matter.mjs') } catch {} diff --git a/test/fixtures/inspector-global-function.js b/test/fixtures/inspector-global-function.mjs similarity index 100% rename from test/fixtures/inspector-global-function.js rename to test/fixtures/inspector-global-function.mjs diff --git a/test/fixtures/print-delayed.js b/test/fixtures/print-delayed.js new file mode 100644 index 00000000000000..42eb45615b2a67 --- /dev/null +++ b/test/fixtures/print-delayed.js @@ -0,0 +1,3 @@ +setTimeout(() => { + console.log('delayed'); +}, 100); diff --git a/test/fixtures/sea.js b/test/fixtures/sea.js index efdc32708b9898..2cd82c709ea157 100644 --- a/test/fixtures/sea.js +++ b/test/fixtures/sea.js @@ -9,8 +9,23 @@ expectWarning('ExperimentalWarning', 'Single executable application is an experimental feature and ' + 'might change at any time'); +// Should be possible to require core modules that optionally require the +// "node:" scheme. const { deepStrictEqual, strictEqual, throws } = require('assert'); -const { dirname } = require('path'); +const { dirname } = require('node:path'); + +// Should be possible to require a core module that requires using the "node:" +// scheme. +{ + const { test } = require('node:test'); + strictEqual(typeof test, 'function'); +} + +// Should not be possible to require a core module without the "node:" scheme if +// it requires using the "node:" scheme. +throws(() => require('test'), { + code: 'ERR_UNKNOWN_BUILTIN_MODULE', +}); deepStrictEqual(process.argv, [process.execPath, process.execPath, '-a', '--b=c', 'd']); diff --git a/test/fixtures/source-map/output/source_map_disabled_by_api.js b/test/fixtures/source-map/output/source_map_disabled_by_api.js index b1a28d0eae1c2e..d94a6310cff7ae 100644 --- a/test/fixtures/source-map/output/source_map_disabled_by_api.js +++ b/test/fixtures/source-map/output/source_map_disabled_by_api.js @@ -2,9 +2,12 @@ 'use strict'; require('../../../common'); +const assert = require('assert'); Error.stackTraceLimit = 5; +assert.strictEqual(process.sourceMapsEnabled, true); process.setSourceMapsEnabled(false); +assert.strictEqual(process.sourceMapsEnabled, false); try { require('../enclosing-call-site-min.js'); @@ -17,6 +20,7 @@ delete require.cache[require // Re-enable. process.setSourceMapsEnabled(true); +assert.strictEqual(process.sourceMapsEnabled, true); try { require('../enclosing-call-site-min.js'); diff --git a/test/fixtures/source-map/output/source_map_enabled_by_api.js b/test/fixtures/source-map/output/source_map_enabled_by_api.js index 4c70fa1cb2a240..1dd4f9530c68db 100644 --- a/test/fixtures/source-map/output/source_map_enabled_by_api.js +++ b/test/fixtures/source-map/output/source_map_enabled_by_api.js @@ -1,8 +1,11 @@ 'use strict'; require('../../../common'); +const assert = require('assert'); Error.stackTraceLimit = 5; +assert.strictEqual(process.sourceMapsEnabled, false); process.setSourceMapsEnabled(true); +assert.strictEqual(process.sourceMapsEnabled, true); try { require('../enclosing-call-site-min.js'); @@ -14,6 +17,7 @@ delete require.cache[require .resolve('../enclosing-call-site-min.js')]; process.setSourceMapsEnabled(false); +assert.strictEqual(process.sourceMapsEnabled, false); try { require('../enclosing-call-site-min.js'); diff --git a/test/fixtures/source-map/output/source_map_enclosing_function.js b/test/fixtures/source-map/output/source_map_enclosing_function.js new file mode 100644 index 00000000000000..37d2b4ddb04746 --- /dev/null +++ b/test/fixtures/source-map/output/source_map_enclosing_function.js @@ -0,0 +1,7 @@ +// Flags: --enable-source-maps + +'use strict'; +require('../../../common'); +Error.stackTraceLimit = 5; + +require('../enclosing-call-site-min.js'); diff --git a/test/fixtures/source-map/output/source_map_enclosing_function.snapshot b/test/fixtures/source-map/output/source_map_enclosing_function.snapshot new file mode 100644 index 00000000000000..976cd4fdbbc6e9 --- /dev/null +++ b/test/fixtures/source-map/output/source_map_enclosing_function.snapshot @@ -0,0 +1,13 @@ +*enclosing-call-site.js:26 + throw err + ^ + + +Error: an error! + at functionD (*enclosing-call-site.js:16:17) + at functionC (*enclosing-call-site.js:10:3) + at functionB (*enclosing-call-site.js:6:3) + at functionA (*enclosing-call-site.js:2:3) + at Object. (*enclosing-call-site.js:24:3) + +Node.js * diff --git a/test/fixtures/source-map/output/source_map_reference_error_tabs.js b/test/fixtures/source-map/output/source_map_reference_error_tabs.js new file mode 100644 index 00000000000000..59d9f1557adae5 --- /dev/null +++ b/test/fixtures/source-map/output/source_map_reference_error_tabs.js @@ -0,0 +1,7 @@ +// Flags: --enable-source-maps + +'use strict'; +require('../../../common'); +Error.stackTraceLimit = 2; + +require('../tabs.js'); diff --git a/test/fixtures/source-map/output/source_map_reference_error_tabs.snapshot b/test/fixtures/source-map/output/source_map_reference_error_tabs.snapshot new file mode 100644 index 00000000000000..97d02f176c0cb7 --- /dev/null +++ b/test/fixtures/source-map/output/source_map_reference_error_tabs.snapshot @@ -0,0 +1,10 @@ +*tabs.coffee:26 + alert "I knew it!" + ^ + + +ReferenceError: alert is not defined + at Object. (*tabs.coffee:26:2) + at Object. (*tabs.coffee:1:14) + +Node.js * diff --git a/test/fixtures/source-map/output/source_map_sourcemapping_url_string.js b/test/fixtures/source-map/output/source_map_sourcemapping_url_string.js new file mode 100644 index 00000000000000..8dca7a35bfe7b9 --- /dev/null +++ b/test/fixtures/source-map/output/source_map_sourcemapping_url_string.js @@ -0,0 +1,13 @@ +// Flags: --enable-source-maps + +'use strict'; +require('../../../common'); +Error.stackTraceLimit = 2; + +try { + require('../typescript-sourcemapping_url_string'); +} catch (err) { + setTimeout(() => { + console.info(err); + }, 10); +} diff --git a/test/fixtures/source-map/output/source_map_sourcemapping_url_string.snapshot b/test/fixtures/source-map/output/source_map_sourcemapping_url_string.snapshot new file mode 100644 index 00000000000000..6a109c904e1155 --- /dev/null +++ b/test/fixtures/source-map/output/source_map_sourcemapping_url_string.snapshot @@ -0,0 +1,3 @@ +Error: an exception. + at Object. (*typescript-sourcemapping_url_string.ts:3:7) + * diff --git a/test/fixtures/source-map/output/source_map_throw_catch.js b/test/fixtures/source-map/output/source_map_throw_catch.js new file mode 100644 index 00000000000000..c49ffcff865907 --- /dev/null +++ b/test/fixtures/source-map/output/source_map_throw_catch.js @@ -0,0 +1,13 @@ +// Flags: --enable-source-maps + +'use strict'; +require('../../../common'); +Error.stackTraceLimit = 2; + +try { + require('../typescript-throw'); +} catch (err) { + setTimeout(() => { + console.info(err); + }, 10); +} diff --git a/test/fixtures/source-map/output/source_map_throw_catch.snapshot b/test/fixtures/source-map/output/source_map_throw_catch.snapshot new file mode 100644 index 00000000000000..5eaffbfbf7874f --- /dev/null +++ b/test/fixtures/source-map/output/source_map_throw_catch.snapshot @@ -0,0 +1,4 @@ +reachable +Error: an exception + at branch (*typescript-throw.ts:18:11) + at Object. (*typescript-throw.ts:24:1) diff --git a/test/fixtures/source-map/output/source_map_throw_icu.js b/test/fixtures/source-map/output/source_map_throw_icu.js new file mode 100644 index 00000000000000..e80c3d1e308b01 --- /dev/null +++ b/test/fixtures/source-map/output/source_map_throw_icu.js @@ -0,0 +1,7 @@ +// Flags: --enable-source-maps + +'use strict'; +require('../../../common'); +Error.stackTraceLimit = 2; + +require('../icu'); diff --git a/test/fixtures/source-map/output/source_map_throw_icu.snapshot b/test/fixtures/source-map/output/source_map_throw_icu.snapshot new file mode 100644 index 00000000000000..425495062e6423 --- /dev/null +++ b/test/fixtures/source-map/output/source_map_throw_icu.snapshot @@ -0,0 +1,10 @@ +*icu.jsx:3 + ("あ 🐕 🐕", throw Error("an error")); + ^ + + +Error: an error + at Object.createElement (*icu.jsx:3:23) + at Object. (*icu.jsx:9:5) + +Node.js * diff --git a/test/fixtures/source-map/output/source_map_throw_set_immediate.js b/test/fixtures/source-map/output/source_map_throw_set_immediate.js new file mode 100644 index 00000000000000..c5601d61ac5997 --- /dev/null +++ b/test/fixtures/source-map/output/source_map_throw_set_immediate.js @@ -0,0 +1,5 @@ +// Flags: --enable-source-maps + +'use strict'; +require('../../../common'); +require('../uglify-throw'); diff --git a/test/fixtures/source-map/output/source_map_throw_set_immediate.snapshot b/test/fixtures/source-map/output/source_map_throw_set_immediate.snapshot new file mode 100644 index 00000000000000..86a95127e2943c --- /dev/null +++ b/test/fixtures/source-map/output/source_map_throw_set_immediate.snapshot @@ -0,0 +1,11 @@ +*uglify-throw-original.js:5 + throw Error('goodbye'); + ^ + + +Error: goodbye + at Hello (*uglify-throw-original.js:5:9) + at Immediate. (*uglify-throw-original.js:9:3) + at process.processImmediate (node:internal*timers:476:21) + +Node.js * diff --git a/test/fixtures/test-runner/aborts/failed-test-still-call-abort.js b/test/fixtures/test-runner/aborts/failed-test-still-call-abort.js new file mode 100644 index 00000000000000..496d2331422c00 --- /dev/null +++ b/test/fixtures/test-runner/aborts/failed-test-still-call-abort.js @@ -0,0 +1,25 @@ +const {test, afterEach} = require('node:test'); +const assert = require('node:assert'); +const { waitForAbort } = require('./wait-for-abort-helper'); + +let testCount = 0; +let signal; + +afterEach(() => { + assert.equal(signal.aborted, false); + + waitForAbort({ testNumber: ++testCount, signal }); +}); + +test("sync", (t) => { + signal = t.signal; + assert.equal(signal.aborted, false); + throw new Error('failing the sync test'); +}); + +test("async", async (t) => { + await null; + signal = t.signal; + assert.equal(signal.aborted, false); + throw new Error('failing the async test'); +}); diff --git a/test/fixtures/test-runner/aborts/successful-test-still-call-abort.js b/test/fixtures/test-runner/aborts/successful-test-still-call-abort.js new file mode 100644 index 00000000000000..4f3879c624de44 --- /dev/null +++ b/test/fixtures/test-runner/aborts/successful-test-still-call-abort.js @@ -0,0 +1,23 @@ +const {test, afterEach} = require('node:test'); +const assert = require('node:assert'); +const {waitForAbort} = require("./wait-for-abort-helper"); + +let testCount = 0; +let signal; + +afterEach(() => { + assert.equal(signal.aborted, false); + + waitForAbort({ testNumber: ++testCount, signal }); +}); + +test("sync", (t) => { + signal = t.signal; + assert.equal(signal.aborted, false); +}); + +test("async", async (t) => { + await null; + signal = t.signal; + assert.equal(signal.aborted, false); +}); diff --git a/test/fixtures/test-runner/aborts/wait-for-abort-helper.js b/test/fixtures/test-runner/aborts/wait-for-abort-helper.js new file mode 100644 index 00000000000000..89eda7ed9138ca --- /dev/null +++ b/test/fixtures/test-runner/aborts/wait-for-abort-helper.js @@ -0,0 +1,19 @@ +module.exports = { + waitForAbort: function ({ testNumber, signal }) { + let retries = 0; + + const interval = setInterval(() => { + retries++; + if(signal.aborted) { + console.log(`abort called for test ${testNumber}`); + clearInterval(interval); + return; + } + + if(retries > 100) { + clearInterval(interval); + throw new Error(`abort was not called for test ${testNumber}`); + } + }, 10); + } +} diff --git a/test/fixtures/test-runner/custom_reporters/throwing-async.js b/test/fixtures/test-runner/custom_reporters/throwing-async.js new file mode 100644 index 00000000000000..b24a632e697e4f --- /dev/null +++ b/test/fixtures/test-runner/custom_reporters/throwing-async.js @@ -0,0 +1,8 @@ +'use strict'; + +module.exports = async function * customReporter() { + yield 'Going to throw an error\n'; + setImmediate(() => { + throw new Error('Reporting error'); + }); +}; diff --git a/test/fixtures/test-runner/custom_reporters/throwing.js b/test/fixtures/test-runner/custom_reporters/throwing.js new file mode 100644 index 00000000000000..8d04901c773ac8 --- /dev/null +++ b/test/fixtures/test-runner/custom_reporters/throwing.js @@ -0,0 +1,6 @@ +'use strict'; + +module.exports = async function * customReporter() { + yield 'Going to throw an error\n'; + throw new Error('Reporting error'); +}; diff --git a/test/fixtures/test-runner/index.test.js b/test/fixtures/test-runner/default-behavior/index.test.js similarity index 100% rename from test/fixtures/test-runner/index.test.js rename to test/fixtures/test-runner/default-behavior/index.test.js diff --git a/test/fixtures/test-runner/node_modules/test-nm.js b/test/fixtures/test-runner/default-behavior/node_modules/test-nm.js similarity index 100% rename from test/fixtures/test-runner/node_modules/test-nm.js rename to test/fixtures/test-runner/default-behavior/node_modules/test-nm.js diff --git a/test/fixtures/test-runner/random.test.mjs b/test/fixtures/test-runner/default-behavior/random.test.mjs similarity index 100% rename from test/fixtures/test-runner/random.test.mjs rename to test/fixtures/test-runner/default-behavior/random.test.mjs diff --git a/test/fixtures/test-runner/default-behavior/subdir/subdir_test.js b/test/fixtures/test-runner/default-behavior/subdir/subdir_test.js new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/test/fixtures/test-runner/test/random.cjs b/test/fixtures/test-runner/default-behavior/test/random.cjs similarity index 100% rename from test/fixtures/test-runner/test/random.cjs rename to test/fixtures/test-runner/default-behavior/test/random.cjs diff --git a/test/fixtures/test-runner/test/skip_by_name.cjs b/test/fixtures/test-runner/default-behavior/test/skip_by_name.cjs similarity index 100% rename from test/fixtures/test-runner/test/skip_by_name.cjs rename to test/fixtures/test-runner/default-behavior/test/skip_by_name.cjs diff --git a/test/fixtures/test-runner/output/abort.js b/test/fixtures/test-runner/output/abort.js index 0cd9c9b9273503..eba48d9ec58718 100644 --- a/test/fixtures/test-runner/output/abort.js +++ b/test/fixtures/test-runner/output/abort.js @@ -1,4 +1,3 @@ -// Flags: --no-warnings 'use strict'; require('../../../common'); const test = require('node:test'); diff --git a/test/fixtures/test-runner/output/abort.snapshot b/test/fixtures/test-runner/output/abort.snapshot index f756377172da65..1b758a2314c486 100644 --- a/test/fixtures/test-runner/output/abort.snapshot +++ b/test/fixtures/test-runner/output/abort.snapshot @@ -24,6 +24,7 @@ TAP version 13 not ok 5 - not ok 1 --- duration_ms: * + location: '/test/fixtures/test-runner/output/abort.js:(LINE):7' failureType: 'cancelledByParent' error: 'test did not finish before its parent and was cancelled' code: 'ERR_TEST_FAILURE' @@ -31,7 +32,8 @@ TAP version 13 # Subtest: not ok 2 not ok 6 - not ok 2 --- - duration_ms: ZERO + duration_ms: * + location: '/test/fixtures/test-runner/output/abort.js:(LINE):7' failureType: 'cancelledByParent' error: 'test did not finish before its parent and was cancelled' code: 'ERR_TEST_FAILURE' @@ -39,7 +41,8 @@ TAP version 13 # Subtest: not ok 3 not ok 7 - not ok 3 --- - duration_ms: ZERO + duration_ms: * + location: '/test/fixtures/test-runner/output/abort.js:(LINE):7' failureType: 'testAborted' error: 'This operation was aborted' code: 20 @@ -59,7 +62,8 @@ TAP version 13 # Subtest: not ok 4 not ok 8 - not ok 4 --- - duration_ms: ZERO + duration_ms: * + location: '/test/fixtures/test-runner/output/abort.js:(LINE):7' failureType: 'testAborted' error: 'This operation was aborted' code: 20 @@ -79,7 +83,8 @@ TAP version 13 # Subtest: not ok 5 not ok 9 - not ok 5 --- - duration_ms: ZERO + duration_ms: * + location: '/test/fixtures/test-runner/output/abort.js:(LINE):7' failureType: 'testAborted' error: 'This operation was aborted' code: 20 @@ -100,6 +105,7 @@ TAP version 13 not ok 1 - promise timeout signal --- duration_ms: * + location: '/test/fixtures/test-runner/output/abort.js:(LINE):1' failureType: 'testAborted' error: 'The operation was aborted due to timeout' code: 23 @@ -114,6 +120,7 @@ not ok 1 - promise timeout signal not ok 2 - promise abort signal --- duration_ms: * + location: '/test/fixtures/test-runner/output/abort.js:(LINE):1' failureType: 'testAborted' error: 'This operation was aborted' code: 20 @@ -154,6 +161,7 @@ not ok 2 - promise abort signal not ok 5 - not ok 1 --- duration_ms: * + location: '/test/fixtures/test-runner/output/abort.js:(LINE):5' failureType: 'cancelledByParent' error: 'test did not finish before its parent and was cancelled' code: 'ERR_TEST_FAILURE' @@ -161,7 +169,8 @@ not ok 2 - promise abort signal # Subtest: not ok 2 not ok 6 - not ok 2 --- - duration_ms: ZERO + duration_ms: * + location: '/test/fixtures/test-runner/output/abort.js:(LINE):5' failureType: 'cancelledByParent' error: 'test did not finish before its parent and was cancelled' code: 'ERR_TEST_FAILURE' @@ -169,7 +178,8 @@ not ok 2 - promise abort signal # Subtest: not ok 3 not ok 7 - not ok 3 --- - duration_ms: ZERO + duration_ms: * + location: '/test/fixtures/test-runner/output/abort.js:(LINE):5' failureType: 'testAborted' error: 'This operation was aborted' code: 20 @@ -189,7 +199,8 @@ not ok 2 - promise abort signal # Subtest: not ok 4 not ok 8 - not ok 4 --- - duration_ms: ZERO + duration_ms: * + location: '/test/fixtures/test-runner/output/abort.js:(LINE):5' failureType: 'testAborted' error: 'This operation was aborted' code: 20 @@ -209,7 +220,8 @@ not ok 2 - promise abort signal # Subtest: not ok 5 not ok 9 - not ok 5 --- - duration_ms: ZERO + duration_ms: * + location: '/test/fixtures/test-runner/output/abort.js:(LINE):5' failureType: 'testAborted' error: 'This operation was aborted' code: 20 @@ -230,6 +242,7 @@ not ok 2 - promise abort signal not ok 3 - callback timeout signal --- duration_ms: * + location: '/test/fixtures/test-runner/output/abort.js:(LINE):1' failureType: 'testAborted' error: 'The operation was aborted due to timeout' code: 23 @@ -244,6 +257,7 @@ not ok 3 - callback timeout signal not ok 4 - callback abort signal --- duration_ms: * + location: '/test/fixtures/test-runner/output/abort.js:(LINE):1' failureType: 'testAborted' error: 'This operation was aborted' code: 20 diff --git a/test/fixtures/test-runner/output/abort_hooks.js b/test/fixtures/test-runner/output/abort_hooks.js new file mode 100644 index 00000000000000..8395f70e86185e --- /dev/null +++ b/test/fixtures/test-runner/output/abort_hooks.js @@ -0,0 +1,62 @@ +'use strict'; +const { before, beforeEach, describe, it, after, afterEach } = require('node:test'); + +describe('1 before describe', () => { + const ac = new AbortController(); + before(() => { + console.log('before'); + ac.abort() + }, {signal: ac.signal}); + + it('test 1', () => { + console.log('1.1'); + }); + it('test 2', () => { + console.log('1.2'); + }); +}); + +describe('2 after describe', () => { + const ac = new AbortController(); + after(() => { + console.log('after'); + ac.abort() + }, {signal: ac.signal}); + + it('test 1', () => { + console.log('2.1'); + }); + it('test 2', () => { + console.log('2.2'); + }); +}); + +describe('3 beforeEach describe', () => { + const ac = new AbortController(); + beforeEach(() => { + console.log('beforeEach'); + ac.abort() + }, {signal: ac.signal}); + + it('test 1', () => { + console.log('3.1'); + }); + it('test 2', () => { + console.log('3.2'); + }); +}); + +describe('4 afterEach describe', () => { + const ac = new AbortController(); + afterEach(() => { + console.log('afterEach'); + ac.abort() + }, {signal: ac.signal}); + + it('test 1', () => { + console.log('4.1'); + }); + it('test 2', () => { + console.log('4.2'); + }); +}); diff --git a/test/fixtures/test-runner/output/abort_hooks.snapshot b/test/fixtures/test-runner/output/abort_hooks.snapshot new file mode 100644 index 00000000000000..278b5e5fd36ca5 --- /dev/null +++ b/test/fixtures/test-runner/output/abort_hooks.snapshot @@ -0,0 +1,198 @@ +before +2.1 +2.2 +after +beforeEach +4.1 +afterEach +4.2 +TAP version 13 +# Subtest: 1 before describe + # Subtest: test 1 + not ok 1 - test 1 + --- + duration_ms: * + location: '/test/fixtures/test-runner/output/abort_hooks.js:(LINE):3' + failureType: 'cancelledByParent' + error: 'test did not finish before its parent and was cancelled' + code: 'ERR_TEST_FAILURE' + ... + # Subtest: test 2 + not ok 2 - test 2 + --- + duration_ms: * + location: '/test/fixtures/test-runner/output/abort_hooks.js:(LINE):3' + failureType: 'cancelledByParent' + error: 'test did not finish before its parent and was cancelled' + code: 'ERR_TEST_FAILURE' + ... + 1..2 +not ok 1 - 1 before describe + --- + duration_ms: * + type: 'suite' + location: '/test/fixtures/test-runner/output/abort_hooks.js:(LINE):1' + failureType: 'hookFailed' + error: 'This operation was aborted' + code: 20 + name: 'AbortError' + stack: |- + * + * + * + * + * + * + * + * + * + * + ... +# Subtest: 2 after describe + # Subtest: test 1 + ok 1 - test 1 + --- + duration_ms: * + ... + # Subtest: test 2 + ok 2 - test 2 + --- + duration_ms: * + ... + 1..2 +not ok 2 - 2 after describe + --- + duration_ms: * + type: 'suite' + location: '/test/fixtures/test-runner/output/abort_hooks.js:(LINE):1' + failureType: 'hookFailed' + error: 'This operation was aborted' + code: 20 + name: 'AbortError' + stack: |- + * + * + * + * + * + * + * + * + * + * + ... +# Subtest: 3 beforeEach describe + # Subtest: test 1 + not ok 1 - test 1 + --- + duration_ms: * + location: '/test/fixtures/test-runner/output/abort_hooks.js:(LINE):3' + failureType: 'hookFailed' + error: 'This operation was aborted' + code: 20 + name: 'AbortError' + stack: |- + * + * + * + * + * + * + * + * + * + async Promise.all (index 0) + ... + # Subtest: test 2 + not ok 2 - test 2 + --- + duration_ms: * + location: '/test/fixtures/test-runner/output/abort_hooks.js:(LINE):3' + failureType: 'hookFailed' + error: 'This operation was aborted' + code: 20 + name: 'AbortError' + stack: |- + * + * + * + * + * + * + * + * + * + async Promise.all (index 0) + ... + 1..2 +not ok 3 - 3 beforeEach describe + --- + duration_ms: * + type: 'suite' + location: '/test/fixtures/test-runner/output/abort_hooks.js:(LINE):1' + failureType: 'subtestsFailed' + error: '2 subtests failed' + code: 'ERR_TEST_FAILURE' + ... +# Subtest: 4 afterEach describe + # Subtest: test 1 + not ok 1 - test 1 + --- + duration_ms: * + location: '/test/fixtures/test-runner/output/abort_hooks.js:(LINE):3' + failureType: 'hookFailed' + error: 'This operation was aborted' + code: 20 + name: 'AbortError' + stack: |- + * + * + * + * + * + * + * + * + * + * + ... + # Subtest: test 2 + not ok 2 - test 2 + --- + duration_ms: * + location: '/test/fixtures/test-runner/output/abort_hooks.js:(LINE):3' + failureType: 'hookFailed' + error: 'This operation was aborted' + code: 20 + name: 'AbortError' + stack: |- + * + * + * + * + * + * + * + * + * + * + ... + 1..2 +not ok 4 - 4 afterEach describe + --- + duration_ms: * + type: 'suite' + location: '/test/fixtures/test-runner/output/abort_hooks.js:(LINE):1' + failureType: 'subtestsFailed' + error: '2 subtests failed' + code: 'ERR_TEST_FAILURE' + ... +1..4 +# tests 8 +# suites 4 +# pass 2 +# fail 4 +# cancelled 2 +# skipped 0 +# todo 0 +# duration_ms * diff --git a/test/fixtures/test-runner/output/abort_suite.js b/test/fixtures/test-runner/output/abort_suite.js index 419698320a5f7d..8a2a2c05458fd4 100644 --- a/test/fixtures/test-runner/output/abort_suite.js +++ b/test/fixtures/test-runner/output/abort_suite.js @@ -1,4 +1,3 @@ -// Flags: --no-warnings 'use strict'; require('../../../common'); const { describe, it } = require('node:test'); diff --git a/test/fixtures/test-runner/output/abort_suite.snapshot b/test/fixtures/test-runner/output/abort_suite.snapshot index e2abdadaf5a4b7..30d48d236ff4a5 100644 --- a/test/fixtures/test-runner/output/abort_suite.snapshot +++ b/test/fixtures/test-runner/output/abort_suite.snapshot @@ -24,6 +24,7 @@ TAP version 13 not ok 5 - not ok 1 --- duration_ms: * + location: '/test/fixtures/test-runner/output/abort_suite.js:(LINE):3' failureType: 'cancelledByParent' error: 'test did not finish before its parent and was cancelled' code: 'ERR_TEST_FAILURE' @@ -31,7 +32,8 @@ TAP version 13 # Subtest: not ok 2 not ok 6 - not ok 2 --- - duration_ms: ZERO + duration_ms: * + location: '/test/fixtures/test-runner/output/abort_suite.js:(LINE):3' failureType: 'cancelledByParent' error: 'test did not finish before its parent and was cancelled' code: 'ERR_TEST_FAILURE' @@ -39,7 +41,8 @@ TAP version 13 # Subtest: not ok 3 not ok 7 - not ok 3 --- - duration_ms: ZERO + duration_ms: * + location: '/test/fixtures/test-runner/output/abort_suite.js:(LINE):3' failureType: 'testAborted' error: 'This operation was aborted' code: 20 @@ -59,7 +62,8 @@ TAP version 13 # Subtest: not ok 4 not ok 8 - not ok 4 --- - duration_ms: ZERO + duration_ms: * + location: '/test/fixtures/test-runner/output/abort_suite.js:(LINE):3' failureType: 'testAborted' error: 'This operation was aborted' code: 20 @@ -79,7 +83,8 @@ TAP version 13 # Subtest: not ok 5 not ok 9 - not ok 5 --- - duration_ms: ZERO + duration_ms: * + location: '/test/fixtures/test-runner/output/abort_suite.js:(LINE):3' failureType: 'testAborted' error: 'This operation was aborted' code: 20 @@ -101,6 +106,7 @@ not ok 1 - describe timeout signal --- duration_ms: * type: 'suite' + location: '/test/fixtures/test-runner/output/abort_suite.js:(LINE):1' failureType: 'testAborted' error: 'The operation was aborted due to timeout' code: 23 @@ -116,6 +122,7 @@ not ok 2 - describe abort signal --- duration_ms: * type: 'suite' + location: '/test/fixtures/test-runner/output/abort_suite.js:(LINE):1' failureType: 'testAborted' error: 'This operation was aborted' code: 20 diff --git a/test/fixtures/test-runner/output/arbitrary-output.snapshot b/test/fixtures/test-runner/output/arbitrary-output.snapshot index 2389096398cd09..601aaa42f3c74a 100644 --- a/test/fixtures/test-runner/output/arbitrary-output.snapshot +++ b/test/fixtures/test-runner/output/arbitrary-output.snapshot @@ -1,17 +1,17 @@ TAP version 13 ok 1 - test --- - duration_ms: ZERO + duration_ms: * ... # arbitrary - pre ok 2 - test --- - duration_ms: ZERO + duration_ms: * ... # arbitrary - mid ok 3 - test --- - duration_ms: ZERO + duration_ms: * ... # arbitrary - post 1..3 diff --git a/test/fixtures/test-runner/output/async-test-scheduling.mjs b/test/fixtures/test-runner/output/async-test-scheduling.mjs new file mode 100644 index 00000000000000..7c7a9f91208911 --- /dev/null +++ b/test/fixtures/test-runner/output/async-test-scheduling.mjs @@ -0,0 +1,13 @@ +import * as common from '../../../common/index.mjs'; +import { describe, test } from 'node:test'; +import { setTimeout } from 'node:timers/promises'; + +test('test', common.mustCall()); +describe('suite', common.mustCall(async () => { + test('test', common.mustCall()); + await setTimeout(10); + test('scheduled async', common.mustCall()); +})); + +await setTimeout(10); +test('scheduled async', common.mustCall()); diff --git a/test/fixtures/test-runner/output/async-test-scheduling.snapshot b/test/fixtures/test-runner/output/async-test-scheduling.snapshot new file mode 100644 index 00000000000000..64c3004d26881d --- /dev/null +++ b/test/fixtures/test-runner/output/async-test-scheduling.snapshot @@ -0,0 +1,37 @@ +TAP version 13 +# Subtest: test +ok 1 - test + --- + duration_ms: * + ... +# Subtest: suite + # Subtest: test + ok 1 - test + --- + duration_ms: * + ... + # Subtest: scheduled async + ok 2 - scheduled async + --- + duration_ms: * + ... + 1..2 +ok 2 - suite + --- + duration_ms: * + type: 'suite' + ... +# Subtest: scheduled async +ok 3 - scheduled async + --- + duration_ms: * + ... +1..3 +# tests 4 +# suites 1 +# pass 4 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms * diff --git a/test/fixtures/test-runner/output/before-and-after-each-too-many-listeners.js b/test/fixtures/test-runner/output/before-and-after-each-too-many-listeners.js new file mode 100644 index 00000000000000..73857096068f9a --- /dev/null +++ b/test/fixtures/test-runner/output/before-and-after-each-too-many-listeners.js @@ -0,0 +1,8 @@ +'use strict'; +const { beforeEach, afterEach, test} = require("node:test"); +beforeEach(() => {}); +afterEach(() => {}); + +for (let i = 1; i <= 11; ++i) { + test(`${i}`, () => {}); +} diff --git a/test/fixtures/test-runner/output/before-and-after-each-too-many-listeners.snapshot b/test/fixtures/test-runner/output/before-and-after-each-too-many-listeners.snapshot new file mode 100644 index 00000000000000..4300e21a26403f --- /dev/null +++ b/test/fixtures/test-runner/output/before-and-after-each-too-many-listeners.snapshot @@ -0,0 +1,65 @@ +TAP version 13 +# Subtest: 1 +ok 1 - 1 + --- + duration_ms: * + ... +# Subtest: 2 +ok 2 - 2 + --- + duration_ms: * + ... +# Subtest: 3 +ok 3 - 3 + --- + duration_ms: * + ... +# Subtest: 4 +ok 4 - 4 + --- + duration_ms: * + ... +# Subtest: 5 +ok 5 - 5 + --- + duration_ms: * + ... +# Subtest: 6 +ok 6 - 6 + --- + duration_ms: * + ... +# Subtest: 7 +ok 7 - 7 + --- + duration_ms: * + ... +# Subtest: 8 +ok 8 - 8 + --- + duration_ms: * + ... +# Subtest: 9 +ok 9 - 9 + --- + duration_ms: * + ... +# Subtest: 10 +ok 10 - 10 + --- + duration_ms: * + ... +# Subtest: 11 +ok 11 - 11 + --- + duration_ms: * + ... +1..11 +# tests 11 +# suites 0 +# pass 11 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms * diff --git a/test/fixtures/test-runner/output/before-and-after-each-with-timeout-too-many-listeners.js b/test/fixtures/test-runner/output/before-and-after-each-with-timeout-too-many-listeners.js new file mode 100644 index 00000000000000..87d645d6b0fa82 --- /dev/null +++ b/test/fixtures/test-runner/output/before-and-after-each-with-timeout-too-many-listeners.js @@ -0,0 +1,8 @@ +'use strict'; +const { beforeEach, afterEach, test} = require("node:test"); +beforeEach(() => {}, {timeout: 10000}); +afterEach(() => {}, {timeout: 10000}); + +for (let i = 1; i <= 11; ++i) { + test(`${i}`, () => {}); +} diff --git a/test/fixtures/test-runner/output/before-and-after-each-with-timeout-too-many-listeners.snapshot b/test/fixtures/test-runner/output/before-and-after-each-with-timeout-too-many-listeners.snapshot new file mode 100644 index 00000000000000..4300e21a26403f --- /dev/null +++ b/test/fixtures/test-runner/output/before-and-after-each-with-timeout-too-many-listeners.snapshot @@ -0,0 +1,65 @@ +TAP version 13 +# Subtest: 1 +ok 1 - 1 + --- + duration_ms: * + ... +# Subtest: 2 +ok 2 - 2 + --- + duration_ms: * + ... +# Subtest: 3 +ok 3 - 3 + --- + duration_ms: * + ... +# Subtest: 4 +ok 4 - 4 + --- + duration_ms: * + ... +# Subtest: 5 +ok 5 - 5 + --- + duration_ms: * + ... +# Subtest: 6 +ok 6 - 6 + --- + duration_ms: * + ... +# Subtest: 7 +ok 7 - 7 + --- + duration_ms: * + ... +# Subtest: 8 +ok 8 - 8 + --- + duration_ms: * + ... +# Subtest: 9 +ok 9 - 9 + --- + duration_ms: * + ... +# Subtest: 10 +ok 10 - 10 + --- + duration_ms: * + ... +# Subtest: 11 +ok 11 - 11 + --- + duration_ms: * + ... +1..11 +# tests 11 +# suites 0 +# pass 11 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms * diff --git a/test/fixtures/test-runner/output/coverage_failure.js b/test/fixtures/test-runner/output/coverage_failure.js new file mode 100644 index 00000000000000..6c4d25ce081cad --- /dev/null +++ b/test/fixtures/test-runner/output/coverage_failure.js @@ -0,0 +1,13 @@ +// Flags: --expose-internals --experimental-test-coverage + +'use strict'; +require('../../../common'); +const { TestCoverage } = require('internal/test_runner/coverage'); +const { test, mock } = require('node:test'); + +mock.method(TestCoverage.prototype, 'summary', () => { + throw new Error('Failed to collect coverage'); +}); + +test('ok'); + diff --git a/test/fixtures/test-runner/output/coverage_failure.snapshot b/test/fixtures/test-runner/output/coverage_failure.snapshot new file mode 100644 index 00000000000000..62f39ebede943a --- /dev/null +++ b/test/fixtures/test-runner/output/coverage_failure.snapshot @@ -0,0 +1,16 @@ +TAP version 13 +# Subtest: ok +ok 1 - ok + --- + duration_ms: * + ... +1..1 +# Warning: Could not report code coverage. Error: Failed to collect coverage +# tests 1 +# suites 0 +# pass 1 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms * diff --git a/test/fixtures/test-runner/output/default_output.snapshot b/test/fixtures/test-runner/output/default_output.snapshot index dca844bb8402aa..b003f9299c4418 100644 --- a/test/fixtures/test-runner/output/default_output.snapshot +++ b/test/fixtures/test-runner/output/default_output.snapshot @@ -35,6 +35,7 @@ [31m✖ failing tests:[39m +* [31m✖ should fail [90m(*ms)[39m[39m Error: fail *[39m @@ -45,6 +46,7 @@ *[39m *[39m +* [31m✖ should fail [90m(*ms)[39m[39m Error: fail *[39m @@ -53,5 +55,6 @@ *[39m *[39m +* [31m✖ should pass but parent fail [90m(*ms)[39m[39m [32m'test did not finish before its parent and was cancelled'[39m diff --git a/test/fixtures/test-runner/output/describe_it.js b/test/fixtures/test-runner/output/describe_it.js index c6d3f9c1b72fb3..ba6a1aed064614 100644 --- a/test/fixtures/test-runner/output/describe_it.js +++ b/test/fixtures/test-runner/output/describe_it.js @@ -1,4 +1,3 @@ -// Flags: --no-warnings 'use strict'; require('../../../common'); const assert = require('node:assert'); @@ -13,12 +12,12 @@ it.todo('sync pass todo', () => { it('sync pass todo with message', { todo: 'this is a passing todo' }, () => { }); -it.todo('sync fail todo', () => { - throw new Error('thrown from sync fail todo'); +it.todo('sync todo', () => { + throw new Error('should not count as a failure'); }); -it('sync fail todo with message', { todo: 'this is a failing todo' }, () => { - throw new Error('thrown from sync fail todo with message'); +it('sync todo with message', { todo: 'this is a failing todo' }, () => { + throw new Error('should not count as a failure'); }); it.skip('sync skip pass', () => { @@ -197,15 +196,6 @@ it('test with a name and options provided', { skip: true }); // A test with only options and a function provided. it({ skip: true }, function functionAndOptions() {}); -// A test whose description needs to be escaped. -it('escaped description \\ # \\#\\'); - -// A test whose skip message needs to be escaped. -it('escaped skip message', { skip: '#skip' }); - -// A test whose todo message needs to be escaped. -it('escaped todo message', { todo: '#todo' }); - it('callback pass', (t, done) => { setImmediate(done); }); @@ -375,3 +365,22 @@ describe('rejected thenable', () => { }, }; }); + +describe("async describe function", async () => { + await null; + + await it("it inside describe 1", async () => { + await null + }); + await it("it inside describe 2", async () => { + await null; + }); + + describe("inner describe", async () => { + await null; + + it("it inside inner describe", async () => { + await null; + }); + }); +}); diff --git a/test/fixtures/test-runner/output/describe_it.snapshot b/test/fixtures/test-runner/output/describe_it.snapshot index e085ff9535ec70..1d4f7853ead0d1 100644 --- a/test/fixtures/test-runner/output/describe_it.snapshot +++ b/test/fixtures/test-runner/output/describe_it.snapshot @@ -9,12 +9,13 @@ ok 2 - sync pass todo with message # TODO this is a passing todo --- duration_ms: * ... -# Subtest: sync fail todo -not ok 3 - sync fail todo # TODO +# Subtest: sync todo +not ok 3 - sync todo # TODO --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):4' failureType: 'testCodeFailure' - error: 'thrown from sync fail todo' + error: 'should not count as a failure' code: 'ERR_TEST_FAILURE' stack: |- * @@ -25,12 +26,13 @@ not ok 3 - sync fail todo # TODO * * ... -# Subtest: sync fail todo with message -not ok 4 - sync fail todo with message # TODO this is a failing todo +# Subtest: sync todo with message +not ok 4 - sync todo with message # TODO this is a failing todo --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'testCodeFailure' - error: 'thrown from sync fail todo with message' + error: 'should not count as a failure' code: 'ERR_TEST_FAILURE' stack: |- * @@ -60,6 +62,7 @@ ok 7 - sync pass not ok 8 - sync throw fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'testCodeFailure' error: 'thrown from sync throw fail' code: 'ERR_TEST_FAILURE' @@ -91,6 +94,7 @@ ok 11 - mixing describe/it and test should work not ok 12 - async throw fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'testCodeFailure' error: 'thrown from async throw fail' code: 'ERR_TEST_FAILURE' @@ -107,6 +111,7 @@ not ok 12 - async throw fail not ok 13 - async skip fail # SKIP --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'callbackAndPromisePresent' error: 'passed a callback but also returned a Promise' code: 'ERR_TEST_FAILURE' @@ -115,6 +120,7 @@ not ok 13 - async skip fail # SKIP not ok 14 - async assertion fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'testCodeFailure' error: |- Expected values to be strictly equal: @@ -144,6 +150,7 @@ ok 15 - resolve pass not ok 16 - reject fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'testCodeFailure' error: 'rejected from reject fail' code: 'ERR_TEST_FAILURE' @@ -186,6 +193,7 @@ ok 21 - immediate resolve pass not ok 1 - +sync throw fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):3' failureType: 'testCodeFailure' error: 'thrown from subtest sync throw fail' code: 'ERR_TEST_FAILURE' @@ -211,6 +219,7 @@ not ok 22 - subtest sync throw fail --- duration_ms: * type: 'suite' + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'subtestsFailed' error: '1 subtest failed' code: 'ERR_TEST_FAILURE' @@ -219,6 +228,7 @@ not ok 22 - subtest sync throw fail not ok 23 - sync throw non-error fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'testCodeFailure' error: 'Symbol(thrown symbol from sync throw non-error fail)' code: 'ERR_TEST_FAILURE' @@ -270,6 +280,7 @@ ok 27 - sync skip option with message # SKIP this is skipped not ok 28 - sync skip option is false fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'testCodeFailure' error: 'this should be executed' code: 'ERR_TEST_FAILURE' @@ -322,30 +333,16 @@ ok 36 - functionAndOptions # SKIP --- duration_ms: * ... -# Subtest: escaped description \\ \# \\\#\\ -ok 37 - escaped description \\ \# \\\#\\ - --- - duration_ms: * - ... -# Subtest: escaped skip message -ok 38 - escaped skip message # SKIP \#skip - --- - duration_ms: * - ... -# Subtest: escaped todo message -ok 39 - escaped todo message # TODO \#todo - --- - duration_ms: * - ... # Subtest: callback pass -ok 40 - callback pass +ok 37 - callback pass --- duration_ms: * ... # Subtest: callback fail -not ok 41 - callback fail +not ok 38 - callback fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'testCodeFailure' error: 'callback failure' code: 'ERR_TEST_FAILURE' @@ -354,32 +351,34 @@ not ok 41 - callback fail * ... # Subtest: sync t is this in test -ok 42 - sync t is this in test +ok 39 - sync t is this in test --- duration_ms: * ... # Subtest: async t is this in test -ok 43 - async t is this in test +ok 40 - async t is this in test --- duration_ms: * ... # Subtest: callback t is this in test -ok 44 - callback t is this in test +ok 41 - callback t is this in test --- duration_ms: * ... # Subtest: callback also returns a Promise -not ok 45 - callback also returns a Promise +not ok 42 - callback also returns a Promise --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'callbackAndPromisePresent' error: 'passed a callback but also returned a Promise' code: 'ERR_TEST_FAILURE' ... # Subtest: callback throw -not ok 46 - callback throw +not ok 43 - callback throw --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'testCodeFailure' error: 'thrown from callback throw' code: 'ERR_TEST_FAILURE' @@ -393,9 +392,10 @@ not ok 46 - callback throw * ... # Subtest: callback called twice -not ok 47 - callback called twice +not ok 44 - callback called twice --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'multipleCallbackInvocations' error: 'callback invoked multiple times' code: 'ERR_TEST_FAILURE' @@ -404,14 +404,15 @@ not ok 47 - callback called twice * ... # Subtest: callback called twice in different ticks -ok 48 - callback called twice in different ticks +ok 45 - callback called twice in different ticks --- duration_ms: * ... # Subtest: callback called twice in future tick -not ok 49 - callback called twice in future tick +not ok 46 - callback called twice in future tick --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'uncaughtException' error: 'callback invoked multiple times' code: 'ERR_TEST_FAILURE' @@ -419,9 +420,10 @@ not ok 49 - callback called twice in future tick * ... # Subtest: callback async throw -not ok 50 - callback async throw +not ok 47 - callback async throw --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'uncaughtException' error: 'thrown from callback async throw' code: 'ERR_TEST_FAILURE' @@ -430,22 +432,24 @@ not ok 50 - callback async throw * ... # Subtest: callback async throw after done -ok 51 - callback async throw after done +ok 48 - callback async throw after done --- duration_ms: * ... # Subtest: custom inspect symbol fail -not ok 52 - custom inspect symbol fail +not ok 49 - custom inspect symbol fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'testCodeFailure' error: 'customized' code: 'ERR_TEST_FAILURE' ... # Subtest: custom inspect symbol that throws fail -not ok 53 - custom inspect symbol that throws fail +not ok 50 - custom inspect symbol that throws fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'testCodeFailure' error: |- { @@ -459,6 +463,7 @@ not ok 53 - custom inspect symbol that throws fail not ok 1 - sync throw fails at first --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):3' failureType: 'testCodeFailure' error: 'thrown from subtest sync throw fails at first' code: 'ERR_TEST_FAILURE' @@ -478,6 +483,7 @@ not ok 53 - custom inspect symbol that throws fail not ok 2 - sync throw fails at second --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):3' failureType: 'testCodeFailure' error: 'thrown from subtest sync throw fails at second' code: 'ERR_TEST_FAILURE' @@ -494,10 +500,11 @@ not ok 53 - custom inspect symbol that throws fail async Promise.all (index 0) ... 1..2 -not ok 54 - subtest sync throw fails +not ok 51 - subtest sync throw fails --- duration_ms: * type: 'suite' + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'subtestsFailed' error: '2 subtests failed' code: 'ERR_TEST_FAILURE' @@ -506,16 +513,18 @@ not ok 54 - subtest sync throw fails # Subtest: should not run not ok 1 - should not run --- - duration_ms: ZERO + duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):3' failureType: 'cancelledByParent' error: 'test did not finish before its parent and was cancelled' code: 'ERR_TEST_FAILURE' ... 1..1 -not ok 55 - describe sync throw fails +not ok 52 - describe sync throw fails --- duration_ms: * type: 'suite' + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'testCodeFailure' error: 'thrown from describe' code: 'ERR_TEST_FAILURE' @@ -535,16 +544,18 @@ not ok 55 - describe sync throw fails # Subtest: should not run not ok 1 - should not run --- - duration_ms: ZERO + duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):3' failureType: 'cancelledByParent' error: 'test did not finish before its parent and was cancelled' code: 'ERR_TEST_FAILURE' ... 1..1 -not ok 56 - describe async throw fails +not ok 53 - describe async throw fails --- duration_ms: * type: 'suite' + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'testCodeFailure' error: 'thrown from describe' code: 'ERR_TEST_FAILURE' @@ -565,6 +576,7 @@ not ok 56 - describe async throw fails not ok 1 - timed out async test --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):3' failureType: 'testTimeoutFailure' error: 'test timed out after 5ms' code: 'ERR_TEST_FAILURE' @@ -575,6 +587,7 @@ not ok 56 - describe async throw fails not ok 2 - timed out callback test --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):3' failureType: 'testTimeoutFailure' error: 'test timed out after 5ms' code: 'ERR_TEST_FAILURE' @@ -590,10 +603,11 @@ not ok 56 - describe async throw fails duration_ms: * ... 1..4 -not ok 57 - timeouts +not ok 54 - timeouts --- duration_ms: * type: 'suite' + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'subtestsFailed' error: '2 subtests failed' code: 'ERR_TEST_FAILURE' @@ -608,6 +622,7 @@ not ok 57 - timeouts not ok 2 - rejected thenable --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):3' failureType: 'testCodeFailure' error: 'custom error' code: 'ERR_TEST_FAILURE' @@ -616,36 +631,68 @@ not ok 57 - timeouts * ... 1..2 -not ok 58 - successful thenable +not ok 55 - successful thenable --- duration_ms: * type: 'suite' + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'subtestsFailed' error: '1 subtest failed' code: 'ERR_TEST_FAILURE' ... # Subtest: rejected thenable -not ok 59 - rejected thenable +not ok 56 - rejected thenable --- duration_ms: * type: 'suite' + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):1' failureType: 'testCodeFailure' error: 'custom error' code: 'ERR_TEST_FAILURE' stack: |- * ... +# Subtest: async describe function + # Subtest: it inside describe 1 + ok 1 - it inside describe 1 + --- + duration_ms: * + ... + # Subtest: it inside describe 2 + ok 2 - it inside describe 2 + --- + duration_ms: * + ... + # Subtest: inner describe + # Subtest: it inside inner describe + ok 1 - it inside inner describe + --- + duration_ms: * + ... + 1..1 + ok 3 - inner describe + --- + duration_ms: * + type: 'suite' + ... + 1..3 +ok 57 - async describe function + --- + duration_ms: * + type: 'suite' + ... # Subtest: invalid subtest fail -not ok 60 - invalid subtest fail +not ok 58 - invalid subtest fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/describe_it.js:(LINE):5' failureType: 'parentAlreadyFinished' error: 'test could not be started because its parent finished' code: 'ERR_TEST_FAILURE' stack: |- * ... -1..60 +1..58 # Warning: Test "unhandled rejection - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: rejected from unhandled rejection fail" and would have caused the test to fail, but instead triggered an unhandledRejection event. # Warning: Test "async unhandled rejection - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: rejected from async unhandled rejection fail" and would have caused the test to fail, but instead triggered an unhandledRejection event. # Warning: Test "immediate throw - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: thrown from immediate throw fail" and would have caused the test to fail, but instead triggered an uncaughtException event. @@ -653,10 +700,10 @@ not ok 60 - invalid subtest fail # Warning: Test "callback called twice in different ticks" generated asynchronous activity after the test ended. This activity created the error "Error [ERR_TEST_FAILURE]: callback invoked multiple times" and would have caused the test to fail, but instead triggered an uncaughtException event. # Warning: Test "callback async throw after done" generated asynchronous activity after the test ended. This activity created the error "Error: thrown from callback async throw after done" and would have caused the test to fail, but instead triggered an uncaughtException event. # tests 67 -# suites 9 -# pass 29 +# suites 11 +# pass 31 # fail 19 # cancelled 4 -# skipped 10 -# todo 5 +# skipped 9 +# todo 4 # duration_ms * diff --git a/test/fixtures/test-runner/output/describe_nested.js b/test/fixtures/test-runner/output/describe_nested.js index 40ea150a018f3d..3cd4dcbb06c849 100644 --- a/test/fixtures/test-runner/output/describe_nested.js +++ b/test/fixtures/test-runner/output/describe_nested.js @@ -1,4 +1,3 @@ -// Flags: --no-warnings 'use strict'; require('../../../common'); const { describe, it } = require('node:test'); diff --git a/test/fixtures/test-runner/output/dot_reporter.js b/test/fixtures/test-runner/output/dot_reporter.js index 72a8aaa10e491b..e9b8f5cead88f0 100644 --- a/test/fixtures/test-runner/output/dot_reporter.js +++ b/test/fixtures/test-runner/output/dot_reporter.js @@ -1,4 +1,3 @@ -// Flags: --no-warnings 'use strict'; require('../../../common'); const fixtures = require('../../../common/fixtures'); diff --git a/test/fixtures/test-runner/output/dot_reporter.snapshot b/test/fixtures/test-runner/output/dot_reporter.snapshot index 5a74119b3887e5..7c6b0ff2356b77 100644 --- a/test/fixtures/test-runner/output/dot_reporter.snapshot +++ b/test/fixtures/test-runner/output/dot_reporter.snapshot @@ -1,5 +1,4 @@ ..XX...X..XXX.X..... XXX.....X..X...X.... -.........X...XXX.XX. -.....XXXXXXX...XXXXX - +.....X...XXX.XX..... +.XXXXXXX...XXXXX diff --git a/test/fixtures/test-runner/output/global_after_should_fail_the_test.js b/test/fixtures/test-runner/output/global_after_should_fail_the_test.js new file mode 100644 index 00000000000000..e2ad4c815b7fcd --- /dev/null +++ b/test/fixtures/test-runner/output/global_after_should_fail_the_test.js @@ -0,0 +1,10 @@ +'use strict'; +const { it, after } = require('node:test'); + +after(() => { + throw new Error('this should fail the test') +}); + +it('this is a test', () => { + console.log('this is a test') +}); diff --git a/test/fixtures/test-runner/output/global_after_should_fail_the_test.snapshot b/test/fixtures/test-runner/output/global_after_should_fail_the_test.snapshot new file mode 100644 index 00000000000000..3196f377b3d4bf --- /dev/null +++ b/test/fixtures/test-runner/output/global_after_should_fail_the_test.snapshot @@ -0,0 +1,34 @@ +this is a test +TAP version 13 +# Subtest: this is a test +ok 1 - this is a test + --- + duration_ms: * + ... +not ok 2 - /test/fixtures/test-runner/output/global_after_should_fail_the_test.js + --- + duration_ms: * + location: '/test/fixtures/test-runner/output/global_after_should_fail_the_test.js:(LINE):1' + failureType: 'hookFailed' + error: 'this should fail the test' + code: 'ERR_TEST_FAILURE' + stack: |- + * + * + * + * + * + * + * + * + * + ... +1..1 +# tests 1 +# suites 0 +# pass 1 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms * diff --git a/test/fixtures/test-runner/output/hooks-with-no-global-test.js b/test/fixtures/test-runner/output/hooks-with-no-global-test.js new file mode 100644 index 00000000000000..ea01463fd6cc1f --- /dev/null +++ b/test/fixtures/test-runner/output/hooks-with-no-global-test.js @@ -0,0 +1,78 @@ +'use strict'; +const { test, describe, it, before, after, beforeEach, afterEach } = require('node:test'); +const assert = require("assert"); + +// This file should not have any global tests to reproduce bug #48844 +const testArr = []; + +before(() => testArr.push('global before')); +after(() => { + testArr.push('global after'); + + assert.deepStrictEqual(testArr, [ + 'global before', + 'describe before', + + 'describe beforeEach', + 'describe it 1', + 'describe afterEach', + + 'describe beforeEach', + 'describe test 2', + 'describe afterEach', + + 'describe nested before', + + 'describe beforeEach', + 'describe nested beforeEach', + 'describe nested it 1', + 'describe afterEach', + 'describe nested afterEach', + + 'describe beforeEach', + 'describe nested beforeEach', + 'describe nested test 2', + 'describe afterEach', + 'describe nested afterEach', + + 'describe nested after', + 'describe after', + 'global after', + ]); +}); + +describe('describe hooks with no global tests', () => { + before(() => { + testArr.push('describe before'); + }); + after(()=> { + testArr.push('describe after'); + }); + beforeEach(() => { + testArr.push('describe beforeEach'); + }); + afterEach(() => { + testArr.push('describe afterEach'); + }); + + it('1', () => testArr.push('describe it 1')); + test('2', () => testArr.push('describe test 2')); + + describe('nested', () => { + before(() => { + testArr.push('describe nested before') + }); + after(() => { + testArr.push('describe nested after') + }); + beforeEach(() => { + testArr.push('describe nested beforeEach') + }); + afterEach(() => { + testArr.push('describe nested afterEach') + }); + + it('nested 1', () => testArr.push('describe nested it 1')); + test('nested 2', () => testArr.push('describe nested test 2')); + }); +}); diff --git a/test/fixtures/test-runner/output/hooks-with-no-global-test.snapshot b/test/fixtures/test-runner/output/hooks-with-no-global-test.snapshot new file mode 100644 index 00000000000000..722a3a4ca2ceac --- /dev/null +++ b/test/fixtures/test-runner/output/hooks-with-no-global-test.snapshot @@ -0,0 +1,44 @@ +TAP version 13 +# Subtest: describe hooks with no global tests + # Subtest: 1 + ok 1 - 1 + --- + duration_ms: * + ... + # Subtest: 2 + ok 2 - 2 + --- + duration_ms: * + ... + # Subtest: nested + # Subtest: nested 1 + ok 1 - nested 1 + --- + duration_ms: * + ... + # Subtest: nested 2 + ok 2 - nested 2 + --- + duration_ms: * + ... + 1..2 + ok 3 - nested + --- + duration_ms: * + type: 'suite' + ... + 1..3 +ok 1 - describe hooks with no global tests + --- + duration_ms: * + type: 'suite' + ... +1..1 +# tests 4 +# suites 2 +# pass 4 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms * diff --git a/test/fixtures/test-runner/output/hooks.js b/test/fixtures/test-runner/output/hooks.js index 827da5d5646262..00a6c23499f52e 100644 --- a/test/fixtures/test-runner/output/hooks.js +++ b/test/fixtures/test-runner/output/hooks.js @@ -1,4 +1,3 @@ -// Flags: --no-warnings 'use strict'; const common = require('../../../common'); const assert = require('assert'); diff --git a/test/fixtures/test-runner/output/hooks.snapshot b/test/fixtures/test-runner/output/hooks.snapshot index 5b16957ba24dc6..6cf29612c535cb 100644 --- a/test/fixtures/test-runner/output/hooks.snapshot +++ b/test/fixtures/test-runner/output/hooks.snapshot @@ -37,7 +37,8 @@ ok 1 - describe hooks # Subtest: 1 not ok 1 - 1 --- - duration_ms: ZERO + duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):3' failureType: 'cancelledByParent' error: 'test did not finish before its parent and was cancelled' code: 'ERR_TEST_FAILURE' @@ -45,7 +46,8 @@ ok 1 - describe hooks # Subtest: 2 not ok 2 - 2 --- - duration_ms: ZERO + duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):3' failureType: 'cancelledByParent' error: 'test did not finish before its parent and was cancelled' code: 'ERR_TEST_FAILURE' @@ -55,8 +57,9 @@ not ok 2 - before throws --- duration_ms: * type: 'suite' + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):1' failureType: 'hookFailed' - error: 'failed running before hook' + error: 'before' code: 'ERR_TEST_FAILURE' stack: |- * @@ -85,8 +88,9 @@ not ok 3 - after throws --- duration_ms: * type: 'suite' + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):1' failureType: 'hookFailed' - error: 'failed running after hook' + error: 'after' code: 'ERR_TEST_FAILURE' stack: |- * @@ -104,8 +108,9 @@ not ok 3 - after throws not ok 1 - 1 --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):3' failureType: 'hookFailed' - error: 'failed running beforeEach hook' + error: 'beforeEach' code: 'ERR_TEST_FAILURE' stack: |- * @@ -123,8 +128,9 @@ not ok 3 - after throws not ok 2 - 2 --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):3' failureType: 'hookFailed' - error: 'failed running beforeEach hook' + error: 'beforeEach' code: 'ERR_TEST_FAILURE' stack: |- * @@ -134,8 +140,6 @@ not ok 3 - after throws * * * - async Promise.all (index 0) - * * ... 1..2 @@ -143,6 +147,7 @@ not ok 4 - beforeEach throws --- duration_ms: * type: 'suite' + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):1' failureType: 'subtestsFailed' error: '2 subtests failed' code: 'ERR_TEST_FAILURE' @@ -152,8 +157,9 @@ not ok 4 - beforeEach throws not ok 1 - 1 --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):3' failureType: 'hookFailed' - error: 'failed running afterEach hook' + error: 'afterEach' code: 'ERR_TEST_FAILURE' stack: |- * @@ -171,8 +177,9 @@ not ok 4 - beforeEach throws not ok 2 - 2 --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):3' failureType: 'hookFailed' - error: 'failed running afterEach hook' + error: 'afterEach' code: 'ERR_TEST_FAILURE' stack: |- * @@ -183,7 +190,6 @@ not ok 4 - beforeEach throws * * * - async Promise.all (index 0) * ... 1..2 @@ -191,6 +197,7 @@ not ok 5 - afterEach throws --- duration_ms: * type: 'suite' + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):1' failureType: 'subtestsFailed' error: '2 subtests failed' code: 'ERR_TEST_FAILURE' @@ -200,6 +207,7 @@ not ok 5 - afterEach throws not ok 1 - 1 --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):3' failureType: 'testCodeFailure' error: 'test' code: 'ERR_TEST_FAILURE' @@ -225,6 +233,7 @@ not ok 6 - afterEach when test fails --- duration_ms: * type: 'suite' + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):1' failureType: 'subtestsFailed' error: '1 subtest failed' code: 'ERR_TEST_FAILURE' @@ -234,6 +243,7 @@ not ok 6 - afterEach when test fails not ok 1 - 1 --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):3' failureType: 'testCodeFailure' error: 'test' code: 'ERR_TEST_FAILURE' @@ -253,8 +263,9 @@ not ok 6 - afterEach when test fails not ok 2 - 2 --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):3' failureType: 'hookFailed' - error: 'failed running afterEach hook' + error: 'afterEach' code: 'ERR_TEST_FAILURE' stack: |- * @@ -265,7 +276,6 @@ not ok 6 - afterEach when test fails * * * - async Promise.all (index 0) * ... 1..2 @@ -273,6 +283,7 @@ not ok 7 - afterEach throws and test fails --- duration_ms: * type: 'suite' + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):1' failureType: 'subtestsFailed' error: '2 subtests failed' code: 'ERR_TEST_FAILURE' @@ -314,8 +325,9 @@ ok 8 - test hooks not ok 1 - 1 --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):11' failureType: 'hookFailed' - error: 'failed running before hook' + error: 'before' code: 'ERR_TEST_FAILURE' stack: |- * @@ -333,8 +345,9 @@ ok 8 - test hooks not ok 2 - 2 --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):11' failureType: 'hookFailed' - error: 'failed running before hook' + error: 'before' code: 'ERR_TEST_FAILURE' stack: |- * @@ -352,6 +365,7 @@ ok 8 - test hooks not ok 9 - t.before throws --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):1' failureType: 'subtestsFailed' error: '2 subtests failed' code: 'ERR_TEST_FAILURE' @@ -361,8 +375,9 @@ not ok 9 - t.before throws not ok 1 - 1 --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):11' failureType: 'hookFailed' - error: 'failed running beforeEach hook' + error: 'beforeEach' code: 'ERR_TEST_FAILURE' stack: |- * @@ -380,8 +395,9 @@ not ok 9 - t.before throws not ok 2 - 2 --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):11' failureType: 'hookFailed' - error: 'failed running beforeEach hook' + error: 'beforeEach' code: 'ERR_TEST_FAILURE' stack: |- * @@ -399,6 +415,7 @@ not ok 9 - t.before throws not ok 10 - t.beforeEach throws --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):1' failureType: 'subtestsFailed' error: '2 subtests failed' code: 'ERR_TEST_FAILURE' @@ -408,8 +425,9 @@ not ok 10 - t.beforeEach throws not ok 1 - 1 --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):11' failureType: 'hookFailed' - error: 'failed running afterEach hook' + error: 'afterEach' code: 'ERR_TEST_FAILURE' stack: |- * @@ -427,8 +445,9 @@ not ok 10 - t.beforeEach throws not ok 2 - 2 --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):11' failureType: 'hookFailed' - error: 'failed running afterEach hook' + error: 'afterEach' code: 'ERR_TEST_FAILURE' stack: |- * @@ -446,6 +465,7 @@ not ok 10 - t.beforeEach throws not ok 11 - t.afterEach throws --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):1' failureType: 'subtestsFailed' error: '2 subtests failed' code: 'ERR_TEST_FAILURE' @@ -455,6 +475,7 @@ not ok 11 - t.afterEach throws not ok 1 - 1 --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):11' failureType: 'testCodeFailure' error: 'test' code: 'ERR_TEST_FAILURE' @@ -478,6 +499,7 @@ not ok 11 - t.afterEach throws not ok 12 - afterEach when test fails --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):1' failureType: 'subtestsFailed' error: '1 subtest failed' code: 'ERR_TEST_FAILURE' @@ -487,6 +509,7 @@ not ok 12 - afterEach when test fails not ok 1 - 1 --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):11' failureType: 'testCodeFailure' error: 'test' code: 'ERR_TEST_FAILURE' @@ -505,8 +528,9 @@ not ok 12 - afterEach when test fails not ok 2 - 2 --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):11' failureType: 'hookFailed' - error: 'failed running afterEach hook' + error: 'afterEach' code: 'ERR_TEST_FAILURE' stack: |- * @@ -524,6 +548,7 @@ not ok 12 - afterEach when test fails not ok 13 - afterEach throws and test fails --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):1' failureType: 'subtestsFailed' error: '2 subtests failed' code: 'ERR_TEST_FAILURE' @@ -532,6 +557,7 @@ not ok 13 - afterEach throws and test fails not ok 14 - t.after() is called if test body throws --- duration_ms: * + location: '/test/fixtures/test-runner/output/hooks.js:(LINE):1' failureType: 'testCodeFailure' error: 'bye' code: 'ERR_TEST_FAILURE' diff --git a/test/fixtures/test-runner/output/junit_reporter.js b/test/fixtures/test-runner/output/junit_reporter.js new file mode 100644 index 00000000000000..1f49b3f6042d97 --- /dev/null +++ b/test/fixtures/test-runner/output/junit_reporter.js @@ -0,0 +1,7 @@ +'use strict'; +require('../../../common'); +const fixtures = require('../../../common/fixtures'); +const spawn = require('node:child_process').spawn; + +spawn(process.execPath, + ['--no-warnings', '--test-reporter', 'junit', fixtures.path('test-runner/output/output.js')], { stdio: 'inherit' }); diff --git a/test/fixtures/test-runner/output/junit_reporter.snapshot b/test/fixtures/test-runner/output/junit_reporter.snapshot new file mode 100644 index 00000000000000..b21a1b9ed183fd --- /dev/null +++ b/test/fixtures/test-runner/output/junit_reporter.snapshot @@ -0,0 +1,488 @@ + + + + + + + + + + + +[Error [ERR_TEST_FAILURE]: thrown from sync fail todo] { + failureType: 'testCodeFailure', + cause: Error: thrown from sync fail todo + * + * + * + * + * + * + at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), + code: 'ERR_TEST_FAILURE' +} + + + + + +[Error [ERR_TEST_FAILURE]: thrown from sync fail todo with message] { + failureType: 'testCodeFailure', + cause: Error: thrown from sync fail todo with message + * + * + * + * + * + * + at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), + code: 'ERR_TEST_FAILURE' +} + + + + + + + + + + + + +[Error [ERR_TEST_FAILURE]: thrown from sync throw fail] { + failureType: 'testCodeFailure', + cause: Error: thrown from sync throw fail + * + * + * + * + * + * + at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), + code: 'ERR_TEST_FAILURE' +} + + + + + + + + +[Error [ERR_TEST_FAILURE]: thrown from async throw fail] { + failureType: 'testCodeFailure', + cause: Error: thrown from async throw fail + * + * + * + * + * + * + at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), + code: 'ERR_TEST_FAILURE' +} + + + + + +[Error [ERR_TEST_FAILURE]: thrown from async throw fail] { + failureType: 'testCodeFailure', + cause: Error: thrown from async throw fail + * + * + * + * + * + * + at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), + code: 'ERR_TEST_FAILURE' +} + + + + +[Error [ERR_TEST_FAILURE]: Expected values to be strictly equal: + +true !== false +] { + failureType: 'testCodeFailure', + cause: AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + true !== false + + * + * + * + * + * + * + * { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: true, + expected: false, + operator: 'strictEqual' + }, + code: 'ERR_TEST_FAILURE' +} + + + + + +[Error [ERR_TEST_FAILURE]: rejected from reject fail] { + failureType: 'testCodeFailure', + cause: Error: rejected from reject fail + * + * + * + * + * + * + at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), + code: 'ERR_TEST_FAILURE' +} + + + + + + + + + + +Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fail + * { + failureType: 'testCodeFailure', + cause: Error: thrown from subtest sync throw fail + * + * + * + * + * + * + * + * + * + at Test.postRun (node:internal/test_runner/test:715:19), + code: 'ERR_TEST_FAILURE' +} + + + + + + +[Error [ERR_TEST_FAILURE]: Symbol(thrown symbol from sync throw non-error fail)] { failureType: 'testCodeFailure', cause: Symbol(thrown symbol from sync throw non-error fail), code: 'ERR_TEST_FAILURE' } + + + + + + + + + + + +[Error [ERR_TEST_FAILURE]: test did not finish before its parent and was cancelled] { failureType: 'cancelledByParent', cause: 'test did not finish before its parent and was cancelled', code: 'ERR_TEST_FAILURE' } + + + + + + + + + + + + + + + +[Error [ERR_TEST_FAILURE]: this should be executed] { + failureType: 'testCodeFailure', + cause: Error: this should be executed + * + * + * + * + * + * + at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), + code: 'ERR_TEST_FAILURE' +} + + + + + + + + + + + + + + + + + + + +[Error [ERR_TEST_FAILURE]: callback failure] { + failureType: 'testCodeFailure', + cause: Error: callback failure + * + at process.processImmediate (node:internal/timers:476:21), + code: 'ERR_TEST_FAILURE' +} + + + + + + + +[Error [ERR_TEST_FAILURE]: passed a callback but also returned a Promise] { failureType: 'callbackAndPromisePresent', cause: 'passed a callback but also returned a Promise', code: 'ERR_TEST_FAILURE' } + + + + +[Error [ERR_TEST_FAILURE]: thrown from callback throw] { + failureType: 'testCodeFailure', + cause: Error: thrown from callback throw + * + * + * + * + * + * + at async Test.processPendingSubtests (node:internal/test_runner/test:374:7), + code: 'ERR_TEST_FAILURE' +} + + + + +Error [ERR_TEST_FAILURE]: callback invoked multiple times + * + * { + failureType: 'multipleCallbackInvocations', + cause: 'callback invoked multiple times', + code: 'ERR_TEST_FAILURE' +} + + + + + +Error [ERR_TEST_FAILURE]: callback invoked multiple times + * { + failureType: 'uncaughtException', + cause: Error [ERR_TEST_FAILURE]: callback invoked multiple times + * { + failureType: 'multipleCallbackInvocations', + cause: 'callback invoked multiple times', + code: 'ERR_TEST_FAILURE' + }, + code: 'ERR_TEST_FAILURE' +} + + + + +Error [ERR_TEST_FAILURE]: thrown from callback async throw + * { + failureType: 'uncaughtException', + cause: Error: thrown from callback async throw + * + at process.processImmediate (node:internal/timers:476:21), + code: 'ERR_TEST_FAILURE' +} + + + + + + + + + + + + + + +[Error [ERR_TEST_FAILURE]: customized] { failureType: 'testCodeFailure', cause: customized, code: 'ERR_TEST_FAILURE' } + + + + +[Error [ERR_TEST_FAILURE]: { + foo: 1, + [Symbol(nodejs.util.inspect.custom)]: [Function: [nodejs.util.inspect.custom]] +}] { + failureType: 'testCodeFailure', + cause: { foo: 1, [Symbol(nodejs.util.inspect.custom)]: [Function: [nodejs.util.inspect.custom]] }, + code: 'ERR_TEST_FAILURE' +} + + + + + +Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fails at first + * { + failureType: 'testCodeFailure', + cause: Error: thrown from subtest sync throw fails at first + * + * + * + * + * + * + * + * + * + at Test.postRun (node:internal/test_runner/test:715:19), + code: 'ERR_TEST_FAILURE' +} + + + + +Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fails at second + * { + failureType: 'testCodeFailure', + cause: Error: thrown from subtest sync throw fails at second + * + * + * + * + * + * + * + * + * + at async Test.run (node:internal/test_runner/test:632:9), + code: 'ERR_TEST_FAILURE' +} + + + + + +[Error [ERR_TEST_FAILURE]: test timed out after 5ms] { failureType: 'testTimeoutFailure', cause: 'test timed out after 5ms', code: 'ERR_TEST_FAILURE' } + + + + +[Error [ERR_TEST_FAILURE]: test timed out after 5ms] { failureType: 'testTimeoutFailure', cause: 'test timed out after 5ms', code: 'ERR_TEST_FAILURE' } + + + + + + + +[Error [ERR_TEST_FAILURE]: custom error] { failureType: 'testCodeFailure', cause: 'custom error', code: 'ERR_TEST_FAILURE' } + + + + +Error [ERR_TEST_FAILURE]: foo + * { + failureType: 'uncaughtException', + cause: Error: foo + * + * + at process.processTimers (node:internal/timers:512:7), + code: 'ERR_TEST_FAILURE' +} + + + + +Error [ERR_TEST_FAILURE]: bar + * { + failureType: 'unhandledRejection', + cause: Error: bar + * + * + at process.processTimers (node:internal/timers:512:7), + code: 'ERR_TEST_FAILURE' +} + + + + +[Error [ERR_TEST_FAILURE]: Expected values to be loosely deep-equal: + +{ + bar: 1, + foo: 1 +} + +should loosely deep-equal + +<ref *1> { + bar: 2, + c: [Circular *1] +}] { + failureType: 'testCodeFailure', + cause: AssertionError [ERR_ASSERTION]: Expected values to be loosely deep-equal: + + { + bar: 1, + foo: 1 + } + + should loosely deep-equal + + <ref *1> { + bar: 2, + c: [Circular *1] + } + * { + generatedMessage: true, + code: 'ERR_ASSERTION', + actual: [Object], + expected: [Object], + operator: 'deepEqual' + }, + code: 'ERR_TEST_FAILURE' +} + + + + +Error [ERR_TEST_FAILURE]: test could not be started because its parent finished + * { + failureType: 'parentAlreadyFinished', + cause: 'test could not be started because its parent finished', + code: 'ERR_TEST_FAILURE' +} + + + + + + + + + + + + + + + + + + diff --git a/test/fixtures/test-runner/output/name_pattern.js b/test/fixtures/test-runner/output/name_pattern.js index f183c09057fa33..10e7619b9cfcb9 100644 --- a/test/fixtures/test-runner/output/name_pattern.js +++ b/test/fixtures/test-runner/output/name_pattern.js @@ -1,4 +1,4 @@ -// Flags: --no-warnings --test-name-pattern=enabled --test-name-pattern=yes --test-name-pattern=/pattern/i +// Flags: --test-name-pattern=enabled --test-name-pattern=yes --test-name-pattern=/pattern/i 'use strict'; const common = require('../../../common'); const { diff --git a/test/fixtures/test-runner/output/name_pattern_with_only.js b/test/fixtures/test-runner/output/name_pattern_with_only.js index a3e2f1be2ad42d..bc68b7a5fdf7e7 100644 --- a/test/fixtures/test-runner/output/name_pattern_with_only.js +++ b/test/fixtures/test-runner/output/name_pattern_with_only.js @@ -1,4 +1,4 @@ -// Flags: --no-warnings --test-only --test-name-pattern=enabled +// Flags: --test-only --test-name-pattern=enabled 'use strict'; const common = require('../../../common'); const { test } = require('node:test'); diff --git a/test/fixtures/test-runner/output/no_refs.js b/test/fixtures/test-runner/output/no_refs.js index 7b36e01133da6e..0d7cc6e01791d0 100644 --- a/test/fixtures/test-runner/output/no_refs.js +++ b/test/fixtures/test-runner/output/no_refs.js @@ -1,4 +1,3 @@ -// Flags: --no-warnings 'use strict'; require('../../../common'); const test = require('node:test'); diff --git a/test/fixtures/test-runner/output/no_refs.snapshot b/test/fixtures/test-runner/output/no_refs.snapshot index 49c51af41caec3..5756f5ebf87a0a 100644 --- a/test/fixtures/test-runner/output/no_refs.snapshot +++ b/test/fixtures/test-runner/output/no_refs.snapshot @@ -4,6 +4,7 @@ TAP version 13 not ok 1 - +does not keep event loop alive --- duration_ms: * + location: '/test/fixtures/test-runner/output/no_refs.js:(LINE):11' failureType: 'cancelledByParent' error: 'Promise resolution is still pending but the event loop has already resolved' code: 'ERR_TEST_FAILURE' @@ -14,6 +15,7 @@ TAP version 13 not ok 1 - does not keep event loop alive --- duration_ms: * + location: '/test/fixtures/test-runner/output/no_refs.js:(LINE):1' failureType: 'cancelledByParent' error: 'Promise resolution is still pending but the event loop has already resolved' code: 'ERR_TEST_FAILURE' diff --git a/test/fixtures/test-runner/output/no_tests.js b/test/fixtures/test-runner/output/no_tests.js index f9a9506706180e..2644e29fe26f85 100644 --- a/test/fixtures/test-runner/output/no_tests.js +++ b/test/fixtures/test-runner/output/no_tests.js @@ -1,4 +1,3 @@ -// Flags: --no-warnings 'use strict'; require('../../../common'); const test = require('node:test'); diff --git a/test/fixtures/test-runner/output/only_tests.js b/test/fixtures/test-runner/output/only_tests.js index 5ac4a90c2cf264..26266b524454b7 100644 --- a/test/fixtures/test-runner/output/only_tests.js +++ b/test/fixtures/test-runner/output/only_tests.js @@ -1,4 +1,4 @@ -// Flags: --no-warnings --test-only +// Flags: --test-only 'use strict'; require('../../../common'); const { test, describe, it } = require('node:test'); diff --git a/test/fixtures/test-runner/output/output.js b/test/fixtures/test-runner/output/output.js index 47d99d1c8d4984..f37d3495030950 100644 --- a/test/fixtures/test-runner/output/output.js +++ b/test/fixtures/test-runner/output/output.js @@ -212,20 +212,6 @@ test('test with a name and options provided', { skip: true }); // A test with only options and a function provided. test({ skip: true }, function functionAndOptions() {}); -// A test whose description needs to be escaped. -test('escaped description \\ # \\#\\ \n \t \f \v \b \r'); - -// A test whose skip message needs to be escaped. -test('escaped skip message', { skip: '#skip' }); - -// A test whose todo message needs to be escaped. -test('escaped todo message', { todo: '#todo' }); - -// A test with a diagnostic message that needs to be escaped. -test('escaped diagnostic', (t) => { - t.diagnostic('#diagnostic'); -}); - test('callback pass', (t, done) => { setImmediate(done); }); diff --git a/test/fixtures/test-runner/output/output.snapshot b/test/fixtures/test-runner/output/output.snapshot index db19d8ca549a38..18f030dab361ab 100644 --- a/test/fixtures/test-runner/output/output.snapshot +++ b/test/fixtures/test-runner/output/output.snapshot @@ -13,6 +13,7 @@ ok 2 - sync pass todo with message # TODO this is a passing todo not ok 3 - sync fail todo # TODO --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'thrown from sync fail todo' code: 'ERR_TEST_FAILURE' @@ -29,6 +30,7 @@ not ok 3 - sync fail todo # TODO not ok 4 - sync fail todo with message # TODO this is a failing todo --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'thrown from sync fail todo with message' code: 'ERR_TEST_FAILURE' @@ -61,6 +63,7 @@ ok 7 - sync pass not ok 8 - sync throw fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'thrown from sync throw fail' code: 'ERR_TEST_FAILURE' @@ -87,6 +90,7 @@ ok 10 - async pass not ok 11 - async throw fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'thrown from async throw fail' code: 'ERR_TEST_FAILURE' @@ -103,6 +107,7 @@ not ok 11 - async throw fail not ok 12 - async skip fail # SKIP --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'thrown from async throw fail' code: 'ERR_TEST_FAILURE' @@ -119,6 +124,7 @@ not ok 12 - async skip fail # SKIP not ok 13 - async assertion fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: |- Expected values to be strictly equal: @@ -148,6 +154,7 @@ ok 14 - resolve pass not ok 15 - reject fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'rejected from reject fail' code: 'ERR_TEST_FAILURE' @@ -190,6 +197,7 @@ ok 20 - immediate resolve pass not ok 1 - +sync throw fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):11' failureType: 'testCodeFailure' error: 'thrown from subtest sync throw fail' code: 'ERR_TEST_FAILURE' @@ -210,6 +218,7 @@ ok 20 - immediate resolve pass not ok 21 - subtest sync throw fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'subtestsFailed' error: '1 subtest failed' code: 'ERR_TEST_FAILURE' @@ -218,6 +227,7 @@ not ok 21 - subtest sync throw fail not ok 22 - sync throw non-error fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'Symbol(thrown symbol from sync throw non-error fail)' code: 'ERR_TEST_FAILURE' @@ -253,6 +263,7 @@ ok 23 - level 0a not ok 1 - +long running --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):5' failureType: 'cancelledByParent' error: 'test did not finish before its parent and was cancelled' code: 'ERR_TEST_FAILURE' @@ -272,6 +283,7 @@ ok 23 - level 0a not ok 24 - top level --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'subtestsFailed' error: '1 subtest failed' code: 'ERR_TEST_FAILURE' @@ -295,6 +307,7 @@ ok 27 - sync skip option with message # SKIP this is skipped not ok 28 - sync skip option is false fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'this should be executed' code: 'ERR_TEST_FAILURE' @@ -347,36 +360,16 @@ ok 36 - functionAndOptions # SKIP --- duration_ms: * ... -# Subtest: escaped description \\ \# \\\#\\ \\n \\t \\f \\v \\b \\r -ok 37 - escaped description \\ \# \\\#\\ \\n \\t \\f \\v \\b \\r - --- - duration_ms: * - ... -# Subtest: escaped skip message -ok 38 - escaped skip message # SKIP \#skip - --- - duration_ms: * - ... -# Subtest: escaped todo message -ok 39 - escaped todo message # TODO \#todo - --- - duration_ms: * - ... -# Subtest: escaped diagnostic -ok 40 - escaped diagnostic - --- - duration_ms: * - ... -# \#diagnostic # Subtest: callback pass -ok 41 - callback pass +ok 37 - callback pass --- duration_ms: * ... # Subtest: callback fail -not ok 42 - callback fail +not ok 38 - callback fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'callback failure' code: 'ERR_TEST_FAILURE' @@ -385,32 +378,34 @@ not ok 42 - callback fail * ... # Subtest: sync t is this in test -ok 43 - sync t is this in test +ok 39 - sync t is this in test --- duration_ms: * ... # Subtest: async t is this in test -ok 44 - async t is this in test +ok 40 - async t is this in test --- duration_ms: * ... # Subtest: callback t is this in test -ok 45 - callback t is this in test +ok 41 - callback t is this in test --- duration_ms: * ... # Subtest: callback also returns a Promise -not ok 46 - callback also returns a Promise +not ok 42 - callback also returns a Promise --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'callbackAndPromisePresent' error: 'passed a callback but also returned a Promise' code: 'ERR_TEST_FAILURE' ... # Subtest: callback throw -not ok 47 - callback throw +not ok 43 - callback throw --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'thrown from callback throw' code: 'ERR_TEST_FAILURE' @@ -424,9 +419,10 @@ not ok 47 - callback throw * ... # Subtest: callback called twice -not ok 48 - callback called twice +not ok 44 - callback called twice --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'multipleCallbackInvocations' error: 'callback invoked multiple times' code: 'ERR_TEST_FAILURE' @@ -435,14 +431,15 @@ not ok 48 - callback called twice * ... # Subtest: callback called twice in different ticks -ok 49 - callback called twice in different ticks +ok 45 - callback called twice in different ticks --- duration_ms: * ... # Subtest: callback called twice in future tick -not ok 50 - callback called twice in future tick +not ok 46 - callback called twice in future tick --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'uncaughtException' error: 'callback invoked multiple times' code: 'ERR_TEST_FAILURE' @@ -450,9 +447,10 @@ not ok 50 - callback called twice in future tick * ... # Subtest: callback async throw -not ok 51 - callback async throw +not ok 47 - callback async throw --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'uncaughtException' error: 'thrown from callback async throw' code: 'ERR_TEST_FAILURE' @@ -461,7 +459,7 @@ not ok 51 - callback async throw * ... # Subtest: callback async throw after done -ok 52 - callback async throw after done +ok 48 - callback async throw after done --- duration_ms: * ... @@ -489,23 +487,25 @@ ok 52 - callback async throw after done duration_ms: * ... 1..4 -ok 53 - only is set but not in only mode +ok 49 - only is set but not in only mode --- duration_ms: * ... # 'only' and 'runOnly' require the --test-only command-line option. # Subtest: custom inspect symbol fail -not ok 54 - custom inspect symbol fail +not ok 50 - custom inspect symbol fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'customized' code: 'ERR_TEST_FAILURE' ... # Subtest: custom inspect symbol that throws fail -not ok 55 - custom inspect symbol that throws fail +not ok 51 - custom inspect symbol that throws fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: |- { @@ -519,6 +519,7 @@ not ok 55 - custom inspect symbol that throws fail not ok 1 - sync throw fails at first --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):11' failureType: 'testCodeFailure' error: 'thrown from subtest sync throw fails at first' code: 'ERR_TEST_FAILURE' @@ -538,6 +539,7 @@ not ok 55 - custom inspect symbol that throws fail not ok 2 - sync throw fails at second --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):11' failureType: 'testCodeFailure' error: 'thrown from subtest sync throw fails at second' code: 'ERR_TEST_FAILURE' @@ -554,56 +556,61 @@ not ok 55 - custom inspect symbol that throws fail * ... 1..2 -not ok 56 - subtest sync throw fails +not ok 52 - subtest sync throw fails --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'subtestsFailed' error: '2 subtests failed' code: 'ERR_TEST_FAILURE' ... # Subtest: timed out async test -not ok 57 - timed out async test +not ok 53 - timed out async test --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testTimeoutFailure' error: 'test timed out after 5ms' code: 'ERR_TEST_FAILURE' ... # Subtest: timed out callback test -not ok 58 - timed out callback test +not ok 54 - timed out callback test --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testTimeoutFailure' error: 'test timed out after 5ms' code: 'ERR_TEST_FAILURE' ... # Subtest: large timeout async test is ok -ok 59 - large timeout async test is ok +ok 55 - large timeout async test is ok --- duration_ms: * ... # Subtest: large timeout callback test is ok -ok 60 - large timeout callback test is ok +ok 56 - large timeout callback test is ok --- duration_ms: * ... # Subtest: successful thenable -ok 61 - successful thenable +ok 57 - successful thenable --- duration_ms: * ... # Subtest: rejected thenable -not ok 62 - rejected thenable +not ok 58 - rejected thenable --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'custom error' code: 'ERR_TEST_FAILURE' ... # Subtest: unfinished test with uncaughtException -not ok 63 - unfinished test with uncaughtException +not ok 59 - unfinished test with uncaughtException --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'uncaughtException' error: 'foo' code: 'ERR_TEST_FAILURE' @@ -613,9 +620,10 @@ not ok 63 - unfinished test with uncaughtException * ... # Subtest: unfinished test with unhandledRejection -not ok 64 - unfinished test with unhandledRejection +not ok 60 - unfinished test with unhandledRejection --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'unhandledRejection' error: 'bar' code: 'ERR_TEST_FAILURE' @@ -625,9 +633,10 @@ not ok 64 - unfinished test with unhandledRejection * ... # Subtest: assertion errors display actual and expected properly -not ok 65 - assertion errors display actual and expected properly +not ok 61 - assertion errors display actual and expected properly --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: |- Expected values to be loosely deep-equal: @@ -656,16 +665,17 @@ not ok 65 - assertion errors display actual and expected properly * ... # Subtest: invalid subtest fail -not ok 66 - invalid subtest fail +not ok 62 - invalid subtest fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):7' failureType: 'parentAlreadyFinished' error: 'test could not be started because its parent finished' code: 'ERR_TEST_FAILURE' stack: |- * ... -1..66 +1..62 # Warning: Test "unhandled rejection - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: rejected from unhandled rejection fail" and would have caused the test to fail, but instead triggered an unhandledRejection event. # Warning: Test "async unhandled rejection - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: rejected from async unhandled rejection fail" and would have caused the test to fail, but instead triggered an unhandledRejection event. # Warning: A resource generated asynchronous activity after the test ended. This activity created the error "Error: uncaught from outside of a test" which triggered an uncaughtException event, caught by the test runner. @@ -673,11 +683,11 @@ not ok 66 - invalid subtest fail # Warning: Test "immediate reject - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: rejected from immediate reject fail" and would have caused the test to fail, but instead triggered an unhandledRejection event. # Warning: Test "callback called twice in different ticks" generated asynchronous activity after the test ended. This activity created the error "Error [ERR_TEST_FAILURE]: callback invoked multiple times" and would have caused the test to fail, but instead triggered an uncaughtException event. # Warning: Test "callback async throw after done" generated asynchronous activity after the test ended. This activity created the error "Error: thrown from callback async throw after done" and would have caused the test to fail, but instead triggered an uncaughtException event. -# tests 80 +# tests 76 # suites 0 -# pass 37 +# pass 35 # fail 25 # cancelled 3 -# skipped 10 -# todo 5 +# skipped 9 +# todo 4 # duration_ms * diff --git a/test/fixtures/test-runner/output/output_cli.js b/test/fixtures/test-runner/output/output_cli.js index 50ef07233314b1..4c6b029c6580c0 100644 --- a/test/fixtures/test-runner/output/output_cli.js +++ b/test/fixtures/test-runner/output/output_cli.js @@ -1,4 +1,3 @@ -// Flags: --no-warnings 'use strict'; require('../../../common'); const fixtures = require('../../../common/fixtures'); diff --git a/test/fixtures/test-runner/output/output_cli.snapshot b/test/fixtures/test-runner/output/output_cli.snapshot index fe192625e1f8b6..3cef8f29b253b9 100644 --- a/test/fixtures/test-runner/output/output_cli.snapshot +++ b/test/fixtures/test-runner/output/output_cli.snapshot @@ -13,6 +13,7 @@ ok 2 - sync pass todo with message # TODO this is a passing todo not ok 3 - sync fail todo # TODO --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'thrown from sync fail todo' code: 'ERR_TEST_FAILURE' @@ -29,6 +30,7 @@ not ok 3 - sync fail todo # TODO not ok 4 - sync fail todo with message # TODO this is a failing todo --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'thrown from sync fail todo with message' code: 'ERR_TEST_FAILURE' @@ -61,6 +63,7 @@ ok 7 - sync pass not ok 8 - sync throw fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'thrown from sync throw fail' code: 'ERR_TEST_FAILURE' @@ -87,6 +90,7 @@ ok 10 - async pass not ok 11 - async throw fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'thrown from async throw fail' code: 'ERR_TEST_FAILURE' @@ -103,6 +107,7 @@ not ok 11 - async throw fail not ok 12 - async skip fail # SKIP --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'thrown from async throw fail' code: 'ERR_TEST_FAILURE' @@ -119,6 +124,7 @@ not ok 12 - async skip fail # SKIP not ok 13 - async assertion fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: |- Expected values to be strictly equal: @@ -148,6 +154,7 @@ ok 14 - resolve pass not ok 15 - reject fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'rejected from reject fail' code: 'ERR_TEST_FAILURE' @@ -190,6 +197,7 @@ ok 20 - immediate resolve pass not ok 1 - +sync throw fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):11' failureType: 'testCodeFailure' error: 'thrown from subtest sync throw fail' code: 'ERR_TEST_FAILURE' @@ -210,6 +218,7 @@ ok 20 - immediate resolve pass not ok 21 - subtest sync throw fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'subtestsFailed' error: '1 subtest failed' code: 'ERR_TEST_FAILURE' @@ -218,6 +227,7 @@ not ok 21 - subtest sync throw fail not ok 22 - sync throw non-error fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'Symbol(thrown symbol from sync throw non-error fail)' code: 'ERR_TEST_FAILURE' @@ -253,6 +263,7 @@ ok 23 - level 0a not ok 1 - +long running --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):5' failureType: 'cancelledByParent' error: 'test did not finish before its parent and was cancelled' code: 'ERR_TEST_FAILURE' @@ -272,6 +283,7 @@ ok 23 - level 0a not ok 24 - top level --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'subtestsFailed' error: '1 subtest failed' code: 'ERR_TEST_FAILURE' @@ -295,6 +307,7 @@ ok 27 - sync skip option with message # SKIP this is skipped not ok 28 - sync skip option is false fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'this should be executed' code: 'ERR_TEST_FAILURE' @@ -347,36 +360,16 @@ ok 36 - functionAndOptions # SKIP --- duration_ms: * ... -# Subtest: escaped description \\ \# \\\#\\ \\n \\t \\f \\v \\b \\r -ok 37 - escaped description \\ \# \\\#\\ \\n \\t \\f \\v \\b \\r - --- - duration_ms: * - ... -# Subtest: escaped skip message -ok 38 - escaped skip message # SKIP \#skip - --- - duration_ms: * - ... -# Subtest: escaped todo message -ok 39 - escaped todo message # TODO \#todo - --- - duration_ms: * - ... -# Subtest: escaped diagnostic -ok 40 - escaped diagnostic - --- - duration_ms: * - ... -# \#diagnostic # Subtest: callback pass -ok 41 - callback pass +ok 37 - callback pass --- duration_ms: * ... # Subtest: callback fail -not ok 42 - callback fail +not ok 38 - callback fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'callback failure' code: 'ERR_TEST_FAILURE' @@ -385,32 +378,34 @@ not ok 42 - callback fail * ... # Subtest: sync t is this in test -ok 43 - sync t is this in test +ok 39 - sync t is this in test --- duration_ms: * ... # Subtest: async t is this in test -ok 44 - async t is this in test +ok 40 - async t is this in test --- duration_ms: * ... # Subtest: callback t is this in test -ok 45 - callback t is this in test +ok 41 - callback t is this in test --- duration_ms: * ... # Subtest: callback also returns a Promise -not ok 46 - callback also returns a Promise +not ok 42 - callback also returns a Promise --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'callbackAndPromisePresent' error: 'passed a callback but also returned a Promise' code: 'ERR_TEST_FAILURE' ... # Subtest: callback throw -not ok 47 - callback throw +not ok 43 - callback throw --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'thrown from callback throw' code: 'ERR_TEST_FAILURE' @@ -424,9 +419,10 @@ not ok 47 - callback throw * ... # Subtest: callback called twice -not ok 48 - callback called twice +not ok 44 - callback called twice --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'multipleCallbackInvocations' error: 'callback invoked multiple times' code: 'ERR_TEST_FAILURE' @@ -435,14 +431,15 @@ not ok 48 - callback called twice * ... # Subtest: callback called twice in different ticks -ok 49 - callback called twice in different ticks +ok 45 - callback called twice in different ticks --- duration_ms: * ... # Subtest: callback called twice in future tick -not ok 50 - callback called twice in future tick +not ok 46 - callback called twice in future tick --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'uncaughtException' error: 'callback invoked multiple times' code: 'ERR_TEST_FAILURE' @@ -450,9 +447,10 @@ not ok 50 - callback called twice in future tick * ... # Subtest: callback async throw -not ok 51 - callback async throw +not ok 47 - callback async throw --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'uncaughtException' error: 'thrown from callback async throw' code: 'ERR_TEST_FAILURE' @@ -461,7 +459,7 @@ not ok 51 - callback async throw * ... # Subtest: callback async throw after done -ok 52 - callback async throw after done +ok 48 - callback async throw after done --- duration_ms: * ... @@ -489,23 +487,25 @@ ok 52 - callback async throw after done duration_ms: * ... 1..4 -ok 53 - only is set but not in only mode +ok 49 - only is set but not in only mode --- duration_ms: * ... # 'only' and 'runOnly' require the --test-only command-line option. # Subtest: custom inspect symbol fail -not ok 54 - custom inspect symbol fail +not ok 50 - custom inspect symbol fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'customized' code: 'ERR_TEST_FAILURE' ... # Subtest: custom inspect symbol that throws fail -not ok 55 - custom inspect symbol that throws fail +not ok 51 - custom inspect symbol that throws fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: |- { @@ -519,6 +519,7 @@ not ok 55 - custom inspect symbol that throws fail not ok 1 - sync throw fails at first --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):11' failureType: 'testCodeFailure' error: 'thrown from subtest sync throw fails at first' code: 'ERR_TEST_FAILURE' @@ -538,6 +539,7 @@ not ok 55 - custom inspect symbol that throws fail not ok 2 - sync throw fails at second --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):11' failureType: 'testCodeFailure' error: 'thrown from subtest sync throw fails at second' code: 'ERR_TEST_FAILURE' @@ -554,56 +556,61 @@ not ok 55 - custom inspect symbol that throws fail * ... 1..2 -not ok 56 - subtest sync throw fails +not ok 52 - subtest sync throw fails --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'subtestsFailed' error: '2 subtests failed' code: 'ERR_TEST_FAILURE' ... # Subtest: timed out async test -not ok 57 - timed out async test +not ok 53 - timed out async test --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testTimeoutFailure' error: 'test timed out after 5ms' code: 'ERR_TEST_FAILURE' ... # Subtest: timed out callback test -not ok 58 - timed out callback test +not ok 54 - timed out callback test --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testTimeoutFailure' error: 'test timed out after 5ms' code: 'ERR_TEST_FAILURE' ... # Subtest: large timeout async test is ok -ok 59 - large timeout async test is ok +ok 55 - large timeout async test is ok --- duration_ms: * ... # Subtest: large timeout callback test is ok -ok 60 - large timeout callback test is ok +ok 56 - large timeout callback test is ok --- duration_ms: * ... # Subtest: successful thenable -ok 61 - successful thenable +ok 57 - successful thenable --- duration_ms: * ... # Subtest: rejected thenable -not ok 62 - rejected thenable +not ok 58 - rejected thenable --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: 'custom error' code: 'ERR_TEST_FAILURE' ... # Subtest: unfinished test with uncaughtException -not ok 63 - unfinished test with uncaughtException +not ok 59 - unfinished test with uncaughtException --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'uncaughtException' error: 'foo' code: 'ERR_TEST_FAILURE' @@ -613,9 +620,10 @@ not ok 63 - unfinished test with uncaughtException * ... # Subtest: unfinished test with unhandledRejection -not ok 64 - unfinished test with unhandledRejection +not ok 60 - unfinished test with unhandledRejection --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'unhandledRejection' error: 'bar' code: 'ERR_TEST_FAILURE' @@ -625,9 +633,10 @@ not ok 64 - unfinished test with unhandledRejection * ... # Subtest: assertion errors display actual and expected properly -not ok 65 - assertion errors display actual and expected properly +not ok 61 - assertion errors display actual and expected properly --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):1' failureType: 'testCodeFailure' error: |- Expected values to be loosely deep-equal: @@ -656,9 +665,10 @@ not ok 65 - assertion errors display actual and expected properly * ... # Subtest: invalid subtest fail -not ok 66 - invalid subtest fail +not ok 62 - invalid subtest fail --- duration_ms: * + location: '/test/fixtures/test-runner/output/output.js:(LINE):7' failureType: 'parentAlreadyFinished' error: 'test could not be started because its parent finished' code: 'ERR_TEST_FAILURE' @@ -673,16 +683,16 @@ not ok 66 - invalid subtest fail # Warning: Test "callback called twice in different ticks" generated asynchronous activity after the test ended. This activity created the error "Error [ERR_TEST_FAILURE]: callback invoked multiple times" and would have caused the test to fail, but instead triggered an uncaughtException event. # Warning: Test "callback async throw after done" generated asynchronous activity after the test ended. This activity created the error "Error: thrown from callback async throw after done" and would have caused the test to fail, but instead triggered an uncaughtException event. # Subtest: last test -ok 67 - last test +ok 63 - last test --- duration_ms: * ... -1..67 -# tests 81 +1..63 +# tests 77 # suites 0 -# pass 38 +# pass 36 # fail 25 # cancelled 3 -# skipped 10 -# todo 5 +# skipped 9 +# todo 4 # duration_ms * diff --git a/test/fixtures/test-runner/output/single.js b/test/fixtures/test-runner/output/single.js index e099ec3c375bb7..568e5ba986ad49 100644 --- a/test/fixtures/test-runner/output/single.js +++ b/test/fixtures/test-runner/output/single.js @@ -1,4 +1,3 @@ -// Flags: --no-warnings 'use strict'; const test = require('node:test'); test('last test', () => {}); diff --git a/test/fixtures/test-runner/output/spec_reporter.js b/test/fixtures/test-runner/output/spec_reporter.js index 6a7c2d655f93b3..46e18b1ca8630d 100644 --- a/test/fixtures/test-runner/output/spec_reporter.js +++ b/test/fixtures/test-runner/output/spec_reporter.js @@ -1,4 +1,3 @@ -// Flags: --no-warnings 'use strict'; require('../../../common'); const fixtures = require('../../../common/fixtures'); diff --git a/test/fixtures/test-runner/output/spec_reporter.snapshot b/test/fixtures/test-runner/output/spec_reporter.snapshot index 768204177014af..5dc05d5b43c12d 100644 --- a/test/fixtures/test-runner/output/spec_reporter.snapshot +++ b/test/fixtures/test-runner/output/spec_reporter.snapshot @@ -1,6 +1,6 @@ - sync pass todo (*ms) - sync pass todo with message (*ms) - sync fail todo (*ms) + sync pass todo (*ms) # TODO + sync pass todo with message (*ms) # this is a passing todo + sync fail todo (*ms) # TODO Error: thrown from sync fail todo * * @@ -10,7 +10,7 @@ * * - sync fail todo with message (*ms) + sync fail todo with message (*ms) # this is a failing todo Error: thrown from sync fail todo with message * * @@ -21,7 +21,7 @@ * sync skip pass (*ms) # SKIP - sync skip pass with message (*ms) # SKIP + sync skip pass with message (*ms) # this is skipped sync pass (*ms) this test should pass sync throw fail (*ms) @@ -130,7 +130,7 @@ invalid subtest - pass but subtest fails (*ms) sync skip option (*ms) # SKIP - sync skip option with message (*ms) # SKIP + sync skip option with message (*ms) # this is skipped sync skip option is false fail (*ms) Error: this should be executed * @@ -149,12 +149,6 @@ (*ms) # SKIP test with a name and options provided (*ms) # SKIP functionAndOptions (*ms) # SKIP - escaped description \ # \#\ -  (*ms) - escaped skip message (*ms) # SKIP - escaped todo message (*ms) - escaped diagnostic (*ms) - #diagnostic callback pass (*ms) callback fail (*ms) Error: callback failure @@ -296,18 +290,19 @@ Warning: Test "immediate reject - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: rejected from immediate reject fail" and would have caused the test to fail, but instead triggered an unhandledRejection event. Warning: Test "callback called twice in different ticks" generated asynchronous activity after the test ended. This activity created the error "Error [ERR_TEST_FAILURE]: callback invoked multiple times" and would have caused the test to fail, but instead triggered an uncaughtException event. Warning: Test "callback async throw after done" generated asynchronous activity after the test ended. This activity created the error "Error: thrown from callback async throw after done" and would have caused the test to fail, but instead triggered an uncaughtException event. - tests 80 + tests 76 suites 0 - pass 37 + pass 35 fail 25 cancelled 3 - skipped 10 - todo 5 + skipped 9 + todo 4 duration_ms * failing tests: - sync fail todo (*ms) +* + sync fail todo (*ms) # TODO Error: thrown from sync fail todo * * @@ -317,7 +312,8 @@ * * - sync fail todo with message (*ms) +* + sync fail todo with message (*ms) # this is a failing todo Error: thrown from sync fail todo with message * * @@ -327,6 +323,7 @@ * * +* sync throw fail (*ms) Error: thrown from sync throw fail * @@ -337,6 +334,7 @@ * * +* async throw fail (*ms) Error: thrown from async throw fail * @@ -347,7 +345,8 @@ * * - async skip fail (*ms) +* + async skip fail (*ms) # SKIP Error: thrown from async throw fail * * @@ -357,6 +356,7 @@ * * +* async assertion fail (*ms) AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: @@ -376,6 +376,7 @@ operator: 'strictEqual' } +* reject fail (*ms) Error: rejected from reject fail * @@ -386,6 +387,7 @@ * * +* +sync throw fail (*ms) Error: thrown from subtest sync throw fail * @@ -399,12 +401,15 @@ * * +* sync throw non-error fail (*ms) Symbol(thrown symbol from sync throw non-error fail) +* +long running (*ms) 'test did not finish before its parent and was cancelled' +* sync skip option is false fail (*ms) Error: this should be executed * @@ -415,14 +420,17 @@ * * +* callback fail (*ms) Error: callback failure * * +* callback also returns a Promise (*ms) 'passed a callback but also returned a Promise' +* callback throw (*ms) Error: thrown from callback throw * @@ -433,9 +441,11 @@ * * +* callback called twice (*ms) 'callback invoked multiple times' +* callback called twice in future tick (*ms) Error [ERR_TEST_FAILURE]: callback invoked multiple times * { @@ -444,17 +454,21 @@ code: 'ERR_TEST_FAILURE' } +* callback async throw (*ms) Error: thrown from callback async throw * * +* custom inspect symbol fail (*ms) customized +* custom inspect symbol that throws fail (*ms) { foo: 1, [Symbol(nodejs.util.inspect.custom)]: [Function: [nodejs.util.inspect.custom]] } +* sync throw fails at first (*ms) Error: thrown from subtest sync throw fails at first * @@ -468,6 +482,7 @@ * * +* sync throw fails at second (*ms) Error: thrown from subtest sync throw fails at second * @@ -481,27 +496,33 @@ * * +* timed out async test (*ms) 'test timed out after *ms' +* timed out callback test (*ms) 'test timed out after *ms' +* rejected thenable (*ms) 'custom error' +* unfinished test with uncaughtException (*ms) Error: foo * * * +* unfinished test with unhandledRejection (*ms) Error: bar * * * +* assertion errors display actual and expected properly (*ms) AssertionError [ERR_ASSERTION]: Expected values to be loosely deep-equal: @@ -524,5 +545,6 @@ operator: 'deepEqual' } +* invalid subtest fail (*ms) 'test could not be started because its parent finished' diff --git a/test/fixtures/test-runner/output/spec_reporter_cli.js b/test/fixtures/test-runner/output/spec_reporter_cli.js index e88a7221fb4e71..b0c72e51ab66b8 100644 --- a/test/fixtures/test-runner/output/spec_reporter_cli.js +++ b/test/fixtures/test-runner/output/spec_reporter_cli.js @@ -1,4 +1,3 @@ -// Flags: --no-warnings 'use strict'; require('../../../common'); const fixtures = require('../../../common/fixtures'); diff --git a/test/fixtures/test-runner/output/spec_reporter_cli.snapshot b/test/fixtures/test-runner/output/spec_reporter_cli.snapshot index e4e08764fd4925..25c22069c3b8e7 100644 --- a/test/fixtures/test-runner/output/spec_reporter_cli.snapshot +++ b/test/fixtures/test-runner/output/spec_reporter_cli.snapshot @@ -1,6 +1,6 @@ - sync pass todo (*ms) - sync pass todo with message (*ms) - sync fail todo (*ms) + sync pass todo (*ms) # TODO + sync pass todo with message (*ms) # this is a passing todo + sync fail todo (*ms) # TODO Error: thrown from sync fail todo * * @@ -10,7 +10,7 @@ * * - sync fail todo with message (*ms) + sync fail todo with message (*ms) # this is a failing todo Error: thrown from sync fail todo with message * * @@ -21,7 +21,7 @@ * sync skip pass (*ms) # SKIP - sync skip pass with message (*ms) # SKIP + sync skip pass with message (*ms) # this is skipped sync pass (*ms) this test should pass sync throw fail (*ms) @@ -130,7 +130,7 @@ invalid subtest - pass but subtest fails (*ms) sync skip option (*ms) # SKIP - sync skip option with message (*ms) # SKIP + sync skip option with message (*ms) # this is skipped sync skip option is false fail (*ms) Error: this should be executed * @@ -149,12 +149,6 @@ (*ms) # SKIP test with a name and options provided (*ms) # SKIP functionAndOptions (*ms) # SKIP - escaped description \ # \#\ -  (*ms) - escaped skip message (*ms) # SKIP - escaped todo message (*ms) - escaped diagnostic (*ms) - #diagnostic callback pass (*ms) callback fail (*ms) Error: callback failure @@ -296,18 +290,19 @@ Warning: Test "immediate reject - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: rejected from immediate reject fail" and would have caused the test to fail, but instead triggered an unhandledRejection event. Warning: Test "callback called twice in different ticks" generated asynchronous activity after the test ended. This activity created the error "Error [ERR_TEST_FAILURE]: callback invoked multiple times" and would have caused the test to fail, but instead triggered an uncaughtException event. Warning: Test "callback async throw after done" generated asynchronous activity after the test ended. This activity created the error "Error: thrown from callback async throw after done" and would have caused the test to fail, but instead triggered an uncaughtException event. - tests 80 + tests 76 suites 0 - pass 37 + pass 35 fail 25 cancelled 3 - skipped 10 - todo 5 + skipped 9 + todo 4 duration_ms * failing tests: - sync fail todo (*ms) +* + sync fail todo (*ms) # TODO Error: thrown from sync fail todo * * @@ -317,7 +312,8 @@ * * - sync fail todo with message (*ms) +* + sync fail todo with message (*ms) # this is a failing todo Error: thrown from sync fail todo with message * * @@ -327,6 +323,7 @@ * * +* sync throw fail (*ms) Error: thrown from sync throw fail * @@ -337,6 +334,7 @@ * * +* async throw fail (*ms) Error: thrown from async throw fail * @@ -347,7 +345,8 @@ * * - async skip fail (*ms) +* + async skip fail (*ms) # SKIP Error: thrown from async throw fail * * @@ -357,6 +356,7 @@ * * +* async assertion fail (*ms) AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: @@ -376,6 +376,7 @@ operator: 'strictEqual' } +* reject fail (*ms) Error: rejected from reject fail * @@ -386,6 +387,7 @@ * * +* +sync throw fail (*ms) Error: thrown from subtest sync throw fail * @@ -399,12 +401,15 @@ * * +* sync throw non-error fail (*ms) Symbol(thrown symbol from sync throw non-error fail) +* +long running (*ms) 'test did not finish before its parent and was cancelled' +* sync skip option is false fail (*ms) Error: this should be executed * @@ -415,14 +420,17 @@ * * +* callback fail (*ms) Error: callback failure * * +* callback also returns a Promise (*ms) 'passed a callback but also returned a Promise' +* callback throw (*ms) Error: thrown from callback throw * @@ -433,9 +441,11 @@ * * +* callback called twice (*ms) 'callback invoked multiple times' +* callback called twice in future tick (*ms) Error [ERR_TEST_FAILURE]: callback invoked multiple times * { @@ -444,17 +454,21 @@ code: 'ERR_TEST_FAILURE' } +* callback async throw (*ms) Error: thrown from callback async throw * * +* custom inspect symbol fail (*ms) customized +* custom inspect symbol that throws fail (*ms) { foo: 1 } +* sync throw fails at first (*ms) Error: thrown from subtest sync throw fails at first * @@ -468,6 +482,7 @@ * * +* sync throw fails at second (*ms) Error: thrown from subtest sync throw fails at second * @@ -481,27 +496,33 @@ * * +* timed out async test (*ms) 'test timed out after *ms' +* timed out callback test (*ms) 'test timed out after *ms' +* rejected thenable (*ms) 'custom error' +* unfinished test with uncaughtException (*ms) Error: foo * * * +* unfinished test with unhandledRejection (*ms) Error: bar * * * +* assertion errors display actual and expected properly (*ms) AssertionError [ERR_ASSERTION]: Expected values to be loosely deep-equal: @@ -524,5 +545,6 @@ operator: 'deepEqual' } +* invalid subtest fail (*ms) 'test could not be started because its parent finished' diff --git a/test/fixtures/test-runner/output/spec_reporter_successful.js b/test/fixtures/test-runner/output/spec_reporter_successful.js index fb9800c0491722..a7ffeb59cc9d1e 100644 --- a/test/fixtures/test-runner/output/spec_reporter_successful.js +++ b/test/fixtures/test-runner/output/spec_reporter_successful.js @@ -1,4 +1,4 @@ -// Flags: --no-warnings --test-reporter=spec +// Flags: --test-reporter=spec 'use strict'; require('../../../common'); const { it } = require('node:test'); diff --git a/test/fixtures/test-runner/output/tap_escape.js b/test/fixtures/test-runner/output/tap_escape.js new file mode 100644 index 00000000000000..029ebea164e1ee --- /dev/null +++ b/test/fixtures/test-runner/output/tap_escape.js @@ -0,0 +1,19 @@ +'use strict'; +require('../../../common'); +const { test } = require('node:test'); + +// Do not include any failing tests in this file. + +// A test whose description needs to be escaped. +test('escaped description \\ # \\#\\ \n \t \f \v \b \r'); + +// A test whose skip message needs to be escaped. +test('escaped skip message', { skip: '#skip' }); + +// A test whose todo message needs to be escaped. +test('escaped todo message', { todo: '#todo' }); + +// A test with a diagnostic message that needs to be escaped. +test('escaped diagnostic', (t) => { + t.diagnostic('#diagnostic'); +}); diff --git a/test/fixtures/test-runner/output/tap_escape.snapshot b/test/fixtures/test-runner/output/tap_escape.snapshot new file mode 100644 index 00000000000000..722cd0ca427ec7 --- /dev/null +++ b/test/fixtures/test-runner/output/tap_escape.snapshot @@ -0,0 +1,31 @@ +TAP version 13 +# Subtest: escaped description \\ \# \\\#\\ \\n \\t \\f \\v \\b \\r +ok 1 - escaped description \\ \# \\\#\\ \\n \\t \\f \\v \\b \\r + --- + duration_ms: * + ... +# Subtest: escaped skip message +ok 2 - escaped skip message # SKIP \#skip + --- + duration_ms: * + ... +# Subtest: escaped todo message +ok 3 - escaped todo message # TODO \#todo + --- + duration_ms: * + ... +# Subtest: escaped diagnostic +ok 4 - escaped diagnostic + --- + duration_ms: * + ... +# \#diagnostic +1..4 +# tests 4 +# suites 0 +# pass 2 +# fail 0 +# cancelled 0 +# skipped 1 +# todo 1 +# duration_ms * diff --git a/test/fixtures/test-runner/output/timeout_in_before_each_should_not_affect_further_tests.js b/test/fixtures/test-runner/output/timeout_in_before_each_should_not_affect_further_tests.js new file mode 100644 index 00000000000000..6205e2c403fc86 --- /dev/null +++ b/test/fixtures/test-runner/output/timeout_in_before_each_should_not_affect_further_tests.js @@ -0,0 +1,46 @@ +const {describe, test, beforeEach, afterEach} = require("node:test"); +const {setTimeout} = require("timers/promises"); + + +describe('before each timeout', () => { + let i = 0; + + beforeEach(async () => { + if (i++ === 0) { + console.log('gonna timeout'); + await setTimeout(700); + return; + } + console.log('not gonna timeout'); + }, {timeout: 500}); + + test('first describe first test', () => { + console.log('before each test first ' + i); + }); + + test('first describe second test', () => { + console.log('before each test second ' + i); + }); +}); + + +describe('after each timeout', () => { + let i = 0; + + afterEach(async function afterEach1() { + if (i++ === 0) { + console.log('gonna timeout'); + await setTimeout(700); + return; + } + console.log('not gonna timeout'); + }, {timeout: 500}); + + test('second describe first test', () => { + console.log('after each test first ' + i); + }); + + test('second describe second test', () => { + console.log('after each test second ' + i); + }); +}); diff --git a/test/fixtures/test-runner/output/timeout_in_before_each_should_not_affect_further_tests.snapshot b/test/fixtures/test-runner/output/timeout_in_before_each_should_not_affect_further_tests.snapshot new file mode 100644 index 00000000000000..b3579da789470b --- /dev/null +++ b/test/fixtures/test-runner/output/timeout_in_before_each_should_not_affect_further_tests.snapshot @@ -0,0 +1,71 @@ +gonna timeout +TAP version 13 +not gonna timeout +before each test second 2 +after each test first 0 +gonna timeout +# Subtest: before each timeout + # Subtest: first describe first test + not ok 1 - first describe first test + --- + duration_ms: * + location: '/test/fixtures/test-runner/output/timeout_in_before_each_should_not_affect_further_tests.js:(LINE):3' + failureType: 'hookFailed' + error: 'failed running beforeEach hook' + code: 'ERR_TEST_FAILURE' + stack: |- + async Promise.all (index 0) + ... + # Subtest: first describe second test + ok 2 - first describe second test + --- + duration_ms: * + ... + 1..2 +not ok 1 - before each timeout + --- + duration_ms: * + type: 'suite' + location: '/test/fixtures/test-runner/output/timeout_in_before_each_should_not_affect_further_tests.js:(LINE):1' + failureType: 'subtestsFailed' + error: '1 subtest failed' + code: 'ERR_TEST_FAILURE' + ... +after each test second 1 +not gonna timeout +# Subtest: after each timeout + # Subtest: second describe first test + not ok 1 - second describe first test + --- + duration_ms: * + location: '/test/fixtures/test-runner/output/timeout_in_before_each_should_not_affect_further_tests.js:(LINE):3' + failureType: 'hookFailed' + error: 'failed running afterEach hook' + code: 'ERR_TEST_FAILURE' + stack: |- + async Promise.all (index 0) + ... + # Subtest: second describe second test + ok 2 - second describe second test + --- + duration_ms: * + ... + 1..2 +not ok 2 - after each timeout + --- + duration_ms: * + type: 'suite' + location: '/test/fixtures/test-runner/output/timeout_in_before_each_should_not_affect_further_tests.js:(LINE):1' + failureType: 'subtestsFailed' + error: '1 subtest failed' + code: 'ERR_TEST_FAILURE' + ... +1..2 +# tests 4 +# suites 2 +# pass 2 +# fail 2 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms * diff --git a/test/fixtures/test-runner/output/unresolved_promise.js b/test/fixtures/test-runner/output/unresolved_promise.js index a43f064d44de8e..daf2cee24b6cf9 100644 --- a/test/fixtures/test-runner/output/unresolved_promise.js +++ b/test/fixtures/test-runner/output/unresolved_promise.js @@ -1,4 +1,3 @@ -// Flags: --no-warnings 'use strict'; require('../../../common'); const test = require('node:test'); diff --git a/test/fixtures/test-runner/output/unresolved_promise.snapshot b/test/fixtures/test-runner/output/unresolved_promise.snapshot index 4b1593c3365798..0090885468c338 100644 --- a/test/fixtures/test-runner/output/unresolved_promise.snapshot +++ b/test/fixtures/test-runner/output/unresolved_promise.snapshot @@ -8,6 +8,7 @@ ok 1 - pass not ok 2 - never resolving promise --- duration_ms: * + location: '/test/fixtures/test-runner/output/unresolved_promise.js:(LINE):1' failureType: 'cancelledByParent' error: 'Promise resolution is still pending but the event loop has already resolved' code: 'ERR_TEST_FAILURE' @@ -17,7 +18,8 @@ not ok 2 - never resolving promise # Subtest: fail not ok 3 - fail --- - duration_ms: ZERO + duration_ms: * + location: '/test/fixtures/test-runner/output/unresolved_promise.js:(LINE):1' failureType: 'cancelledByParent' error: 'Promise resolution is still pending but the event loop has already resolved' code: 'ERR_TEST_FAILURE' diff --git a/test/fixtures/test-runner/shards/a.cjs b/test/fixtures/test-runner/shards/a.cjs new file mode 100644 index 00000000000000..650e61eda80b09 --- /dev/null +++ b/test/fixtures/test-runner/shards/a.cjs @@ -0,0 +1,4 @@ +'use strict'; +const test = require('node:test'); + +test('a.cjs this should pass'); diff --git a/test/fixtures/test-runner/shards/b.cjs b/test/fixtures/test-runner/shards/b.cjs new file mode 100644 index 00000000000000..12677e2505cdcf --- /dev/null +++ b/test/fixtures/test-runner/shards/b.cjs @@ -0,0 +1,4 @@ +'use strict'; +const test = require('node:test'); + +test('b.cjs this should pass'); diff --git a/test/fixtures/test-runner/shards/c.cjs b/test/fixtures/test-runner/shards/c.cjs new file mode 100644 index 00000000000000..4a4c938a74d44f --- /dev/null +++ b/test/fixtures/test-runner/shards/c.cjs @@ -0,0 +1,4 @@ +'use strict'; +const test = require('node:test'); + +test('c.cjs this should pass'); diff --git a/test/fixtures/test-runner/shards/d.cjs b/test/fixtures/test-runner/shards/d.cjs new file mode 100644 index 00000000000000..d643276b112801 --- /dev/null +++ b/test/fixtures/test-runner/shards/d.cjs @@ -0,0 +1,4 @@ +'use strict'; +const test = require('node:test'); + +test('d.cjs this should pass'); diff --git a/test/fixtures/test-runner/shards/e.cjs b/test/fixtures/test-runner/shards/e.cjs new file mode 100644 index 00000000000000..e4af3d49fcc335 --- /dev/null +++ b/test/fixtures/test-runner/shards/e.cjs @@ -0,0 +1,4 @@ +'use strict'; +const test = require('node:test'); + +test('e.cjs this should pass'); diff --git a/test/fixtures/test-runner/shards/f.cjs b/test/fixtures/test-runner/shards/f.cjs new file mode 100644 index 00000000000000..4ed5c4eb4ed841 --- /dev/null +++ b/test/fixtures/test-runner/shards/f.cjs @@ -0,0 +1,4 @@ +'use strict'; +const test = require('node:test'); + +test('f.cjs this should pass'); diff --git a/test/fixtures/test-runner/shards/g.cjs b/test/fixtures/test-runner/shards/g.cjs new file mode 100644 index 00000000000000..da8d297d35b4b7 --- /dev/null +++ b/test/fixtures/test-runner/shards/g.cjs @@ -0,0 +1,4 @@ +'use strict'; +const test = require('node:test'); + +test('g.cjs this should pass'); diff --git a/test/fixtures/test-runner/shards/h.cjs b/test/fixtures/test-runner/shards/h.cjs new file mode 100644 index 00000000000000..502250974dbc4b --- /dev/null +++ b/test/fixtures/test-runner/shards/h.cjs @@ -0,0 +1,4 @@ +'use strict'; +const test = require('node:test'); + +test('h.cjs this should pass'); diff --git a/test/fixtures/test-runner/shards/i.cjs b/test/fixtures/test-runner/shards/i.cjs new file mode 100644 index 00000000000000..42df5e74c9c483 --- /dev/null +++ b/test/fixtures/test-runner/shards/i.cjs @@ -0,0 +1,4 @@ +'use strict'; +const test = require('node:test'); + +test('i.cjs this should pass'); diff --git a/test/fixtures/test-runner/shards/j.cjs b/test/fixtures/test-runner/shards/j.cjs new file mode 100644 index 00000000000000..e2167de43d9b94 --- /dev/null +++ b/test/fixtures/test-runner/shards/j.cjs @@ -0,0 +1,4 @@ +'use strict'; +const test = require('node:test'); + +test('j.cjs this should pass'); diff --git a/test/fixtures/test-runner/test_only.js b/test/fixtures/test-runner/test_only.js new file mode 100644 index 00000000000000..efc79b9dfadca6 --- /dev/null +++ b/test/fixtures/test-runner/test_only.js @@ -0,0 +1,5 @@ +'use strict'; +const test = require('node:test'); + +test('this should be skipped'); +test.only('this should be executed'); diff --git a/test/fixtures/test-runner/todo_exit_code.js b/test/fixtures/test-runner/todo_exit_code.js new file mode 100644 index 00000000000000..6577eefe52f7dc --- /dev/null +++ b/test/fixtures/test-runner/todo_exit_code.js @@ -0,0 +1,15 @@ +const { describe, test } = require('node:test'); + +describe('suite should pass', () => { + test.todo('should fail without harming suite', () => { + throw new Error('Fail but not badly') + }); +}); + +test.todo('should fail without effecting exit code', () => { + throw new Error('Fail but not badly') +}); + +test('empty string todo', { todo: '' }, () => { + throw new Error('Fail but not badly') +}); diff --git a/test/js-native-api/2_function_arguments/2_function_arguments.c b/test/js-native-api/2_function_arguments/2_function_arguments.c index 2f7a196f65c0b3..123d9116b35c90 100644 --- a/test/js-native-api/2_function_arguments/2_function_arguments.c +++ b/test/js-native-api/2_function_arguments/2_function_arguments.c @@ -1,5 +1,6 @@ #include #include "../common.h" +#include "../entry_point.h" static napi_value Add(napi_env env, napi_callback_info info) { size_t argc = 2; diff --git a/test/js-native-api/2_function_arguments/binding.gyp b/test/js-native-api/2_function_arguments/binding.gyp index 7e35a4c9d6dc05..77836418d4736e 100644 --- a/test/js-native-api/2_function_arguments/binding.gyp +++ b/test/js-native-api/2_function_arguments/binding.gyp @@ -3,7 +3,6 @@ { "target_name": "2_function_arguments", "sources": [ - "../entry_point.c", "2_function_arguments.c" ] } diff --git a/test/js-native-api/3_callbacks/3_callbacks.c b/test/js-native-api/3_callbacks/3_callbacks.c index 3be18daff1d7a6..44bd2455749145 100644 --- a/test/js-native-api/3_callbacks/3_callbacks.c +++ b/test/js-native-api/3_callbacks/3_callbacks.c @@ -1,6 +1,7 @@ #include -#include "../common.h" #include +#include "../common.h" +#include "../entry_point.h" static napi_value RunCallback(napi_env env, napi_callback_info info) { size_t argc = 2; diff --git a/test/js-native-api/3_callbacks/binding.gyp b/test/js-native-api/3_callbacks/binding.gyp index 3cc662c4076dc1..0b3e2eb96cd903 100644 --- a/test/js-native-api/3_callbacks/binding.gyp +++ b/test/js-native-api/3_callbacks/binding.gyp @@ -3,7 +3,6 @@ { "target_name": "3_callbacks", "sources": [ - "../entry_point.c", "3_callbacks.c" ] } diff --git a/test/js-native-api/4_object_factory/4_object_factory.c b/test/js-native-api/4_object_factory/4_object_factory.c index 5b06517744dd3e..8fd6090f22a37e 100644 --- a/test/js-native-api/4_object_factory/4_object_factory.c +++ b/test/js-native-api/4_object_factory/4_object_factory.c @@ -1,5 +1,6 @@ #include #include "../common.h" +#include "../entry_point.h" static napi_value CreateObject(napi_env env, napi_callback_info info) { size_t argc = 1; diff --git a/test/js-native-api/4_object_factory/binding.gyp b/test/js-native-api/4_object_factory/binding.gyp index 6cb3a9fa68b48a..c1f2aca1498346 100644 --- a/test/js-native-api/4_object_factory/binding.gyp +++ b/test/js-native-api/4_object_factory/binding.gyp @@ -3,7 +3,6 @@ { "target_name": "4_object_factory", "sources": [ - "../entry_point.c", "4_object_factory.c" ] } diff --git a/test/js-native-api/5_function_factory/5_function_factory.c b/test/js-native-api/5_function_factory/5_function_factory.c index 679f09fee9e49e..8c2bdac5bd5f94 100644 --- a/test/js-native-api/5_function_factory/5_function_factory.c +++ b/test/js-native-api/5_function_factory/5_function_factory.c @@ -1,5 +1,6 @@ #include #include "../common.h" +#include "../entry_point.h" static napi_value MyFunction(napi_env env, napi_callback_info info) { napi_value str; diff --git a/test/js-native-api/5_function_factory/binding.gyp b/test/js-native-api/5_function_factory/binding.gyp index c621c29f185cab..183332d3441112 100644 --- a/test/js-native-api/5_function_factory/binding.gyp +++ b/test/js-native-api/5_function_factory/binding.gyp @@ -3,7 +3,6 @@ { "target_name": "5_function_factory", "sources": [ - "../entry_point.c", "5_function_factory.c" ] } diff --git a/test/js-native-api/6_object_wrap/6_object_wrap.cc b/test/js-native-api/6_object_wrap/6_object_wrap.cc index 7ebe711a6dccf1..49b1241fb38caa 100644 --- a/test/js-native-api/6_object_wrap/6_object_wrap.cc +++ b/test/js-native-api/6_object_wrap/6_object_wrap.cc @@ -1,4 +1,5 @@ #include "../common.h" +#include "../entry_point.h" #include "assert.h" #include "myobject.h" diff --git a/test/js-native-api/6_object_wrap/binding.gyp b/test/js-native-api/6_object_wrap/binding.gyp index 2807d6a1572529..44c9c3f837b4a6 100644 --- a/test/js-native-api/6_object_wrap/binding.gyp +++ b/test/js-native-api/6_object_wrap/binding.gyp @@ -3,7 +3,6 @@ { "target_name": "6_object_wrap", "sources": [ - "../entry_point.c", "6_object_wrap.cc" ] } diff --git a/test/js-native-api/7_factory_wrap/7_factory_wrap.cc b/test/js-native-api/7_factory_wrap/7_factory_wrap.cc index b1dbd8eee4945f..5fb7a6670d74d8 100644 --- a/test/js-native-api/7_factory_wrap/7_factory_wrap.cc +++ b/test/js-native-api/7_factory_wrap/7_factory_wrap.cc @@ -1,6 +1,7 @@ #include -#include "myobject.h" #include "../common.h" +#include "../entry_point.h" +#include "myobject.h" napi_value CreateObject(napi_env env, napi_callback_info info) { size_t argc = 1; diff --git a/test/js-native-api/7_factory_wrap/binding.gyp b/test/js-native-api/7_factory_wrap/binding.gyp index f9096674a70b5c..bb7c8aab1826a2 100644 --- a/test/js-native-api/7_factory_wrap/binding.gyp +++ b/test/js-native-api/7_factory_wrap/binding.gyp @@ -3,7 +3,6 @@ { "target_name": "7_factory_wrap", "sources": [ - "../entry_point.c", "7_factory_wrap.cc", "myobject.cc" ] diff --git a/test/js-native-api/8_passing_wrapped/8_passing_wrapped.cc b/test/js-native-api/8_passing_wrapped/8_passing_wrapped.cc index 5b3b7909582e21..1a3e6d1072045b 100644 --- a/test/js-native-api/8_passing_wrapped/8_passing_wrapped.cc +++ b/test/js-native-api/8_passing_wrapped/8_passing_wrapped.cc @@ -1,6 +1,7 @@ #include -#include "myobject.h" #include "../common.h" +#include "../entry_point.h" +#include "myobject.h" extern size_t finalize_count; diff --git a/test/js-native-api/8_passing_wrapped/binding.gyp b/test/js-native-api/8_passing_wrapped/binding.gyp index f85cc4cc97ae45..206d106e52cf94 100644 --- a/test/js-native-api/8_passing_wrapped/binding.gyp +++ b/test/js-native-api/8_passing_wrapped/binding.gyp @@ -3,7 +3,6 @@ { "target_name": "8_passing_wrapped", "sources": [ - "../entry_point.c", "8_passing_wrapped.cc", "myobject.cc" ] diff --git a/test/js-native-api/common-inl.h b/test/js-native-api/common-inl.h new file mode 100644 index 00000000000000..d4db4a3e58bdc6 --- /dev/null +++ b/test/js-native-api/common-inl.h @@ -0,0 +1,56 @@ +#ifndef JS_NATIVE_API_COMMON_INL_H_ +#define JS_NATIVE_API_COMMON_INL_H_ + +#include +#include "common.h" + +#include + +inline void add_returned_status(napi_env env, + const char* key, + napi_value object, + char* expected_message, + napi_status expected_status, + napi_status actual_status) { + char napi_message_string[100] = ""; + napi_value prop_value; + + if (actual_status != expected_status) { + snprintf(napi_message_string, + sizeof(napi_message_string), + "Invalid status [%d]", + actual_status); + } + + NODE_API_CALL_RETURN_VOID( + env, + napi_create_string_utf8( + env, + (actual_status == expected_status ? expected_message + : napi_message_string), + NAPI_AUTO_LENGTH, + &prop_value)); + NODE_API_CALL_RETURN_VOID( + env, napi_set_named_property(env, object, key, prop_value)); +} + +inline void add_last_status(napi_env env, + const char* key, + napi_value return_value) { + napi_value prop_value; + const napi_extended_error_info* p_last_error; + NODE_API_CALL_RETURN_VOID(env, napi_get_last_error_info(env, &p_last_error)); + + NODE_API_CALL_RETURN_VOID( + env, + napi_create_string_utf8( + env, + (p_last_error->error_message == NULL ? "napi_ok" + : p_last_error->error_message), + NAPI_AUTO_LENGTH, + &prop_value)); + NODE_API_CALL_RETURN_VOID( + env, napi_set_named_property(env, return_value, key, prop_value)); +} + +#endif // JS_NATIVE_API_COMMON_INL_H_ diff --git a/test/js-native-api/common.c b/test/js-native-api/common.c deleted file mode 100644 index 865d2064bdef85..00000000000000 --- a/test/js-native-api/common.c +++ /dev/null @@ -1,48 +0,0 @@ -#include -#include "common.h" - -#include - -void add_returned_status(napi_env env, - const char* key, - napi_value object, - char* expected_message, - napi_status expected_status, - napi_status actual_status) { - - char napi_message_string[100] = ""; - napi_value prop_value; - - if (actual_status != expected_status) { - snprintf(napi_message_string, sizeof(napi_message_string), - "Invalid status [%d]", actual_status); - } - - NODE_API_CALL_RETURN_VOID(env, - napi_create_string_utf8( - env, - (actual_status == expected_status ? - expected_message : - napi_message_string), - NAPI_AUTO_LENGTH, - &prop_value)); - NODE_API_CALL_RETURN_VOID(env, - napi_set_named_property(env, object, key, prop_value)); -} - -void add_last_status(napi_env env, const char* key, napi_value return_value) { - napi_value prop_value; - const napi_extended_error_info* p_last_error; - NODE_API_CALL_RETURN_VOID(env, - napi_get_last_error_info(env, &p_last_error)); - - NODE_API_CALL_RETURN_VOID(env, - napi_create_string_utf8(env, - (p_last_error->error_message == NULL ? - "napi_ok" : - p_last_error->error_message), - NAPI_AUTO_LENGTH, - &prop_value)); - NODE_API_CALL_RETURN_VOID(env, - napi_set_named_property(env, return_value, key, prop_value)); -} diff --git a/test/js-native-api/common.h b/test/js-native-api/common.h index 25b26fb09137c5..fc6f4cb6c2e1db 100644 --- a/test/js-native-api/common.h +++ b/test/js-native-api/common.h @@ -1,3 +1,6 @@ +#ifndef JS_NATIVE_API_COMMON_H_ +#define JS_NATIVE_API_COMMON_H_ + #include // Empty value so that macros here are able to return NULL or void @@ -76,11 +79,17 @@ #define DECLARE_NODE_API_PROPERTY_VALUE(name, value) \ { (name), NULL, NULL, NULL, NULL, (value), napi_default, NULL } -void add_returned_status(napi_env env, - const char* key, - napi_value object, - char* expected_message, - napi_status expected_status, - napi_status actual_status); +static inline void add_returned_status(napi_env env, + const char* key, + napi_value object, + char* expected_message, + napi_status expected_status, + napi_status actual_status); + +static inline void add_last_status(napi_env env, + const char* key, + napi_value return_value); + +#include "common-inl.h" -void add_last_status(napi_env env, const char* key, napi_value return_value); +#endif // JS_NATIVE_API_COMMON_H_ diff --git a/test/js-native-api/entry_point.c b/test/js-native-api/entry_point.c deleted file mode 100644 index 6b7b50a38c9535..00000000000000 --- a/test/js-native-api/entry_point.c +++ /dev/null @@ -1,7 +0,0 @@ -#include - -EXTERN_C_START -napi_value Init(napi_env env, napi_value exports); -EXTERN_C_END - -NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) diff --git a/test/js-native-api/entry_point.h b/test/js-native-api/entry_point.h new file mode 100644 index 00000000000000..5ba5aaffa62312 --- /dev/null +++ b/test/js-native-api/entry_point.h @@ -0,0 +1,12 @@ +#ifndef JS_NATIVE_API_ENTRY_POINT_H_ +#define JS_NATIVE_API_ENTRY_POINT_H_ + +#include + +EXTERN_C_START +napi_value Init(napi_env env, napi_value exports); +EXTERN_C_END + +NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) + +#endif // JS_NATIVE_API_ENTRY_POINT_H_ diff --git a/test/js-native-api/test_array/binding.gyp b/test/js-native-api/test_array/binding.gyp index feb6bd37d88b28..ba19b16e397ad8 100644 --- a/test/js-native-api/test_array/binding.gyp +++ b/test/js-native-api/test_array/binding.gyp @@ -3,7 +3,6 @@ { "target_name": "test_array", "sources": [ - "../entry_point.c", "test_array.c" ] } diff --git a/test/js-native-api/test_array/test_array.c b/test/js-native-api/test_array/test_array.c index 846755a97b7059..a4515025fc217c 100644 --- a/test/js-native-api/test_array/test_array.c +++ b/test/js-native-api/test_array/test_array.c @@ -1,6 +1,7 @@ #include #include #include "../common.h" +#include "../entry_point.h" static napi_value TestGetElement(napi_env env, napi_callback_info info) { size_t argc = 2; diff --git a/test/js-native-api/test_bigint/binding.gyp b/test/js-native-api/test_bigint/binding.gyp index 84db32bf3ea131..6ef04b4394ae8a 100644 --- a/test/js-native-api/test_bigint/binding.gyp +++ b/test/js-native-api/test_bigint/binding.gyp @@ -3,7 +3,6 @@ { "target_name": "test_bigint", "sources": [ - "../entry_point.c", "test_bigint.c" ] } diff --git a/test/js-native-api/test_bigint/test_bigint.c b/test/js-native-api/test_bigint/test_bigint.c index c63c2f7fe29b44..2c61e0b217ecb4 100644 --- a/test/js-native-api/test_bigint/test_bigint.c +++ b/test/js-native-api/test_bigint/test_bigint.c @@ -1,8 +1,9 @@ -#include #include -#include #include +#include +#include #include "../common.h" +#include "../entry_point.h" static napi_value IsLossless(napi_env env, napi_callback_info info) { size_t argc = 2; diff --git a/test/js-native-api/test_cannot_run_js/binding.gyp b/test/js-native-api/test_cannot_run_js/binding.gyp index 210417b47b17ec..0b827ff34d129f 100644 --- a/test/js-native-api/test_cannot_run_js/binding.gyp +++ b/test/js-native-api/test_cannot_run_js/binding.gyp @@ -1,32 +1,18 @@ { "targets": [ - { - "target_name": "copy_entry_point", - "type": "none", - "copies": [ - { - "destination": ".", - "files": [ "../entry_point.c" ] - } - ] - }, { "target_name": "test_cannot_run_js", "sources": [ - "entry_point.c", "test_cannot_run_js.c" ], "defines": [ "NAPI_EXPERIMENTAL" ], - "dependencies": [ "copy_entry_point" ], }, { "target_name": "test_pending_exception", "sources": [ - "entry_point.c", "test_cannot_run_js.c" ], "defines": [ "NAPI_VERSION=8" ], - "dependencies": [ "copy_entry_point" ], } ] } diff --git a/test/js-native-api/test_cannot_run_js/test_cannot_run_js.c b/test/js-native-api/test_cannot_run_js/test_cannot_run_js.c index 6f2a6e71b8dc22..2cd25823c924c0 100644 --- a/test/js-native-api/test_cannot_run_js/test_cannot_run_js.c +++ b/test/js-native-api/test_cannot_run_js/test_cannot_run_js.c @@ -1,5 +1,6 @@ #include #include "../common.h" +#include "../entry_point.h" #include "stdlib.h" static void Finalize(napi_env env, void* data, void* hint) { diff --git a/test/js-native-api/test_constructor/binding.gyp b/test/js-native-api/test_constructor/binding.gyp index 019114f64651c6..d796a9dbf1cf44 100644 --- a/test/js-native-api/test_constructor/binding.gyp +++ b/test/js-native-api/test_constructor/binding.gyp @@ -3,8 +3,6 @@ { "target_name": "test_constructor", "sources": [ - "../common.c", - "../entry_point.c", "test_constructor.c", "test_null.c", ] diff --git a/test/js-native-api/test_constructor/test_constructor.c b/test/js-native-api/test_constructor/test_constructor.c index 92b03985513d36..c706170bac4a8c 100644 --- a/test/js-native-api/test_constructor/test_constructor.c +++ b/test/js-native-api/test_constructor/test_constructor.c @@ -1,5 +1,6 @@ #include #include "../common.h" +#include "../entry_point.h" #include "test_null.h" static double value_ = 1; diff --git a/test/js-native-api/test_conversions/binding.gyp b/test/js-native-api/test_conversions/binding.gyp index f1640c6638e41e..c286c3fd029203 100644 --- a/test/js-native-api/test_conversions/binding.gyp +++ b/test/js-native-api/test_conversions/binding.gyp @@ -3,8 +3,6 @@ { "target_name": "test_conversions", "sources": [ - "../entry_point.c", - "../common.c", "test_conversions.c", "test_null.c", ] diff --git a/test/js-native-api/test_conversions/test_conversions.c b/test/js-native-api/test_conversions/test_conversions.c index 500962d5144e0f..89b93ef0112513 100644 --- a/test/js-native-api/test_conversions/test_conversions.c +++ b/test/js-native-api/test_conversions/test_conversions.c @@ -1,5 +1,6 @@ #include #include "../common.h" +#include "../entry_point.h" #include "test_null.h" static napi_value AsBool(napi_env env, napi_callback_info info) { diff --git a/test/js-native-api/test_dataview/binding.gyp b/test/js-native-api/test_dataview/binding.gyp index b8d641f5c0f34e..64235390812d79 100644 --- a/test/js-native-api/test_dataview/binding.gyp +++ b/test/js-native-api/test_dataview/binding.gyp @@ -3,7 +3,6 @@ { "target_name": "test_dataview", "sources": [ - "../entry_point.c", "test_dataview.c" ] } diff --git a/test/js-native-api/test_dataview/test_dataview.c b/test/js-native-api/test_dataview/test_dataview.c index c614a79818cb85..9f62b734c6a9ef 100644 --- a/test/js-native-api/test_dataview/test_dataview.c +++ b/test/js-native-api/test_dataview/test_dataview.c @@ -1,6 +1,7 @@ #include #include #include "../common.h" +#include "../entry_point.h" static napi_value CreateDataView(napi_env env, napi_callback_info info) { size_t argc = 3; diff --git a/test/js-native-api/test_date/binding.gyp b/test/js-native-api/test_date/binding.gyp index a65a4e1387235a..6039d122c7649a 100644 --- a/test/js-native-api/test_date/binding.gyp +++ b/test/js-native-api/test_date/binding.gyp @@ -3,7 +3,6 @@ { "target_name": "test_date", "sources": [ - "../entry_point.c", "test_date.c" ] } diff --git a/test/js-native-api/test_date/test_date.c b/test/js-native-api/test_date/test_date.c index d5e9c778a9cd8f..ef87d6da350d02 100644 --- a/test/js-native-api/test_date/test_date.c +++ b/test/js-native-api/test_date/test_date.c @@ -1,5 +1,6 @@ #include #include "../common.h" +#include "../entry_point.h" static napi_value createDate(napi_env env, napi_callback_info info) { size_t argc = 1; diff --git a/test/js-native-api/test_error/binding.gyp b/test/js-native-api/test_error/binding.gyp index 617ececb89fcb5..46382427fe669c 100644 --- a/test/js-native-api/test_error/binding.gyp +++ b/test/js-native-api/test_error/binding.gyp @@ -3,7 +3,6 @@ { "target_name": "test_error", "sources": [ - "../entry_point.c", "test_error.c" ] } diff --git a/test/js-native-api/test_error/test_error.c b/test/js-native-api/test_error/test_error.c index 43e98921efadb0..f34798263dba3e 100644 --- a/test/js-native-api/test_error/test_error.c +++ b/test/js-native-api/test_error/test_error.c @@ -1,6 +1,7 @@ #define NAPI_VERSION 9 #include #include "../common.h" +#include "../entry_point.h" static napi_value checkError(napi_env env, napi_callback_info info) { size_t argc = 1; diff --git a/test/js-native-api/test_exception/binding.gyp b/test/js-native-api/test_exception/binding.gyp index 4844346a139338..e98a564a10feac 100644 --- a/test/js-native-api/test_exception/binding.gyp +++ b/test/js-native-api/test_exception/binding.gyp @@ -3,7 +3,6 @@ { "target_name": "test_exception", "sources": [ - "../entry_point.c", "test_exception.c" ] } diff --git a/test/js-native-api/test_exception/test_exception.c b/test/js-native-api/test_exception/test_exception.c index 053f048466d930..84b991961ae136 100644 --- a/test/js-native-api/test_exception/test_exception.c +++ b/test/js-native-api/test_exception/test_exception.c @@ -1,5 +1,6 @@ #include #include "../common.h" +#include "../entry_point.h" static bool exceptionWasPending = false; static int num = 0x23432; diff --git a/test/js-native-api/test_finalizer/binding.gyp b/test/js-native-api/test_finalizer/binding.gyp new file mode 100644 index 00000000000000..4c63346f30ce74 --- /dev/null +++ b/test/js-native-api/test_finalizer/binding.gyp @@ -0,0 +1,11 @@ +{ + "targets": [ + { + "target_name": "test_finalizer", + "defines": [ "NAPI_EXPERIMENTAL" ], + "sources": [ + "test_finalizer.c" + ] + } + ] +} diff --git a/test/js-native-api/test_finalizer/test.js b/test/js-native-api/test_finalizer/test.js new file mode 100644 index 00000000000000..cfbf57239c3a6d --- /dev/null +++ b/test/js-native-api/test_finalizer/test.js @@ -0,0 +1,43 @@ +'use strict'; +// Flags: --expose-gc + +const common = require('../../common'); +const test_finalizer = require(`./build/${common.buildType}/test_finalizer`); +const assert = require('assert'); + +// The goal of this test is to show that we can run "pure" finalizers in the +// current JS loop tick. Thus, we do not use common.gcUntil function works +// asynchronously using micro tasks. +// We use IIFE for the obj scope instead of {} to be compatible with +// non-V8 JS engines that do not support scoped variables. +(() => { + const obj = {}; + test_finalizer.addFinalizer(obj); +})(); + +for (let i = 0; i < 10; ++i) { + global.gc(); + if (test_finalizer.getFinalizerCallCount() === 1) { + break; + } +} + +assert.strictEqual(test_finalizer.getFinalizerCallCount(), 1); + +// The finalizer that access JS cannot run synchronously. They are run in the +// next JS loop tick. Thus, we must use common.gcUntil. +async function runAsyncTests() { + // We do not use common.mustCall() because we want to see the finalizer + // called in response to GC and not as a part of env destruction. + let js_is_called = false; + // We use IIFE for the obj scope instead of {} to be compatible with + // non-V8 JS engines that do not support scoped variables. + (() => { + const obj = {}; + test_finalizer.addFinalizerWithJS(obj, () => { js_is_called = true; }); + })(); + await common.gcUntil('ensure JS finalizer called', + () => (test_finalizer.getFinalizerCallCount() === 2)); + assert(js_is_called); +} +runAsyncTests(); diff --git a/test/js-native-api/test_finalizer/test_fatal_finalize.js b/test/js-native-api/test_finalizer/test_fatal_finalize.js new file mode 100644 index 00000000000000..352310128a97f6 --- /dev/null +++ b/test/js-native-api/test_finalizer/test_fatal_finalize.js @@ -0,0 +1,31 @@ +'use strict'; +const common = require('../../common'); + +if (process.argv[2] === 'child') { + const test_finalizer = require(`./build/${common.buildType}/test_finalizer`); + + (() => { + const obj = {}; + test_finalizer.addFinalizerFailOnJS(obj); + })(); + + // Collect garbage 10 times. At least one of those should throw the exception + // and cause the whole process to bail with it, its text printed to stderr and + // asserted by the parent process to match expectations. + let gcCount = 10; + (function gcLoop() { + global.gc(); + if (--gcCount > 0) { + setImmediate(() => gcLoop()); + } + })(); + return; +} + +const assert = require('assert'); +const { spawnSync } = require('child_process'); +const child = spawnSync(process.execPath, [ + '--expose-gc', __filename, 'child', +]); +assert.strictEqual(child.signal, common.isWindows ? null : 'SIGABRT'); +assert.match(child.stderr.toString(), /Finalizer is calling a function that may affect GC state/); diff --git a/test/js-native-api/test_finalizer/test_finalizer.c b/test/js-native-api/test_finalizer/test_finalizer.c new file mode 100644 index 00000000000000..378781b7042f96 --- /dev/null +++ b/test/js-native-api/test_finalizer/test_finalizer.c @@ -0,0 +1,146 @@ +#include +#include +#include +#include +#include +#include "../common.h" +#include "../entry_point.h" + +typedef struct { + int32_t finalize_count; + napi_ref js_func; +} FinalizerData; + +static void finalizerOnlyCallback(napi_env env, + void* finalize_data, + void* finalize_hint) { + FinalizerData* data = (FinalizerData*)finalize_data; + int32_t count = ++data->finalize_count; + + // It is safe to access instance data + NODE_API_CALL_RETURN_VOID(env, napi_get_instance_data(env, (void**)&data)); + NODE_API_ASSERT_RETURN_VOID(env, + count = data->finalize_count, + "Expected to be the same FinalizerData"); +} + +static void finalizerCallingJSCallback(napi_env env, + void* finalize_data, + void* finalize_hint) { + napi_value js_func, undefined; + FinalizerData* data = (FinalizerData*)finalize_data; + NODE_API_CALL_RETURN_VOID( + env, napi_get_reference_value(env, data->js_func, &js_func)); + NODE_API_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined)); + NODE_API_CALL_RETURN_VOID( + env, napi_call_function(env, undefined, js_func, 0, NULL, NULL)); + NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, data->js_func)); + data->js_func = NULL; + ++data->finalize_count; +} + +// Schedule async finalizer to run JavaScript-touching code. +static void finalizerWithJSCallback(napi_env env, + void* finalize_data, + void* finalize_hint) { + NODE_API_CALL_RETURN_VOID( + env, + node_api_post_finalizer( + env, finalizerCallingJSCallback, finalize_data, finalize_hint)); +} + +static void finalizerWithFailedJSCallback(napi_env env, + void* finalize_data, + void* finalize_hint) { + napi_value obj; + FinalizerData* data = (FinalizerData*)finalize_data; + ++data->finalize_count; + NODE_API_CALL_RETURN_VOID(env, napi_create_object(env, &obj)); +} + +static napi_value addFinalizer(napi_env env, napi_callback_info info) { + size_t argc = 1; + napi_value argv[1] = {0}; + FinalizerData* data; + + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + NODE_API_CALL(env, napi_get_instance_data(env, (void**)&data)); + NODE_API_CALL(env, + napi_add_finalizer( + env, argv[0], data, finalizerOnlyCallback, NULL, NULL)); + return NULL; +} + +// This finalizer is going to call JavaScript from finalizer and succeed. +static napi_value addFinalizerWithJS(napi_env env, napi_callback_info info) { + size_t argc = 2; + napi_value argv[2] = {0}; + napi_valuetype arg_type; + FinalizerData* data; + + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + NODE_API_CALL(env, napi_get_instance_data(env, (void**)&data)); + NODE_API_CALL(env, napi_typeof(env, argv[1], &arg_type)); + NODE_API_ASSERT( + env, arg_type == napi_function, "Expected function as the second arg"); + NODE_API_CALL(env, napi_create_reference(env, argv[1], 1, &data->js_func)); + NODE_API_CALL(env, + napi_add_finalizer( + env, argv[0], data, finalizerWithJSCallback, NULL, NULL)); + return NULL; +} + +// This finalizer is going to call JavaScript from finalizer and fail. +static napi_value addFinalizerFailOnJS(napi_env env, napi_callback_info info) { + size_t argc = 1; + napi_value argv[1] = {0}; + FinalizerData* data; + + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + NODE_API_CALL(env, napi_get_instance_data(env, (void**)&data)); + NODE_API_CALL( + env, + napi_add_finalizer( + env, argv[0], data, finalizerWithFailedJSCallback, NULL, NULL)); + return NULL; +} + +static napi_value getFinalizerCallCount(napi_env env, napi_callback_info info) { + size_t argc = 1; + napi_value argv[1]; + FinalizerData* data; + napi_value result; + + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + NODE_API_CALL(env, napi_get_instance_data(env, (void**)&data)); + NODE_API_CALL(env, napi_create_int32(env, data->finalize_count, &result)); + return result; +} + +static void finalizeData(napi_env env, void* data, void* hint) { + free(data); +} + +EXTERN_C_START +napi_value Init(napi_env env, napi_value exports) { + FinalizerData* data = (FinalizerData*)malloc(sizeof(FinalizerData)); + NODE_API_ASSERT(env, data != NULL, "Failed to allocate memory"); + memset(data, 0, sizeof(FinalizerData)); + NODE_API_CALL(env, napi_set_instance_data(env, data, finalizeData, NULL)); + napi_property_descriptor descriptors[] = { + DECLARE_NODE_API_PROPERTY("addFinalizer", addFinalizer), + DECLARE_NODE_API_PROPERTY("addFinalizerWithJS", addFinalizerWithJS), + DECLARE_NODE_API_PROPERTY("addFinalizerFailOnJS", addFinalizerFailOnJS), + DECLARE_NODE_API_PROPERTY("getFinalizerCallCount", + getFinalizerCallCount)}; + + NODE_API_CALL( + env, + napi_define_properties(env, + exports, + sizeof(descriptors) / sizeof(*descriptors), + descriptors)); + + return exports; +} +EXTERN_C_END diff --git a/test/js-native-api/test_function/binding.gyp b/test/js-native-api/test_function/binding.gyp index df70facefc00cb..7ea9400c351b88 100644 --- a/test/js-native-api/test_function/binding.gyp +++ b/test/js-native-api/test_function/binding.gyp @@ -3,8 +3,6 @@ { "target_name": "test_function", "sources": [ - "../common.c", - "../entry_point.c", "test_function.c" ] } diff --git a/test/js-native-api/test_function/test_function.c b/test/js-native-api/test_function/test_function.c index 107727872a0655..02a2988dc3e265 100644 --- a/test/js-native-api/test_function/test_function.c +++ b/test/js-native-api/test_function/test_function.c @@ -1,5 +1,6 @@ #include #include "../common.h" +#include "../entry_point.h" static napi_value TestCreateFunctionParameters(napi_env env, napi_callback_info info) { diff --git a/test/js-native-api/test_general/binding.gyp b/test/js-native-api/test_general/binding.gyp index 6a766dc5e40131..577a506f7fad73 100644 --- a/test/js-native-api/test_general/binding.gyp +++ b/test/js-native-api/test_general/binding.gyp @@ -3,7 +3,6 @@ { "target_name": "test_general", "sources": [ - "../entry_point.c", "test_general.c" ] } diff --git a/test/js-native-api/test_general/test_general.c b/test/js-native-api/test_general/test_general.c index b474ab442cb763..0cd1c54ee142f1 100644 --- a/test/js-native-api/test_general/test_general.c +++ b/test/js-native-api/test_general/test_general.c @@ -3,11 +3,12 @@ // not related to any of the other tests // defined in the file #define NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED +#include +#include #include #include -#include -#include #include "../common.h" +#include "../entry_point.h" static napi_value testStrictEquals(napi_env env, napi_callback_info info) { size_t argc = 2; diff --git a/test/js-native-api/test_handle_scope/binding.gyp b/test/js-native-api/test_handle_scope/binding.gyp index 842bd5af7444ae..7959c47cb9039e 100644 --- a/test/js-native-api/test_handle_scope/binding.gyp +++ b/test/js-native-api/test_handle_scope/binding.gyp @@ -3,7 +3,6 @@ { "target_name": "test_handle_scope", "sources": [ - "../entry_point.c", "test_handle_scope.c" ] } diff --git a/test/js-native-api/test_handle_scope/test_handle_scope.c b/test/js-native-api/test_handle_scope/test_handle_scope.c index 681cc04c4f4b68..832ce545d1fabe 100644 --- a/test/js-native-api/test_handle_scope/test_handle_scope.c +++ b/test/js-native-api/test_handle_scope/test_handle_scope.c @@ -1,6 +1,7 @@ #include -#include "../common.h" #include +#include "../common.h" +#include "../entry_point.h" // these tests validate the handle scope functions in the normal // flow. Forcing gc behavior to fully validate they are doing diff --git a/test/js-native-api/test_instance_data/binding.gyp b/test/js-native-api/test_instance_data/binding.gyp index 5b2d4ff328b4fa..0d55905e9e7236 100644 --- a/test/js-native-api/test_instance_data/binding.gyp +++ b/test/js-native-api/test_instance_data/binding.gyp @@ -3,7 +3,6 @@ { "target_name": "test_instance_data", "sources": [ - "../entry_point.c", "test_instance_data.c" ] } diff --git a/test/js-native-api/test_instance_data/test_instance_data.c b/test/js-native-api/test_instance_data/test_instance_data.c index 95d41ed5f64994..5e33ddd75d47a5 100644 --- a/test/js-native-api/test_instance_data/test_instance_data.c +++ b/test/js-native-api/test_instance_data/test_instance_data.c @@ -1,7 +1,8 @@ +#include #include #include -#include #include "../common.h" +#include "../entry_point.h" typedef struct { size_t value; diff --git a/test/js-native-api/test_new_target/binding.gyp b/test/js-native-api/test_new_target/binding.gyp index f9cc6e83758ced..1afe797d1402b8 100644 --- a/test/js-native-api/test_new_target/binding.gyp +++ b/test/js-native-api/test_new_target/binding.gyp @@ -4,7 +4,6 @@ 'target_name': 'test_new_target', 'defines': [ 'V8_DEPRECATION_WARNINGS=1' ], 'sources': [ - '../entry_point.c', 'test_new_target.c' ] } diff --git a/test/js-native-api/test_new_target/test_new_target.c b/test/js-native-api/test_new_target/test_new_target.c index d3fe5b0d2d9568..4e2be97419c7f3 100644 --- a/test/js-native-api/test_new_target/test_new_target.c +++ b/test/js-native-api/test_new_target/test_new_target.c @@ -1,5 +1,6 @@ #include #include "../common.h" +#include "../entry_point.h" static napi_value BaseClass(napi_env env, napi_callback_info info) { napi_value newTargetArg; diff --git a/test/js-native-api/test_number/binding.gyp b/test/js-native-api/test_number/binding.gyp index fa65304ba54089..c0a4cb62d9803e 100644 --- a/test/js-native-api/test_number/binding.gyp +++ b/test/js-native-api/test_number/binding.gyp @@ -3,8 +3,6 @@ { "target_name": "test_number", "sources": [ - "../common.c", - "../entry_point.c", "test_number.c", "test_null.c", ] diff --git a/test/js-native-api/test_number/test_number.c b/test/js-native-api/test_number/test_number.c index c8d4733f580a05..b8169451e62ad1 100644 --- a/test/js-native-api/test_number/test_number.c +++ b/test/js-native-api/test_number/test_number.c @@ -1,5 +1,6 @@ #include #include "../common.h" +#include "../entry_point.h" #include "test_null.h" static napi_value Test(napi_env env, napi_callback_info info) { diff --git a/test/js-native-api/test_object/binding.gyp b/test/js-native-api/test_object/binding.gyp index e681f98f73ace6..b81f502584619e 100644 --- a/test/js-native-api/test_object/binding.gyp +++ b/test/js-native-api/test_object/binding.gyp @@ -3,8 +3,6 @@ { "target_name": "test_object", "sources": [ - "../common.c", - "../entry_point.c", "test_null.c", "test_object.c" ] diff --git a/test/js-native-api/test_object/test_object.c b/test/js-native-api/test_object/test_object.c index eb5aa2071e30a3..eddf805187507e 100644 --- a/test/js-native-api/test_object/test_object.c +++ b/test/js-native-api/test_object/test_object.c @@ -1,6 +1,7 @@ #include -#include "../common.h" #include +#include "../common.h" +#include "../entry_point.h" #include "test_null.h" static int test_value = 3; diff --git a/test/js-native-api/test_promise/binding.gyp b/test/js-native-api/test_promise/binding.gyp index fd777daf5e02cc..de2802f8607dcf 100644 --- a/test/js-native-api/test_promise/binding.gyp +++ b/test/js-native-api/test_promise/binding.gyp @@ -3,7 +3,6 @@ { "target_name": "test_promise", "sources": [ - "../entry_point.c", "test_promise.c" ] } diff --git a/test/js-native-api/test_promise/test_promise.c b/test/js-native-api/test_promise/test_promise.c index 488ecea7853601..eef4813aa63774 100644 --- a/test/js-native-api/test_promise/test_promise.c +++ b/test/js-native-api/test_promise/test_promise.c @@ -1,5 +1,6 @@ #include #include "../common.h" +#include "../entry_point.h" napi_deferred deferred = NULL; diff --git a/test/js-native-api/test_properties/binding.gyp b/test/js-native-api/test_properties/binding.gyp index adb6dd5ea151c3..ee38504eea75a6 100644 --- a/test/js-native-api/test_properties/binding.gyp +++ b/test/js-native-api/test_properties/binding.gyp @@ -3,7 +3,6 @@ { "target_name": "test_properties", "sources": [ - "../entry_point.c", "test_properties.c" ] } diff --git a/test/js-native-api/test_properties/test_properties.c b/test/js-native-api/test_properties/test_properties.c index d822d3628d87fa..567dd8c3a44ecd 100644 --- a/test/js-native-api/test_properties/test_properties.c +++ b/test/js-native-api/test_properties/test_properties.c @@ -1,6 +1,7 @@ #define NAPI_VERSION 9 #include #include "../common.h" +#include "../entry_point.h" static double value_ = 1; diff --git a/test/js-native-api/test_reference/binding.gyp b/test/js-native-api/test_reference/binding.gyp index 518fd21c37c566..a9d81ef9d2c05d 100644 --- a/test/js-native-api/test_reference/binding.gyp +++ b/test/js-native-api/test_reference/binding.gyp @@ -3,9 +3,14 @@ { "target_name": "test_reference", "sources": [ - "../entry_point.c", "test_reference.c" ] + }, + { + "target_name": "test_finalizer", + "sources": [ + "test_finalizer.c" + ] } ] } diff --git a/test/js-native-api/test_reference/test_finalizer.c b/test/js-native-api/test_reference/test_finalizer.c new file mode 100644 index 00000000000000..51492d9623f69c --- /dev/null +++ b/test/js-native-api/test_reference/test_finalizer.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include "../common.h" +#include "../entry_point.h" + +static int test_value = 1; +static int finalize_count = 0; + +static void FinalizeExternalCallJs(napi_env env, void* data, void* hint) { + int* actual_value = data; + NODE_API_ASSERT_RETURN_VOID( + env, + actual_value == &test_value, + "The correct pointer was passed to the finalizer"); + + napi_ref finalizer_ref = (napi_ref)hint; + napi_value js_finalizer; + napi_value recv; + NODE_API_CALL_RETURN_VOID( + env, napi_get_reference_value(env, finalizer_ref, &js_finalizer)); + NODE_API_CALL_RETURN_VOID(env, napi_get_global(env, &recv)); + NODE_API_CALL_RETURN_VOID( + env, napi_call_function(env, recv, js_finalizer, 0, NULL, NULL)); + NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, finalizer_ref)); +} + +static napi_value CreateExternalWithJsFinalize(napi_env env, + napi_callback_info info) { + size_t argc = 1; + napi_value args[1]; + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_ASSERT(env, argc == 1, "Wrong number of arguments"); + napi_value finalizer = args[0]; + napi_valuetype finalizer_valuetype; + NODE_API_CALL(env, napi_typeof(env, finalizer, &finalizer_valuetype)); + NODE_API_ASSERT(env, + finalizer_valuetype == napi_function, + "Wrong type of first argument"); + napi_ref finalizer_ref; + NODE_API_CALL(env, napi_create_reference(env, finalizer, 1, &finalizer_ref)); + + napi_value result; + NODE_API_CALL(env, + napi_create_external(env, + &test_value, + FinalizeExternalCallJs, + finalizer_ref, /* finalize_hint */ + &result)); + + finalize_count = 0; + return result; +} + +EXTERN_C_START +napi_value Init(napi_env env, napi_value exports) { + napi_property_descriptor descriptors[] = { + DECLARE_NODE_API_PROPERTY("createExternalWithJsFinalize", + CreateExternalWithJsFinalize), + }; + + NODE_API_CALL( + env, + napi_define_properties(env, + exports, + sizeof(descriptors) / sizeof(*descriptors), + descriptors)); + + return exports; +} +EXTERN_C_END diff --git a/test/js-native-api/test_reference/test_finalizer.js b/test/js-native-api/test_reference/test_finalizer.js index b70582fd0342fe..a5270512dc87c1 100644 --- a/test/js-native-api/test_reference/test_finalizer.js +++ b/test/js-native-api/test_reference/test_finalizer.js @@ -2,7 +2,7 @@ // Flags: --expose-gc --force-node-api-uncaught-exceptions-policy const common = require('../../common'); -const test_reference = require(`./build/${common.buildType}/test_reference`); +const binding = require(`./build/${common.buildType}/test_finalizer`); const assert = require('assert'); process.on('uncaughtException', common.mustCall((err) => { @@ -11,7 +11,7 @@ process.on('uncaughtException', common.mustCall((err) => { (async function() { { - test_reference.createExternalWithJsFinalize( + binding.createExternalWithJsFinalize( common.mustCall(() => { throw new Error('finalizer error'); })); diff --git a/test/js-native-api/test_reference/test_reference.c b/test/js-native-api/test_reference/test_reference.c index c17f27021b4215..058be07363588b 100644 --- a/test/js-native-api/test_reference/test_reference.c +++ b/test/js-native-api/test_reference/test_reference.c @@ -1,8 +1,9 @@ #define NAPI_VERSION 9 -#include #include #include +#include #include "../common.h" +#include "../entry_point.h" static int test_value = 1; static int finalize_count = 0; @@ -21,20 +22,6 @@ static void FinalizeExternal(napi_env env, void* data, void* hint) { finalize_count++; } -static void FinalizeExternalCallJs(napi_env env, void* data, void* hint) { - int *actual_value = data; - NODE_API_ASSERT_RETURN_VOID(env, actual_value == &test_value, - "The correct pointer was passed to the finalizer"); - - napi_ref finalizer_ref = (napi_ref)hint; - napi_value js_finalizer; - napi_value recv; - NODE_API_CALL_RETURN_VOID(env, napi_get_reference_value(env, finalizer_ref, &js_finalizer)); - NODE_API_CALL_RETURN_VOID(env, napi_get_global(env, &recv)); - NODE_API_CALL_RETURN_VOID(env, napi_call_function(env, recv, js_finalizer, 0, NULL, NULL)); - NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, finalizer_ref)); -} - static napi_value CreateExternal(napi_env env, napi_callback_info info) { int* data = &test_value; @@ -51,40 +38,44 @@ static napi_value CreateExternal(napi_env env, napi_callback_info info) { } static napi_value CreateSymbol(napi_env env, napi_callback_info info) { - - size_t argc = 1; - napi_value args[1]; - - NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL,NULL)); - NODE_API_ASSERT(env, argc == 1, "Expect one argument only (symbol description)"); - - napi_value result_symbol; - - NODE_API_CALL(env, napi_create_symbol(env, args[0], &result_symbol)); - return result_symbol; + size_t argc = 1; + napi_value args[1]; + + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_ASSERT( + env, argc == 1, "Expect one argument only (symbol description)"); + + napi_value result_symbol; + + NODE_API_CALL(env, napi_create_symbol(env, args[0], &result_symbol)); + return result_symbol; } static napi_value CreateSymbolFor(napi_env env, napi_callback_info info) { - - size_t argc = 1; - napi_value args[1]; - - char description[256]; - size_t description_length; - - NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL,NULL)); - NODE_API_ASSERT(env, argc == 1, "Expect one argument only (symbol description)"); - - NODE_API_CALL(env, napi_get_value_string_utf8(env, args[0], description, sizeof(description), &description_length)); - NODE_API_ASSERT(env, description_length <= 255, "Cannot accommodate descriptions longer than 255 bytes"); - - napi_value result_symbol; - - NODE_API_CALL(env, node_api_symbol_for(env, - description, - description_length, - &result_symbol)); - return result_symbol; + size_t argc = 1; + napi_value args[1]; + + char description[256]; + size_t description_length; + + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_ASSERT( + env, argc == 1, "Expect one argument only (symbol description)"); + + NODE_API_CALL( + env, + napi_get_value_string_utf8( + env, args[0], description, sizeof(description), &description_length)); + NODE_API_ASSERT(env, + description_length <= 255, + "Cannot accommodate descriptions longer than 255 bytes"); + + napi_value result_symbol; + + NODE_API_CALL(env, + node_api_symbol_for( + env, description, description_length, &result_symbol)); + return result_symbol; } static napi_value CreateSymbolForEmptyString(napi_env env, napi_callback_info info) { @@ -113,31 +104,6 @@ CreateExternalWithFinalize(napi_env env, napi_callback_info info) { return result; } -static napi_value -CreateExternalWithJsFinalize(napi_env env, napi_callback_info info) { - size_t argc = 1; - napi_value args[1]; - NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NODE_API_ASSERT(env, argc == 1, "Wrong number of arguments"); - napi_value finalizer = args[0]; - napi_valuetype finalizer_valuetype; - NODE_API_CALL(env, napi_typeof(env, finalizer, &finalizer_valuetype)); - NODE_API_ASSERT(env, finalizer_valuetype == napi_function, "Wrong type of first argument"); - napi_ref finalizer_ref; - NODE_API_CALL(env, napi_create_reference(env, finalizer, 1, &finalizer_ref)); - - napi_value result; - NODE_API_CALL(env, - napi_create_external(env, - &test_value, - FinalizeExternalCallJs, - finalizer_ref, /* finalize_hint */ - &result)); - - finalize_count = 0; - return result; -} - static napi_value CheckExternal(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value arg; @@ -258,24 +224,24 @@ static napi_value ValidateDeleteBeforeFinalize(napi_env env, napi_callback_info EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { - DECLARE_NODE_API_GETTER("finalizeCount", GetFinalizeCount), - DECLARE_NODE_API_PROPERTY("createExternal", CreateExternal), - DECLARE_NODE_API_PROPERTY("createExternalWithFinalize", - CreateExternalWithFinalize), - DECLARE_NODE_API_PROPERTY("createExternalWithJsFinalize", - CreateExternalWithJsFinalize), - DECLARE_NODE_API_PROPERTY("checkExternal", CheckExternal), - DECLARE_NODE_API_PROPERTY("createReference", CreateReference), - DECLARE_NODE_API_PROPERTY("createSymbol", CreateSymbol), - DECLARE_NODE_API_PROPERTY("createSymbolFor", CreateSymbolFor), - DECLARE_NODE_API_PROPERTY("createSymbolForEmptyString", CreateSymbolForEmptyString), - DECLARE_NODE_API_PROPERTY("createSymbolForIncorrectLength", CreateSymbolForIncorrectLength), - DECLARE_NODE_API_PROPERTY("deleteReference", DeleteReference), - DECLARE_NODE_API_PROPERTY("incrementRefcount", IncrementRefcount), - DECLARE_NODE_API_PROPERTY("decrementRefcount", DecrementRefcount), - DECLARE_NODE_API_GETTER("referenceValue", GetReferenceValue), - DECLARE_NODE_API_PROPERTY("validateDeleteBeforeFinalize", - ValidateDeleteBeforeFinalize), + DECLARE_NODE_API_GETTER("finalizeCount", GetFinalizeCount), + DECLARE_NODE_API_PROPERTY("createExternal", CreateExternal), + DECLARE_NODE_API_PROPERTY("createExternalWithFinalize", + CreateExternalWithFinalize), + DECLARE_NODE_API_PROPERTY("checkExternal", CheckExternal), + DECLARE_NODE_API_PROPERTY("createReference", CreateReference), + DECLARE_NODE_API_PROPERTY("createSymbol", CreateSymbol), + DECLARE_NODE_API_PROPERTY("createSymbolFor", CreateSymbolFor), + DECLARE_NODE_API_PROPERTY("createSymbolForEmptyString", + CreateSymbolForEmptyString), + DECLARE_NODE_API_PROPERTY("createSymbolForIncorrectLength", + CreateSymbolForIncorrectLength), + DECLARE_NODE_API_PROPERTY("deleteReference", DeleteReference), + DECLARE_NODE_API_PROPERTY("incrementRefcount", IncrementRefcount), + DECLARE_NODE_API_PROPERTY("decrementRefcount", DecrementRefcount), + DECLARE_NODE_API_GETTER("referenceValue", GetReferenceValue), + DECLARE_NODE_API_PROPERTY("validateDeleteBeforeFinalize", + ValidateDeleteBeforeFinalize), }; NODE_API_CALL(env, napi_define_properties( diff --git a/test/js-native-api/test_reference_double_free/binding.gyp b/test/js-native-api/test_reference_double_free/binding.gyp index 864846765d0132..2d906dadae6126 100644 --- a/test/js-native-api/test_reference_double_free/binding.gyp +++ b/test/js-native-api/test_reference_double_free/binding.gyp @@ -3,7 +3,6 @@ { "target_name": "test_reference_double_free", "sources": [ - "../entry_point.c", "test_reference_double_free.c" ] } diff --git a/test/js-native-api/test_reference_double_free/test_reference_double_free.c b/test/js-native-api/test_reference_double_free/test_reference_double_free.c index f491d237fded3e..0e0f91caf98458 100644 --- a/test/js-native-api/test_reference_double_free/test_reference_double_free.c +++ b/test/js-native-api/test_reference_double_free/test_reference_double_free.c @@ -1,6 +1,7 @@ -#include #include +#include #include "../common.h" +#include "../entry_point.h" static size_t g_call_count = 0; diff --git a/test/js-native-api/test_string/binding.gyp b/test/js-native-api/test_string/binding.gyp index c2f55857d41fe7..63fec1ae3b5375 100644 --- a/test/js-native-api/test_string/binding.gyp +++ b/test/js-native-api/test_string/binding.gyp @@ -3,10 +3,8 @@ { "target_name": "test_string", "sources": [ - "../entry_point.c", "test_string.c", "test_null.c", - "../common.c", ] } ] diff --git a/test/js-native-api/test_string/test_string.c b/test/js-native-api/test_string/test_string.c index e4b79fe50f0774..b2046e3b873392 100644 --- a/test/js-native-api/test_string/test_string.c +++ b/test/js-native-api/test_string/test_string.c @@ -4,6 +4,7 @@ #define NAPI_EXPERIMENTAL #include #include "../common.h" +#include "../entry_point.h" #include "test_null.h" enum length_type { actual_length, auto_length }; diff --git a/test/js-native-api/test_symbol/binding.gyp b/test/js-native-api/test_symbol/binding.gyp index 254531dfa92869..c44a78d042f57c 100644 --- a/test/js-native-api/test_symbol/binding.gyp +++ b/test/js-native-api/test_symbol/binding.gyp @@ -3,7 +3,6 @@ { "target_name": "test_symbol", "sources": [ - "../entry_point.c", "test_symbol.c" ] } diff --git a/test/js-native-api/test_symbol/test_symbol.c b/test/js-native-api/test_symbol/test_symbol.c index a87b275c938fbf..b14658298d517b 100644 --- a/test/js-native-api/test_symbol/test_symbol.c +++ b/test/js-native-api/test_symbol/test_symbol.c @@ -1,5 +1,6 @@ #include #include "../common.h" +#include "../entry_point.h" static napi_value New(napi_env env, napi_callback_info info) { size_t argc = 1; diff --git a/test/js-native-api/test_typedarray/binding.gyp b/test/js-native-api/test_typedarray/binding.gyp index 0caf90049cac5d..d708d2d2493bf6 100644 --- a/test/js-native-api/test_typedarray/binding.gyp +++ b/test/js-native-api/test_typedarray/binding.gyp @@ -3,7 +3,6 @@ { "target_name": "test_typedarray", "sources": [ - "../entry_point.c", "test_typedarray.c" ] } diff --git a/test/js-native-api/test_typedarray/test_typedarray.c b/test/js-native-api/test_typedarray/test_typedarray.c index 9a2031d256604d..240d024691e772 100644 --- a/test/js-native-api/test_typedarray/test_typedarray.c +++ b/test/js-native-api/test_typedarray/test_typedarray.c @@ -1,7 +1,8 @@ #include -#include #include +#include #include "../common.h" +#include "../entry_point.h" static napi_value Multiply(napi_env env, napi_callback_info info) { size_t argc = 2; diff --git a/test/known_issues/test-cwd-enoent-file.js b/test/known_issues/test-cwd-enoent-file.js index 0f75896134f7e3..6d99987895baf4 100644 --- a/test/known_issues/test-cwd-enoent-file.js +++ b/test/known_issues/test-cwd-enoent-file.js @@ -5,7 +5,7 @@ const common = require('../common'); const assert = require('assert'); -if (common.isSunOS || common.isWindows || common.isAIX) { +if (common.isSunOS || common.isWindows || common.isAIX || common.isIBMi) { // The current working directory cannot be removed on these platforms. // Change this to common.skip() when this is no longer a known issue test. assert.fail('cannot rmdir current working directory'); diff --git a/test/message/source_map_enclosing_function.js b/test/message/source_map_enclosing_function.js deleted file mode 100644 index f77bd818f02d78..00000000000000 --- a/test/message/source_map_enclosing_function.js +++ /dev/null @@ -1,7 +0,0 @@ -// Flags: --enable-source-maps - -'use strict'; -require('../common'); -Error.stackTraceLimit = 5; - -require('../fixtures/source-map/enclosing-call-site-min.js'); diff --git a/test/message/source_map_enclosing_function.out b/test/message/source_map_enclosing_function.out deleted file mode 100644 index 5bb920e7eba42a..00000000000000 --- a/test/message/source_map_enclosing_function.out +++ /dev/null @@ -1,12 +0,0 @@ -*enclosing-call-site.js:26 - throw err - ^ - -Error: an error! - at functionD (*enclosing-call-site.js:16:17) - at functionC (*enclosing-call-site.js:10:3) - at functionB (*enclosing-call-site.js:6:3) - at functionA (*enclosing-call-site.js:2:3) - at Object. (*enclosing-call-site.js:24:3) - -Node.js * diff --git a/test/message/source_map_reference_error_tabs.js b/test/message/source_map_reference_error_tabs.js deleted file mode 100644 index fbe058a5f531bf..00000000000000 --- a/test/message/source_map_reference_error_tabs.js +++ /dev/null @@ -1,7 +0,0 @@ -// Flags: --enable-source-maps - -'use strict'; -require('../common'); -Error.stackTraceLimit = 2; - -require('../fixtures/source-map/tabs.js'); diff --git a/test/message/source_map_reference_error_tabs.out b/test/message/source_map_reference_error_tabs.out deleted file mode 100644 index 7bf2d13305ef12..00000000000000 --- a/test/message/source_map_reference_error_tabs.out +++ /dev/null @@ -1,9 +0,0 @@ -*tabs.coffee:26 - alert "I knew it!" - ^ - -ReferenceError: alert is not defined - at *tabs.coffee:26:2* - at *tabs.coffee:1:14* - -Node.js * diff --git a/test/message/source_map_sourcemapping_url_string.js b/test/message/source_map_sourcemapping_url_string.js deleted file mode 100644 index 254d18bd080e53..00000000000000 --- a/test/message/source_map_sourcemapping_url_string.js +++ /dev/null @@ -1,13 +0,0 @@ -// Flags: --enable-source-maps - -'use strict'; -require('../common'); -Error.stackTraceLimit = 2; - -try { - require('../fixtures/source-map/typescript-sourcemapping_url_string'); -} catch (err) { - setTimeout(() => { - console.info(err); - }, 10); -} diff --git a/test/message/source_map_sourcemapping_url_string.out b/test/message/source_map_sourcemapping_url_string.out deleted file mode 100644 index 3d0b6e15eb6c7a..00000000000000 --- a/test/message/source_map_sourcemapping_url_string.out +++ /dev/null @@ -1,3 +0,0 @@ -Error: an exception. - at *typescript-sourcemapping_url_string.ts:3:7* - at Module._compile (node:internal/modules/cjs/loader:*) diff --git a/test/message/source_map_throw_catch.js b/test/message/source_map_throw_catch.js deleted file mode 100644 index 603fa81867bcbe..00000000000000 --- a/test/message/source_map_throw_catch.js +++ /dev/null @@ -1,13 +0,0 @@ -// Flags: --enable-source-maps - -'use strict'; -require('../common'); -Error.stackTraceLimit = 2; - -try { - require('../fixtures/source-map/typescript-throw'); -} catch (err) { - setTimeout(() => { - console.info(err); - }, 10); -} diff --git a/test/message/source_map_throw_catch.out b/test/message/source_map_throw_catch.out deleted file mode 100644 index 662d4b5bee4dab..00000000000000 --- a/test/message/source_map_throw_catch.out +++ /dev/null @@ -1,4 +0,0 @@ -reachable -Error: an exception - at *typescript-throw.ts:18:11* - at *typescript-throw.ts:24:1* diff --git a/test/message/source_map_throw_icu.js b/test/message/source_map_throw_icu.js deleted file mode 100644 index 672c1575c6547a..00000000000000 --- a/test/message/source_map_throw_icu.js +++ /dev/null @@ -1,7 +0,0 @@ -// Flags: --enable-source-maps - -'use strict'; -require('../common'); -Error.stackTraceLimit = 2; - -require('../fixtures/source-map/icu'); diff --git a/test/message/source_map_throw_icu.out b/test/message/source_map_throw_icu.out deleted file mode 100644 index 65297956f92437..00000000000000 --- a/test/message/source_map_throw_icu.out +++ /dev/null @@ -1,9 +0,0 @@ -*icu.jsx:3 - ("********", throw Error("an error")); - ^ - -Error: an error - at *icu.jsx:3:23* - at *icu.jsx:9:5* - -Node.js * diff --git a/test/message/source_map_throw_set_immediate.js b/test/message/source_map_throw_set_immediate.js deleted file mode 100644 index 17da1bd7acea66..00000000000000 --- a/test/message/source_map_throw_set_immediate.js +++ /dev/null @@ -1,5 +0,0 @@ -// Flags: --enable-source-maps - -'use strict'; -require('../common'); -require('../fixtures/source-map/uglify-throw'); diff --git a/test/message/source_map_throw_set_immediate.out b/test/message/source_map_throw_set_immediate.out deleted file mode 100644 index 21ce9c8158e016..00000000000000 --- a/test/message/source_map_throw_set_immediate.out +++ /dev/null @@ -1,10 +0,0 @@ -*uglify-throw-original.js:5 - throw Error('goodbye'); - ^ - -Error: goodbye - at Hello *uglify-throw-original.js:5:9* - at *uglify-throw-original.js:9:3* - at process.processImmediate (node:internal/timers:*) - -Node.js * diff --git a/test/node-api/test_buffer/binding.gyp b/test/node-api/test_buffer/binding.gyp index e41a3993cd7c9d..e5d0955ae6308e 100644 --- a/test/node-api/test_buffer/binding.gyp +++ b/test/node-api/test_buffer/binding.gyp @@ -3,6 +3,10 @@ { "target_name": "test_buffer", "sources": [ "test_buffer.c" ] + }, + { + "target_name": "test_finalizer", + "sources": [ "test_finalizer.c" ] } ] } diff --git a/test/node-api/test_buffer/test_buffer.c b/test/node-api/test_buffer/test_buffer.c index bc61cd7a2e9062..013a7e2d417fbe 100644 --- a/test/node-api/test_buffer/test_buffer.c +++ b/test/node-api/test_buffer/test_buffer.c @@ -22,17 +22,6 @@ static void noopDeleter(napi_env env, void* data, void* finalize_hint) { deleterCallCount++; } -static void malignDeleter(napi_env env, void* data, void* finalize_hint) { - NODE_API_ASSERT_RETURN_VOID(env, data != NULL && strcmp(data, theText) == 0, "invalid data"); - napi_ref finalizer_ref = (napi_ref)finalize_hint; - napi_value js_finalizer; - napi_value recv; - NODE_API_CALL_RETURN_VOID(env, napi_get_reference_value(env, finalizer_ref, &js_finalizer)); - NODE_API_CALL_RETURN_VOID(env, napi_get_global(env, &recv)); - NODE_API_CALL_RETURN_VOID(env, napi_call_function(env, recv, js_finalizer, 0, NULL, NULL)); - NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, finalizer_ref)); -} - static napi_value newBuffer(napi_env env, napi_callback_info info) { napi_value theBuffer; char* theCopy; @@ -118,30 +107,6 @@ static napi_value staticBuffer(napi_env env, napi_callback_info info) { return theBuffer; } -static napi_value malignFinalizerBuffer(napi_env env, napi_callback_info info) { - size_t argc = 1; - napi_value args[1]; - NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); - NODE_API_ASSERT(env, argc == 1, "Wrong number of arguments"); - napi_value finalizer = args[0]; - napi_valuetype finalizer_valuetype; - NODE_API_CALL(env, napi_typeof(env, finalizer, &finalizer_valuetype)); - NODE_API_ASSERT(env, finalizer_valuetype == napi_function, "Wrong type of first argument"); - napi_ref finalizer_ref; - NODE_API_CALL(env, napi_create_reference(env, finalizer, 1, &finalizer_ref)); - - napi_value theBuffer; - NODE_API_CALL( - env, - napi_create_external_buffer(env, - sizeof(theText), - (void*)theText, - malignDeleter, - finalizer_ref, // finalize_hint - &theBuffer)); - return theBuffer; -} - static napi_value Init(napi_env env, napi_value exports) { napi_value theValue; @@ -151,14 +116,13 @@ static napi_value Init(napi_env env, napi_value exports) { napi_set_named_property(env, exports, "theText", theValue)); napi_property_descriptor methods[] = { - DECLARE_NODE_API_PROPERTY("newBuffer", newBuffer), - DECLARE_NODE_API_PROPERTY("newExternalBuffer", newExternalBuffer), - DECLARE_NODE_API_PROPERTY("getDeleterCallCount", getDeleterCallCount), - DECLARE_NODE_API_PROPERTY("copyBuffer", copyBuffer), - DECLARE_NODE_API_PROPERTY("bufferHasInstance", bufferHasInstance), - DECLARE_NODE_API_PROPERTY("bufferInfo", bufferInfo), - DECLARE_NODE_API_PROPERTY("staticBuffer", staticBuffer), - DECLARE_NODE_API_PROPERTY("malignFinalizerBuffer", malignFinalizerBuffer), + DECLARE_NODE_API_PROPERTY("newBuffer", newBuffer), + DECLARE_NODE_API_PROPERTY("newExternalBuffer", newExternalBuffer), + DECLARE_NODE_API_PROPERTY("getDeleterCallCount", getDeleterCallCount), + DECLARE_NODE_API_PROPERTY("copyBuffer", copyBuffer), + DECLARE_NODE_API_PROPERTY("bufferHasInstance", bufferHasInstance), + DECLARE_NODE_API_PROPERTY("bufferInfo", bufferInfo), + DECLARE_NODE_API_PROPERTY("staticBuffer", staticBuffer), }; NODE_API_CALL(env, napi_define_properties( diff --git a/test/node-api/test_buffer/test_finalizer.c b/test/node-api/test_buffer/test_finalizer.c new file mode 100644 index 00000000000000..eb5426d8f29cdf --- /dev/null +++ b/test/node-api/test_buffer/test_finalizer.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include "../../js-native-api/common.h" + +static const char theText[] = + "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; + +static void malignDeleter(napi_env env, void* data, void* finalize_hint) { + NODE_API_ASSERT_RETURN_VOID( + env, data != NULL && strcmp(data, theText) == 0, "invalid data"); + napi_ref finalizer_ref = (napi_ref)finalize_hint; + napi_value js_finalizer; + napi_value recv; + NODE_API_CALL_RETURN_VOID( + env, napi_get_reference_value(env, finalizer_ref, &js_finalizer)); + NODE_API_CALL_RETURN_VOID(env, napi_get_global(env, &recv)); + NODE_API_CALL_RETURN_VOID( + env, napi_call_function(env, recv, js_finalizer, 0, NULL, NULL)); + NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, finalizer_ref)); +} + +static napi_value malignFinalizerBuffer(napi_env env, napi_callback_info info) { + size_t argc = 1; + napi_value args[1]; + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + NODE_API_ASSERT(env, argc == 1, "Wrong number of arguments"); + napi_value finalizer = args[0]; + napi_valuetype finalizer_valuetype; + NODE_API_CALL(env, napi_typeof(env, finalizer, &finalizer_valuetype)); + NODE_API_ASSERT(env, + finalizer_valuetype == napi_function, + "Wrong type of first argument"); + napi_ref finalizer_ref; + NODE_API_CALL(env, napi_create_reference(env, finalizer, 1, &finalizer_ref)); + + napi_value theBuffer; + NODE_API_CALL(env, + napi_create_external_buffer(env, + sizeof(theText), + (void*)theText, + malignDeleter, + finalizer_ref, // finalize_hint + &theBuffer)); + return theBuffer; +} + +static napi_value Init(napi_env env, napi_value exports) { + napi_property_descriptor methods[] = { + DECLARE_NODE_API_PROPERTY("malignFinalizerBuffer", malignFinalizerBuffer), + }; + + NODE_API_CALL( + env, + napi_define_properties( + env, exports, sizeof(methods) / sizeof(methods[0]), methods)); + + return exports; +} + +NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) diff --git a/test/node-api/test_buffer/test_finalizer.js b/test/node-api/test_buffer/test_finalizer.js index b706c68c7c3e02..35511fcb016c95 100644 --- a/test/node-api/test_buffer/test_finalizer.js +++ b/test/node-api/test_buffer/test_finalizer.js @@ -2,7 +2,7 @@ // Flags: --expose-gc --force-node-api-uncaught-exceptions-policy const common = require('../../common'); -const binding = require(`./build/${common.buildType}/test_buffer`); +const binding = require(`./build/${common.buildType}/test_finalizer`); const assert = require('assert'); const tick = require('util').promisify(require('../../common/tick')); diff --git a/test/node-api/test_policy/test_policy.js b/test/node-api/test_policy/test_policy.js index d6cb12b56cb683..e60c314579bc3b 100644 --- a/test/node-api/test_policy/test_policy.js +++ b/test/node-api/test_policy/test_policy.js @@ -24,11 +24,6 @@ const policyFilepath = path.join(tmpdir.path, 'policy'); const depFilepath = require.resolve(`./build/${common.buildType}/binding.node`); const depURL = pathToFileURL(depFilepath); -const tmpdirURL = pathToFileURL(tmpdir.path); -if (!tmpdirURL.pathname.endsWith('/')) { - tmpdirURL.pathname += '/'; -} - const depBody = fs.readFileSync(depURL); function writePolicy(...resources) { const manifest = { resources: {} }; diff --git a/test/node-api/test_threadsafe_function/binding.gyp b/test/node-api/test_threadsafe_function/binding.gyp index b60352e05af103..58a9d04d4a5619 100644 --- a/test/node-api/test_threadsafe_function/binding.gyp +++ b/test/node-api/test_threadsafe_function/binding.gyp @@ -3,6 +3,20 @@ { 'target_name': 'binding', 'sources': ['binding.c'] + }, + { + 'target_name': 'test_uncaught_exception_v9', + 'defines': [ + 'NAPI_VERSION=9' + ], + 'sources': ['test_uncaught_exception.c'] + }, + { + 'target_name': 'test_uncaught_exception', + 'defines': [ + 'NAPI_EXPERIMENTAL' + ], + 'sources': ['test_uncaught_exception.c'] } ] } diff --git a/test/node-api/test_threadsafe_function/test_force_uncaught_exception.js b/test/node-api/test_threadsafe_function/test_force_uncaught_exception.js deleted file mode 100644 index b1f95715eadf60..00000000000000 --- a/test/node-api/test_threadsafe_function/test_force_uncaught_exception.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; -// Flags: --no-force-node-api-uncaught-exceptions-policy - -const common = require('../../common'); -const binding = require(`./build/${common.buildType}/binding`); - -process.on( - 'uncaughtException', - common.mustNotCall('uncaught callback errors should be suppressed ' + - 'with the option --no-force-node-api-uncaught-exceptions-policy'), -); - -binding.CallIntoModule( - common.mustCall(() => { - throw new Error('callback error'); - }), - {}, - 'resource_name', - common.mustCall(function finalizer() { - throw new Error('finalizer error'); - }), -); diff --git a/test/node-api/test_threadsafe_function/test_legacy_uncaught_exception.js b/test/node-api/test_threadsafe_function/test_legacy_uncaught_exception.js new file mode 100644 index 00000000000000..a8743e00b5b8c5 --- /dev/null +++ b/test/node-api/test_threadsafe_function/test_legacy_uncaught_exception.js @@ -0,0 +1,22 @@ +'use strict'; +// Flags: --no-force-node-api-uncaught-exceptions-policy + +const common = require('../../common'); +const binding = require(`./build/${common.buildType}/test_uncaught_exception_v9`); + +process.on( + 'uncaughtException', + common.mustNotCall('uncaught callback errors should be suppressed ' + + 'with the option --no-force-node-api-uncaught-exceptions-policy'), +); + +binding.CallIntoModule( + common.mustCall(() => { + throw new Error('callback error'); + }), + {}, + 'resource_name', + common.mustCall(function finalizer() { + throw new Error('finalizer error'); + }), +); diff --git a/test/node-api/test_threadsafe_function/test_uncaught_exception.c b/test/node-api/test_threadsafe_function/test_uncaught_exception.c new file mode 100644 index 00000000000000..f8499d4fe4d680 --- /dev/null +++ b/test/node-api/test_threadsafe_function/test_uncaught_exception.c @@ -0,0 +1,62 @@ +#include +#include "../../js-native-api/common.h" + +// Testing calling into JavaScript +static void ThreadSafeFunctionFinalize(napi_env env, + void* finalize_data, + void* finalize_hint) { + napi_ref js_func_ref = (napi_ref)finalize_data; + napi_value js_func; + napi_value recv; + NODE_API_CALL_RETURN_VOID( + env, napi_get_reference_value(env, js_func_ref, &js_func)); + NODE_API_CALL_RETURN_VOID(env, napi_get_global(env, &recv)); + NODE_API_CALL_RETURN_VOID( + env, napi_call_function(env, recv, js_func, 0, NULL, NULL)); + NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, js_func_ref)); +} + +// Testing calling into JavaScript +static napi_value CallIntoModule(napi_env env, napi_callback_info info) { + size_t argc = 4; + napi_value argv[4]; + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL)); + + napi_ref finalize_func; + NODE_API_CALL(env, napi_create_reference(env, argv[3], 1, &finalize_func)); + + napi_threadsafe_function tsfn; + NODE_API_CALL(env, + napi_create_threadsafe_function(env, + argv[0], + argv[1], + argv[2], + 0, + 1, + finalize_func, + ThreadSafeFunctionFinalize, + NULL, + NULL, + &tsfn)); + NODE_API_CALL(env, + napi_call_threadsafe_function(tsfn, NULL, napi_tsfn_blocking)); + NODE_API_CALL(env, napi_release_threadsafe_function(tsfn, napi_tsfn_release)); + return NULL; +} + +// Module init +static napi_value Init(napi_env env, napi_value exports) { + napi_property_descriptor properties[] = { + DECLARE_NODE_API_PROPERTY("CallIntoModule", CallIntoModule), + }; + + NODE_API_CALL( + env, + napi_define_properties(env, + exports, + sizeof(properties) / sizeof(properties[0]), + properties)); + + return exports; +} +NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) diff --git a/test/node-api/test_threadsafe_function/test_uncaught_exception.js b/test/node-api/test_threadsafe_function/test_uncaught_exception.js index 2529757908999b..81b2623d702790 100644 --- a/test/node-api/test_threadsafe_function/test_uncaught_exception.js +++ b/test/node-api/test_threadsafe_function/test_uncaught_exception.js @@ -1,27 +1,7 @@ 'use strict'; -// Flags: --force-node-api-uncaught-exceptions-policy const common = require('../../common'); -const assert = require('assert'); -const binding = require(`./build/${common.buildType}/binding`); +const binding = require(`./build/${common.buildType}/test_uncaught_exception`); +const { testUncaughtException } = require('./uncaught_exception'); -const callbackCheck = common.mustCall((err) => { - assert.throws(() => { throw err; }, /callback error/); - process.removeListener('uncaughtException', callbackCheck); - process.on('uncaughtException', finalizerCheck); -}); -const finalizerCheck = common.mustCall((err) => { - assert.throws(() => { throw err; }, /finalizer error/); -}); -process.on('uncaughtException', callbackCheck); - -binding.CallIntoModule( - common.mustCall(() => { - throw new Error('callback error'); - }), - {}, - 'resource_name', - common.mustCall(function finalizer() { - throw new Error('finalizer error'); - }), -); +testUncaughtException(binding); diff --git a/test/node-api/test_threadsafe_function/test_uncaught_exception_v9.js b/test/node-api/test_threadsafe_function/test_uncaught_exception_v9.js new file mode 100644 index 00000000000000..28e628918fdff2 --- /dev/null +++ b/test/node-api/test_threadsafe_function/test_uncaught_exception_v9.js @@ -0,0 +1,8 @@ +'use strict'; +// Flags: --force-node-api-uncaught-exceptions-policy + +const common = require('../../common'); +const binding = require(`./build/${common.buildType}/test_uncaught_exception_v9`); +const { testUncaughtException } = require('./uncaught_exception'); + +testUncaughtException(binding); diff --git a/test/node-api/test_threadsafe_function/uncaught_exception.js b/test/node-api/test_threadsafe_function/uncaught_exception.js new file mode 100644 index 00000000000000..da2aa2f4efef8a --- /dev/null +++ b/test/node-api/test_threadsafe_function/uncaught_exception.js @@ -0,0 +1,31 @@ +'use strict'; + +const common = require('../../common'); +const assert = require('assert'); + +function testUncaughtException(binding) { + const callbackCheck = common.mustCall((err) => { + assert.throws(() => { throw err; }, /callback error/); + process.removeListener('uncaughtException', callbackCheck); + process.on('uncaughtException', finalizerCheck); + }); + const finalizerCheck = common.mustCall((err) => { + assert.throws(() => { throw err; }, /finalizer error/); + }); + process.on('uncaughtException', callbackCheck); + + binding.CallIntoModule( + common.mustCall(() => { + throw new Error('callback error'); + }), + {}, + 'resource_name', + common.mustCall(function finalizer() { + throw new Error('finalizer error'); + }), + ); +} + +module.exports = { + testUncaughtException, +}; diff --git a/test/parallel/parallel.status b/test/parallel/parallel.status index 8de4ad29cb1414..58beb9d2c2e645 100644 --- a/test/parallel/parallel.status +++ b/test/parallel/parallel.status @@ -14,6 +14,14 @@ test-fs-rmdir-recursive: PASS, FLAKY # https://github.com/nodejs/node/issues/48300 test-child-process-pipe-dataflow: PASS, FLAKY test-child-process-stdio-reuse-readable-stdio: PASS, FLAKY +# https://github.com/nodejs/node/issues/49985 +test-runner-watch-mode: PASS, FLAKY +# https://github.com/nodejs/node/issues/50295 +test-cli-node-options: PASS, FLAKY + +# Windows on x86 +[$system==win32 && $arch==ia32] +test-worker-nearheaplimit-deadlock: PASS, FLAKY # Windows on ARM [$system==win32 && $arch==arm64] @@ -23,6 +31,12 @@ test-child-process-stdio-reuse-readable-stdio: PASS, FLAKY test-domain-error-types: PASS,FLAKY # https://github.com/nodejs/node/issues/47420 test-file-write-stream4: PASS,FLAKY +# https://github.com/nodejs/node/issues/43465 +test-http-server-request-timeouts-mixed: PASS, FLAKY + +[$system==linux || $system==win32] +# https://github.com/nodejs/node/issues/49605 +test-runner-watch-mode: PASS,FLAKY [$system==macos] # https://github.com/nodejs/node/issues/42741 @@ -30,6 +44,8 @@ test-http-server-headers-timeout-keepalive: PASS,FLAKY test-http-server-request-timeout-keepalive: PASS,FLAKY # https://github.com/nodejs/node/issues/43465 test-http-server-request-timeouts-mixed: PASS,FLAKY +# https://github.com/nodejs/node/issues/50243 +test-inspector-async-stack-traces-set-interval: PASS, FLAKY [$arch==arm || $arch==arm64] # https://github.com/nodejs/node/pull/31178 @@ -96,3 +112,7 @@ test-http-pipeline-flood: SKIP [$asan==on] # https://github.com/nodejs/node/issues/39655 test-cluster-primary-error: PASS, FLAKY + +[$arch==s390x] +# https://github.com/nodejs/node/issues/50222 +test-inspector-async-hook-setup-at-inspect-brk: PASS, FLAKY diff --git a/test/parallel/test-bootstrap-modules.js b/test/parallel/test-bootstrap-modules.js index b68a3d3da256a8..1ce0effe4fb02d 100644 --- a/test/parallel/test-bootstrap-modules.js +++ b/test/parallel/test-bootstrap-modules.js @@ -10,7 +10,6 @@ const assert = require('assert'); const expectedModules = new Set([ 'Internal Binding async_wrap', - 'Internal Binding block_list', 'Internal Binding buffer', 'Internal Binding builtins', 'Internal Binding config', @@ -18,235 +17,130 @@ const expectedModules = new Set([ 'Internal Binding contextify', 'Internal Binding credentials', 'Internal Binding errors', - 'Internal Binding fs_dir', - 'Internal Binding fs_event_wrap', 'Internal Binding fs', - 'Internal Binding heap_utils', 'Internal Binding mksnapshot', 'Internal Binding messaging', 'Internal Binding module_wrap', 'Internal Binding options', 'Internal Binding performance', - 'Internal Binding pipe_wrap', 'Internal Binding process_methods', - 'Internal Binding report', - 'Internal Binding serdes', - 'Internal Binding stream_wrap', 'Internal Binding string_decoder', 'Internal Binding symbols', 'Internal Binding task_queue', - 'Internal Binding tcp_wrap', 'Internal Binding timers', 'Internal Binding trace_events', 'Internal Binding types', 'Internal Binding url', 'Internal Binding util', - 'Internal Binding uv', - 'Internal Binding v8', 'Internal Binding wasm_web_api', 'Internal Binding worker', 'NativeModule buffer', 'NativeModule events', 'NativeModule fs', - 'NativeModule internal/abort_controller', 'NativeModule internal/assert', 'NativeModule internal/async_hooks', - 'NativeModule internal/blocklist', 'NativeModule internal/buffer', 'NativeModule internal/console/constructor', 'NativeModule internal/console/global', 'NativeModule internal/constants', - 'NativeModule internal/dtrace', 'NativeModule internal/dns/utils', - 'NativeModule internal/encoding', 'NativeModule internal/errors', 'NativeModule internal/event_target', 'NativeModule internal/fixed_queue', - 'NativeModule internal/fs/dir', - 'NativeModule internal/fs/promises', - 'NativeModule internal/fs/read_file_context', - 'NativeModule internal/fs/rimraf', 'NativeModule internal/fs/utils', - 'NativeModule internal/fs/watchers', - 'NativeModule internal/heap_utils', - 'NativeModule internal/histogram', - 'NativeModule internal/idna', 'NativeModule internal/linkedlist', - 'NativeModule internal/mime', - 'NativeModule internal/modules/cjs/helpers', 'NativeModule internal/modules/cjs/loader', - 'NativeModule internal/modules/esm/assert', - 'NativeModule internal/modules/esm/create_dynamic_module', - 'NativeModule internal/modules/esm/fetch_module', - 'NativeModule internal/modules/esm/formats', - 'NativeModule internal/modules/esm/get_format', - 'NativeModule internal/modules/esm/handle_process_exit', - 'NativeModule internal/modules/esm/initialize_import_meta', - 'NativeModule internal/modules/esm/load', - 'NativeModule internal/modules/esm/loader', - 'NativeModule internal/modules/esm/module_job', - 'NativeModule internal/modules/esm/module_map', - 'NativeModule internal/modules/esm/package_config', - 'NativeModule internal/modules/esm/resolve', - 'NativeModule internal/modules/esm/translators', + 'NativeModule internal/modules/esm/utils', + 'NativeModule internal/modules/helpers', 'NativeModule internal/modules/package_json_reader', 'NativeModule internal/modules/run_main', 'NativeModule internal/net', 'NativeModule internal/options', - 'NativeModule internal/perf/event_loop_delay', - 'NativeModule internal/perf/event_loop_utilization', - 'NativeModule internal/perf/nodetiming', - 'NativeModule internal/perf/observe', - 'NativeModule internal/perf/performance_entry', - 'NativeModule internal/perf/performance', - 'NativeModule internal/perf/timerify', - 'NativeModule internal/perf/usertiming', - 'NativeModule internal/perf/resource_timing', 'NativeModule internal/perf/utils', 'NativeModule internal/priority_queue', - 'NativeModule internal/process/esm_loader', 'NativeModule internal/process/execution', 'NativeModule internal/process/per_thread', 'NativeModule internal/process/pre_execution', 'NativeModule internal/process/promises', - 'NativeModule internal/process/report', 'NativeModule internal/process/signal', 'NativeModule internal/process/task_queues', 'NativeModule internal/process/warning', - 'NativeModule internal/promise_hooks', 'NativeModule internal/querystring', - 'NativeModule internal/readline/callbacks', - 'NativeModule internal/readline/interface', - 'NativeModule internal/readline/utils', - 'NativeModule internal/socketaddress', 'NativeModule internal/source_map/source_map_cache', - 'NativeModule internal/stream_base_commons', - 'NativeModule internal/streams/add-abort-signal', - 'NativeModule internal/streams/buffer_list', - 'NativeModule internal/streams/compose', - 'NativeModule internal/streams/destroy', - 'NativeModule internal/streams/duplex', - 'NativeModule internal/streams/end-of-stream', - 'NativeModule internal/streams/from', - 'NativeModule internal/streams/legacy', - 'NativeModule internal/streams/operators', - 'NativeModule internal/streams/passthrough', - 'NativeModule internal/streams/pipeline', - 'NativeModule internal/streams/readable', - 'NativeModule internal/streams/state', - 'NativeModule internal/streams/transform', - 'NativeModule internal/streams/utils', - 'NativeModule internal/streams/writable', - 'NativeModule internal/structured_clone', 'NativeModule internal/timers', 'NativeModule internal/url', 'NativeModule internal/util', 'NativeModule internal/util/debuglog', 'NativeModule internal/util/inspect', - 'NativeModule internal/util/iterable_weak_map', - 'NativeModule internal/util/parse_args/utils', - 'NativeModule internal/util/parse_args/parse_args', 'NativeModule internal/util/types', 'NativeModule internal/validators', 'NativeModule internal/vm', 'NativeModule internal/vm/module', - 'NativeModule internal/wasm_web_api', 'NativeModule internal/webidl', - 'NativeModule internal/webstreams/adapters', - 'NativeModule internal/webstreams/compression', - 'NativeModule internal/webstreams/encoding', - 'NativeModule internal/webstreams/queuingstrategies', - 'NativeModule internal/webstreams/readablestream', - 'NativeModule internal/webstreams/transformstream', - 'NativeModule internal/webstreams/util', - 'NativeModule internal/webstreams/writablestream', - 'NativeModule internal/worker/io', 'NativeModule internal/worker/js_transferable', 'Internal Binding blob', - 'NativeModule internal/blob', - 'NativeModule internal/file', 'NativeModule async_hooks', - 'NativeModule net', 'NativeModule path', - 'NativeModule perf_hooks', 'NativeModule querystring', - 'NativeModule stream', - 'NativeModule stream/promises', - 'NativeModule string_decoder', 'NativeModule timers', - 'NativeModule url', - 'NativeModule util', - 'NativeModule v8', 'NativeModule internal/v8/startup_snapshot', - 'NativeModule vm', + 'NativeModule util', ]); -if (!common.isMainThread) { +if (common.isMainThread) { + [ + 'NativeModule internal/idna', + 'NativeModule url', + ].forEach(expectedModules.add.bind(expectedModules)); +} else { [ 'Internal Binding messaging', 'Internal Binding performance', 'Internal Binding symbols', 'Internal Binding worker', - 'NativeModule internal/streams/duplex', - 'NativeModule internal/streams/passthrough', - 'NativeModule internal/streams/readable', - 'NativeModule internal/streams/transform', - 'NativeModule internal/streams/writable', + 'NativeModule internal/abort_controller', 'NativeModule internal/error_serdes', + 'NativeModule internal/event_target', 'NativeModule internal/process/worker_thread_only', + 'NativeModule internal/streams/add-abort-signal', 'NativeModule internal/streams/buffer_list', + 'NativeModule internal/streams/compose', 'NativeModule internal/streams/destroy', + 'NativeModule internal/streams/duplex', 'NativeModule internal/streams/end-of-stream', + 'NativeModule internal/streams/from', 'NativeModule internal/streams/legacy', + 'NativeModule internal/streams/operators', + 'NativeModule internal/streams/passthrough', 'NativeModule internal/streams/pipeline', + 'NativeModule internal/streams/readable', 'NativeModule internal/streams/state', + 'NativeModule internal/streams/transform', + 'NativeModule internal/streams/utils', + 'NativeModule internal/streams/writable', 'NativeModule internal/worker', 'NativeModule internal/worker/io', - 'NativeModule stream', 'NativeModule worker_threads', + 'NativeModule stream', + 'NativeModule stream/promises', + 'NativeModule string_decoder', + 'NativeModule util', ].forEach(expectedModules.add.bind(expectedModules)); } +if (common.isWindows) { + // On Windows fs needs SideEffectFreeRegExpPrototypeExec which uses vm. + expectedModules.add('NativeModule vm'); +} + if (common.hasIntl) { expectedModules.add('Internal Binding icu'); -} else { - expectedModules.add('NativeModule url'); } if (process.features.inspector) { expectedModules.add('Internal Binding inspector'); expectedModules.add('NativeModule internal/inspector_async_hook'); expectedModules.add('NativeModule internal/util/inspector'); - expectedModules.add('Internal Binding profiler'); -} - -if (process.env.NODE_V8_COVERAGE) { - expectedModules.add('Internal Binding profiler'); -} - -if (common.hasCrypto) { - expectedModules.add('Internal Binding crypto'); - expectedModules.add('NativeModule crypto'); - expectedModules.add('NativeModule internal/crypto/certificate'); - expectedModules.add('NativeModule internal/crypto/cipher'); - expectedModules.add('NativeModule internal/crypto/diffiehellman'); - expectedModules.add('NativeModule internal/crypto/hash'); - expectedModules.add('NativeModule internal/crypto/hashnames'); - expectedModules.add('NativeModule internal/crypto/hkdf'); - expectedModules.add('NativeModule internal/crypto/keygen'); - expectedModules.add('NativeModule internal/crypto/keys'); - expectedModules.add('NativeModule internal/crypto/pbkdf2'); - expectedModules.add('NativeModule internal/crypto/random'); - expectedModules.add('NativeModule internal/crypto/scrypt'); - expectedModules.add('NativeModule internal/crypto/sig'); - expectedModules.add('NativeModule internal/crypto/util'); - expectedModules.add('NativeModule internal/crypto/x509'); - expectedModules.add('NativeModule internal/streams/lazy_transform'); -} - -const { internalBinding } = require('internal/test/binding'); -if (internalBinding('config').hasDtrace) { - expectedModules.add('Internal Binding dtrace'); } const difference = (setA, setB) => { diff --git a/test/parallel/test-child-process-cwd.js b/test/parallel/test-child-process-cwd.js index 869db83db3902e..b527b7f9ea8012 100644 --- a/test/parallel/test-child-process-cwd.js +++ b/test/parallel/test-child-process-cwd.js @@ -27,7 +27,6 @@ tmpdir.refresh(); const assert = require('assert'); const { spawn } = require('child_process'); -const { pathToFileURL, URL } = require('url'); // Spawns 'pwd' with given options, then test // - whether the child pid is undefined or number, @@ -88,7 +87,7 @@ function testCwd(options, expectPidType, expectCode = 0, expectData) { testCwd({ cwd: tmpdir.path }, 'number', 0, tmpdir.path); const shouldExistDir = common.isWindows ? process.env.windir : '/dev'; testCwd({ cwd: shouldExistDir }, 'number', 0, shouldExistDir); -testCwd({ cwd: pathToFileURL(tmpdir.path) }, 'number', 0, tmpdir.path); +testCwd({ cwd: tmpdir.fileURL() }, 'number', 0, tmpdir.path); // Spawn() shouldn't try to chdir() to invalid arg, so this should just work testCwd({ cwd: '' }, 'number'); diff --git a/test/parallel/test-crypto-dh-errors.js b/test/parallel/test-crypto-dh-errors.js new file mode 100644 index 00000000000000..fcf1922bcdba73 --- /dev/null +++ b/test/parallel/test-crypto-dh-errors.js @@ -0,0 +1,111 @@ +'use strict'; +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const crypto = require('crypto'); + +// https://github.com/nodejs/node/issues/32738 +// XXX(bnoordhuis) validateInt32() throwing ERR_OUT_OF_RANGE and RangeError +// instead of ERR_INVALID_ARG_TYPE and TypeError is questionable, IMO. +assert.throws(() => crypto.createDiffieHellman(13.37), { + code: 'ERR_OUT_OF_RANGE', + name: 'RangeError', + message: 'The value of "sizeOrKey" is out of range. ' + + 'It must be an integer. Received 13.37', +}); + +assert.throws(() => crypto.createDiffieHellman('abcdef', 13.37), { + code: 'ERR_OUT_OF_RANGE', + name: 'RangeError', + message: 'The value of "generator" is out of range. ' + + 'It must be an integer. Received 13.37', +}); + +for (const bits of [-1, 0, 1]) { + if (common.hasOpenSSL3) { + assert.throws(() => crypto.createDiffieHellman(bits), { + code: 'ERR_OSSL_DH_MODULUS_TOO_SMALL', + name: 'Error', + message: /modulus too small/, + }); + } else { + assert.throws(() => crypto.createDiffieHellman(bits), { + code: 'ERR_OSSL_BN_BITS_TOO_SMALL', + name: 'Error', + message: /bits too small/, + }); + } +} + +for (const g of [-1, 1]) { + const ex = { + code: 'ERR_OSSL_DH_BAD_GENERATOR', + name: 'Error', + message: /bad generator/, + }; + assert.throws(() => crypto.createDiffieHellman('abcdef', g), ex); + assert.throws(() => crypto.createDiffieHellman('abcdef', 'hex', g), ex); +} + +for (const g of [Buffer.from([]), + Buffer.from([0]), + Buffer.from([1])]) { + const ex = { + code: 'ERR_OSSL_DH_BAD_GENERATOR', + name: 'Error', + message: /bad generator/, + }; + assert.throws(() => crypto.createDiffieHellman('abcdef', g), ex); + assert.throws(() => crypto.createDiffieHellman('abcdef', 'hex', g), ex); +} + +[ + [0x1, 0x2], + () => { }, + /abc/, + {}, +].forEach((input) => { + assert.throws( + () => crypto.createDiffieHellman(input), + { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError', + } + ); +}); + +// Invalid test: curve argument is undefined +assert.throws( + () => crypto.createECDH(), + { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError', + message: 'The "curve" argument must be of type string. ' + + 'Received undefined' + }); + +assert.throws( + function() { + crypto.getDiffieHellman('unknown-group'); + }, + { + name: 'Error', + code: 'ERR_CRYPTO_UNKNOWN_DH_GROUP', + message: 'Unknown DH group' + }, + 'crypto.getDiffieHellman(\'unknown-group\') ' + + 'failed to throw the expected error.' +); + +assert.throws( + () => crypto.createDiffieHellman('', true), + { + code: 'ERR_INVALID_ARG_TYPE' + } +); +[true, Symbol(), {}, () => {}, []].forEach((generator) => assert.throws( + () => crypto.createDiffieHellman('', 'base64', generator), + { code: 'ERR_INVALID_ARG_TYPE' } +)); diff --git a/test/parallel/test-crypto-dh-generate-keys.js b/test/parallel/test-crypto-dh-generate-keys.js new file mode 100644 index 00000000000000..fc277bb0d9b8e4 --- /dev/null +++ b/test/parallel/test-crypto-dh-generate-keys.js @@ -0,0 +1,63 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const crypto = require('crypto'); + +{ + const size = common.hasFipsCrypto || common.hasOpenSSL3 ? 1024 : 256; + + function unlessInvalidState(f) { + try { + return f(); + } catch (err) { + if (err.code !== 'ERR_CRYPTO_INVALID_STATE') { + throw err; + } + } + } + + function testGenerateKeysChangesKeys(setup, expected) { + const dh = crypto.createDiffieHellman(size); + setup(dh); + const firstPublicKey = unlessInvalidState(() => dh.getPublicKey()); + const firstPrivateKey = unlessInvalidState(() => dh.getPrivateKey()); + dh.generateKeys(); + const secondPublicKey = dh.getPublicKey(); + const secondPrivateKey = dh.getPrivateKey(); + function changed(shouldChange, first, second) { + if (shouldChange) { + assert.notDeepStrictEqual(first, second); + } else { + assert.deepStrictEqual(first, second); + } + } + changed(expected.includes('public'), firstPublicKey, secondPublicKey); + changed(expected.includes('private'), firstPrivateKey, secondPrivateKey); + } + + // Both the private and the public key are missing: generateKeys() generates both. + testGenerateKeysChangesKeys(() => { + // No setup. + }, ['public', 'private']); + + // Neither key is missing: generateKeys() does nothing. + testGenerateKeysChangesKeys((dh) => { + dh.generateKeys(); + }, []); + + // Only the public key is missing: generateKeys() generates only the public key. + testGenerateKeysChangesKeys((dh) => { + dh.setPrivateKey(Buffer.from('01020304', 'hex')); + }, ['public']); + + // The public key is outdated: generateKeys() generates only the public key. + testGenerateKeysChangesKeys((dh) => { + const oldPublicKey = dh.generateKeys(); + dh.setPrivateKey(Buffer.from('01020304', 'hex')); + assert.deepStrictEqual(dh.getPublicKey(), oldPublicKey); + }, ['public']); +} diff --git a/test/parallel/test-crypto-modp1-error.js b/test/parallel/test-crypto-dh-group-setters.js similarity index 100% rename from test/parallel/test-crypto-modp1-error.js rename to test/parallel/test-crypto-dh-group-setters.js diff --git a/test/parallel/test-crypto-dh.js b/test/parallel/test-crypto-dh.js index c730eac4ce76dd..3b738b7f47ec59 100644 --- a/test/parallel/test-crypto-dh.js +++ b/test/parallel/test-crypto-dh.js @@ -6,51 +6,93 @@ if (!common.hasCrypto) const assert = require('assert'); const crypto = require('crypto'); -const size = common.hasFipsCrypto || common.hasOpenSSL3 ? 1024 : 256; -const dh1 = crypto.createDiffieHellman(size); -const p1 = dh1.getPrime('buffer'); -const dh2 = crypto.createDiffieHellman(p1, 'buffer'); -const key1 = dh1.generateKeys(); -const key2 = dh2.generateKeys('hex'); -const secret1 = dh1.computeSecret(key2, 'hex', 'base64'); -const secret2 = dh2.computeSecret(key1, 'latin1', 'buffer'); - -// Test Diffie-Hellman with two parties sharing a secret, -// using various encodings as we go along -assert.strictEqual(secret2.toString('base64'), secret1); -assert.strictEqual(dh1.verifyError, 0); -assert.strictEqual(dh2.verifyError, 0); +{ + const size = common.hasFipsCrypto || common.hasOpenSSL3 ? 1024 : 256; + const dh1 = crypto.createDiffieHellman(size); + const p1 = dh1.getPrime('buffer'); + const dh2 = crypto.createDiffieHellman(p1, 'buffer'); + const key1 = dh1.generateKeys(); + const key2 = dh2.generateKeys('hex'); + const secret1 = dh1.computeSecret(key2, 'hex', 'base64'); + const secret2 = dh2.computeSecret(key1, 'latin1', 'buffer'); + + // Test Diffie-Hellman with two parties sharing a secret, + // using various encodings as we go along + assert.strictEqual(secret2.toString('base64'), secret1); + assert.strictEqual(dh1.verifyError, 0); + assert.strictEqual(dh2.verifyError, 0); + + // Create "another dh1" using generated keys from dh1, + // and compute secret again + const dh3 = crypto.createDiffieHellman(p1, 'buffer'); + const privkey1 = dh1.getPrivateKey(); + dh3.setPublicKey(key1); + dh3.setPrivateKey(privkey1); + + assert.deepStrictEqual(dh1.getPrime(), dh3.getPrime()); + assert.deepStrictEqual(dh1.getGenerator(), dh3.getGenerator()); + assert.deepStrictEqual(dh1.getPublicKey(), dh3.getPublicKey()); + assert.deepStrictEqual(dh1.getPrivateKey(), dh3.getPrivateKey()); + assert.strictEqual(dh3.verifyError, 0); + + const secret3 = dh3.computeSecret(key2, 'hex', 'base64'); + + assert.strictEqual(secret1, secret3); + + // computeSecret works without a public key set at all. + const dh4 = crypto.createDiffieHellman(p1, 'buffer'); + dh4.setPrivateKey(privkey1); + + assert.deepStrictEqual(dh1.getPrime(), dh4.getPrime()); + assert.deepStrictEqual(dh1.getGenerator(), dh4.getGenerator()); + assert.deepStrictEqual(dh1.getPrivateKey(), dh4.getPrivateKey()); + assert.strictEqual(dh4.verifyError, 0); + + const secret4 = dh4.computeSecret(key2, 'hex', 'base64'); + + assert.strictEqual(secret1, secret4); + + let wrongBlockLength; + if (common.hasOpenSSL3) { + wrongBlockLength = { + message: 'error:1C80006B:Provider routines::wrong final block length', + code: 'ERR_OSSL_WRONG_FINAL_BLOCK_LENGTH', + library: 'Provider routines', + reason: 'wrong final block length' + }; + } else { + wrongBlockLength = { + message: 'error:0606506D:digital envelope' + + ' routines:EVP_DecryptFinal_ex:wrong final block length', + code: 'ERR_OSSL_EVP_WRONG_FINAL_BLOCK_LENGTH', + library: 'digital envelope routines', + reason: 'wrong final block length' + }; + } -// https://github.com/nodejs/node/issues/32738 -// XXX(bnoordhuis) validateInt32() throwing ERR_OUT_OF_RANGE and RangeError -// instead of ERR_INVALID_ARG_TYPE and TypeError is questionable, IMO. -assert.throws(() => crypto.createDiffieHellman(13.37), { - code: 'ERR_OUT_OF_RANGE', - name: 'RangeError', - message: 'The value of "sizeOrKey" is out of range. ' + - 'It must be an integer. Received 13.37', -}); + // Run this one twice to make sure that the dh3 clears its error properly + { + const c = crypto.createDecipheriv('aes-128-ecb', crypto.randomBytes(16), ''); + assert.throws(() => { + c.final('utf8'); + }, wrongBlockLength); + } -assert.throws(() => crypto.createDiffieHellman('abcdef', 13.37), { - code: 'ERR_OUT_OF_RANGE', - name: 'RangeError', - message: 'The value of "generator" is out of range. ' + - 'It must be an integer. Received 13.37', -}); + { + const c = crypto.createDecipheriv('aes-128-ecb', crypto.randomBytes(16), ''); + assert.throws(() => { + c.final('utf8'); + }, wrongBlockLength); + } -for (const bits of [-1, 0, 1]) { - if (common.hasOpenSSL3) { - assert.throws(() => crypto.createDiffieHellman(bits), { - code: 'ERR_OSSL_DH_MODULUS_TOO_SMALL', - name: 'Error', - message: /modulus too small/, - }); - } else { - assert.throws(() => crypto.createDiffieHellman(bits), { - code: 'ERR_OSSL_BN_BITS_TOO_SMALL', - name: 'Error', - message: /bits too small/, - }); + { + const v = crypto.constants.OPENSSL_VERSION_NUMBER; + const hasOpenSSL3WithNewErrorMessage = (v >= 0x300000c0 && v <= 0x30100000) || (v >= 0x30100040 && v <= 0x30200000); + assert.throws(() => { + dh3.computeSecret(''); + }, { message: common.hasOpenSSL3 && !hasOpenSSL3WithNewErrorMessage ? + 'error:02800080:Diffie-Hellman routines::invalid secret' : + 'Supplied key is too small' }); } } @@ -61,197 +103,6 @@ for (const bits of [-1, 0, 1]) { crypto.createDiffieHellman('abcdef', 'hex', g); } -for (const g of [-1, 1]) { - const ex = { - code: 'ERR_OSSL_DH_BAD_GENERATOR', - name: 'Error', - message: /bad generator/, - }; - assert.throws(() => crypto.createDiffieHellman('abcdef', g), ex); - assert.throws(() => crypto.createDiffieHellman('abcdef', 'hex', g), ex); -} - -crypto.createDiffieHellman('abcdef', Buffer.from([2])); // OK - -for (const g of [Buffer.from([]), - Buffer.from([0]), - Buffer.from([1])]) { - const ex = { - code: 'ERR_OSSL_DH_BAD_GENERATOR', - name: 'Error', - message: /bad generator/, - }; - assert.throws(() => crypto.createDiffieHellman('abcdef', g), ex); - assert.throws(() => crypto.createDiffieHellman('abcdef', 'hex', g), ex); -} - -[ - [0x1, 0x2], - () => { }, - /abc/, - {}, -].forEach((input) => { - assert.throws( - () => crypto.createDiffieHellman(input), - { - code: 'ERR_INVALID_ARG_TYPE', - name: 'TypeError', - } - ); -}); - -// Create "another dh1" using generated keys from dh1, -// and compute secret again -const dh3 = crypto.createDiffieHellman(p1, 'buffer'); -const privkey1 = dh1.getPrivateKey(); -dh3.setPublicKey(key1); -dh3.setPrivateKey(privkey1); - -assert.deepStrictEqual(dh1.getPrime(), dh3.getPrime()); -assert.deepStrictEqual(dh1.getGenerator(), dh3.getGenerator()); -assert.deepStrictEqual(dh1.getPublicKey(), dh3.getPublicKey()); -assert.deepStrictEqual(dh1.getPrivateKey(), dh3.getPrivateKey()); -assert.strictEqual(dh3.verifyError, 0); - -const secret3 = dh3.computeSecret(key2, 'hex', 'base64'); - -assert.strictEqual(secret1, secret3); - -// computeSecret works without a public key set at all. -const dh4 = crypto.createDiffieHellman(p1, 'buffer'); -dh4.setPrivateKey(privkey1); - -assert.deepStrictEqual(dh1.getPrime(), dh4.getPrime()); -assert.deepStrictEqual(dh1.getGenerator(), dh4.getGenerator()); -assert.deepStrictEqual(dh1.getPrivateKey(), dh4.getPrivateKey()); -assert.strictEqual(dh4.verifyError, 0); - -const secret4 = dh4.computeSecret(key2, 'hex', 'base64'); - -assert.strictEqual(secret1, secret4); - -let wrongBlockLength; -if (common.hasOpenSSL3) { - wrongBlockLength = { - message: 'error:1C80006B:Provider routines::wrong final block length', - code: 'ERR_OSSL_WRONG_FINAL_BLOCK_LENGTH', - library: 'Provider routines', - reason: 'wrong final block length' - }; -} else { - wrongBlockLength = { - message: 'error:0606506D:digital envelope' + - ' routines:EVP_DecryptFinal_ex:wrong final block length', - code: 'ERR_OSSL_EVP_WRONG_FINAL_BLOCK_LENGTH', - library: 'digital envelope routines', - reason: 'wrong final block length' - }; -} - -// Run this one twice to make sure that the dh3 clears its error properly -{ - const c = crypto.createDecipheriv('aes-128-ecb', crypto.randomBytes(16), ''); - assert.throws(() => { - c.final('utf8'); - }, wrongBlockLength); -} - -{ - const c = crypto.createDecipheriv('aes-128-ecb', crypto.randomBytes(16), ''); - assert.throws(() => { - c.final('utf8'); - }, wrongBlockLength); -} - -assert.throws(() => { - dh3.computeSecret(''); -}, { message: common.hasOpenSSL3 ? - 'error:02800080:Diffie-Hellman routines::invalid secret' : - 'Supplied key is too small' }); - -// Invalid test: curve argument is undefined -assert.throws( - () => crypto.createECDH(), - { - code: 'ERR_INVALID_ARG_TYPE', - name: 'TypeError', - message: 'The "curve" argument must be of type string. ' + - 'Received undefined' - }); - -assert.throws( - function() { - crypto.getDiffieHellman('unknown-group'); - }, - { - name: 'Error', - code: 'ERR_CRYPTO_UNKNOWN_DH_GROUP', - message: 'Unknown DH group' - }, - 'crypto.getDiffieHellman(\'unknown-group\') ' + - 'failed to throw the expected error.' -); - -assert.throws( - () => crypto.createDiffieHellman('', true), - { - code: 'ERR_INVALID_ARG_TYPE' - } -); -[true, Symbol(), {}, () => {}, []].forEach((generator) => assert.throws( - () => crypto.createDiffieHellman('', 'base64', generator), - { code: 'ERR_INVALID_ARG_TYPE' } -)); - { - function unlessInvalidState(f) { - try { - return f(); - } catch (err) { - if (err.code !== 'ERR_CRYPTO_INVALID_STATE') { - throw err; - } - } - } - - function testGenerateKeysChangesKeys(setup, expected) { - const dh = crypto.createDiffieHellman(size); - setup(dh); - const firstPublicKey = unlessInvalidState(() => dh.getPublicKey()); - const firstPrivateKey = unlessInvalidState(() => dh.getPrivateKey()); - dh.generateKeys(); - const secondPublicKey = dh.getPublicKey(); - const secondPrivateKey = dh.getPrivateKey(); - function changed(shouldChange, first, second) { - if (shouldChange) { - assert.notDeepStrictEqual(first, second); - } else { - assert.deepStrictEqual(first, second); - } - } - changed(expected.includes('public'), firstPublicKey, secondPublicKey); - changed(expected.includes('private'), firstPrivateKey, secondPrivateKey); - } - - // Both the private and the public key are missing: generateKeys() generates both. - testGenerateKeysChangesKeys(() => { - // No setup. - }, ['public', 'private']); - - // Neither key is missing: generateKeys() does nothing. - testGenerateKeysChangesKeys((dh) => { - dh.generateKeys(); - }, []); - - // Only the public key is missing: generateKeys() generates only the public key. - testGenerateKeysChangesKeys((dh) => { - dh.setPrivateKey(Buffer.from('01020304', 'hex')); - }, ['public']); - - // The public key is outdated: generateKeys() generates only the public key. - testGenerateKeysChangesKeys((dh) => { - const oldPublicKey = dh.generateKeys(); - dh.setPrivateKey(Buffer.from('01020304', 'hex')); - assert.deepStrictEqual(dh.getPublicKey(), oldPublicKey); - }, ['public']); + crypto.createDiffieHellman('abcdef', Buffer.from([2])); // OK } diff --git a/test/parallel/test-crypto-keygen-async-dsa-key-object.js b/test/parallel/test-crypto-keygen-async-dsa-key-object.js new file mode 100644 index 00000000000000..c15807295541e2 --- /dev/null +++ b/test/parallel/test-crypto-keygen-async-dsa-key-object.js @@ -0,0 +1,32 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); + +// Test async DSA key object generation. +{ + generateKeyPair('dsa', { + modulusLength: common.hasOpenSSL3 ? 2048 : 512, + divisorLength: 256 + }, common.mustSucceed((publicKey, privateKey) => { + assert.strictEqual(publicKey.type, 'public'); + assert.strictEqual(publicKey.asymmetricKeyType, 'dsa'); + assert.deepStrictEqual(publicKey.asymmetricKeyDetails, { + modulusLength: common.hasOpenSSL3 ? 2048 : 512, + divisorLength: 256 + }); + + assert.strictEqual(privateKey.type, 'private'); + assert.strictEqual(privateKey.asymmetricKeyType, 'dsa'); + assert.deepStrictEqual(privateKey.asymmetricKeyDetails, { + modulusLength: common.hasOpenSSL3 ? 2048 : 512, + divisorLength: 256 + }); + })); +} diff --git a/test/parallel/test-crypto-keygen-async-dsa.js b/test/parallel/test-crypto-keygen-async-dsa.js new file mode 100644 index 00000000000000..048c0ce6fb92ef --- /dev/null +++ b/test/parallel/test-crypto-keygen-async-dsa.js @@ -0,0 +1,64 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); +const { + assertApproximateSize, + testSignVerify, + spkiExp, +} = require('../common/crypto'); + +// Test async DSA key generation. +{ + const privateKeyEncoding = { + type: 'pkcs8', + format: 'der' + }; + + generateKeyPair('dsa', { + modulusLength: common.hasOpenSSL3 ? 2048 : 512, + divisorLength: 256, + publicKeyEncoding: { + type: 'spki', + format: 'pem' + }, + privateKeyEncoding: { + cipher: 'aes-128-cbc', + passphrase: 'secret', + ...privateKeyEncoding + } + }, common.mustSucceed((publicKey, privateKeyDER) => { + assert.strictEqual(typeof publicKey, 'string'); + assert.match(publicKey, spkiExp); + // The private key is DER-encoded. + assert(Buffer.isBuffer(privateKeyDER)); + + assertApproximateSize(publicKey, common.hasOpenSSL3 ? 1194 : 440); + assertApproximateSize(privateKeyDER, common.hasOpenSSL3 ? 721 : 336); + + // Since the private key is encrypted, signing shouldn't work anymore. + assert.throws(() => { + return testSignVerify(publicKey, { + key: privateKeyDER, + ...privateKeyEncoding + }); + }, { + name: 'TypeError', + code: 'ERR_MISSING_PASSPHRASE', + message: 'Passphrase required for encrypted key' + }); + + // Signing should work with the correct password. + testSignVerify(publicKey, { + key: privateKeyDER, + ...privateKeyEncoding, + passphrase: 'secret' + }); + })); +} diff --git a/test/parallel/test-crypto-keygen-async-elliptic-curve-jwk-ec.js b/test/parallel/test-crypto-keygen-async-elliptic-curve-jwk-ec.js new file mode 100644 index 00000000000000..bddb4aa2fbdcd6 --- /dev/null +++ b/test/parallel/test-crypto-keygen-async-elliptic-curve-jwk-ec.js @@ -0,0 +1,35 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); + +// Test async elliptic curve key generation with 'jwk' encoding and named +// curve. +['P-384', 'P-256', 'P-521', 'secp256k1'].forEach((curve) => { + generateKeyPair('ec', { + namedCurve: curve, + publicKeyEncoding: { + format: 'jwk' + }, + privateKeyEncoding: { + format: 'jwk' + } + }, common.mustSucceed((publicKey, privateKey) => { + assert.strictEqual(typeof publicKey, 'object'); + assert.strictEqual(typeof privateKey, 'object'); + assert.strictEqual(publicKey.x, privateKey.x); + assert.strictEqual(publicKey.y, privateKey.y); + assert(!publicKey.d); + assert(privateKey.d); + assert.strictEqual(publicKey.kty, 'EC'); + assert.strictEqual(publicKey.kty, privateKey.kty); + assert.strictEqual(publicKey.crv, curve); + assert.strictEqual(publicKey.crv, privateKey.crv); + })); +}); diff --git a/test/parallel/test-crypto-keygen-async-elliptic-curve-jwk-rsa.js b/test/parallel/test-crypto-keygen-async-elliptic-curve-jwk-rsa.js new file mode 100644 index 00000000000000..449d1a97f9f68b --- /dev/null +++ b/test/parallel/test-crypto-keygen-async-elliptic-curve-jwk-rsa.js @@ -0,0 +1,38 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); + +// Test async elliptic curve key generation with 'jwk' encoding and RSA. +{ + generateKeyPair('rsa', { + modulusLength: 1024, + publicKeyEncoding: { + format: 'jwk' + }, + privateKeyEncoding: { + format: 'jwk' + } + }, common.mustSucceed((publicKey, privateKey) => { + assert.strictEqual(typeof publicKey, 'object'); + assert.strictEqual(typeof privateKey, 'object'); + assert.strictEqual(publicKey.kty, 'RSA'); + assert.strictEqual(publicKey.kty, privateKey.kty); + assert.strictEqual(typeof publicKey.n, 'string'); + assert.strictEqual(publicKey.n, privateKey.n); + assert.strictEqual(typeof publicKey.e, 'string'); + assert.strictEqual(publicKey.e, privateKey.e); + assert.strictEqual(typeof privateKey.d, 'string'); + assert.strictEqual(typeof privateKey.p, 'string'); + assert.strictEqual(typeof privateKey.q, 'string'); + assert.strictEqual(typeof privateKey.dp, 'string'); + assert.strictEqual(typeof privateKey.dq, 'string'); + assert.strictEqual(typeof privateKey.qi, 'string'); + })); +} diff --git a/test/parallel/test-crypto-keygen-async-elliptic-curve-jwk.js b/test/parallel/test-crypto-keygen-async-elliptic-curve-jwk.js new file mode 100644 index 00000000000000..5243edd8c825b7 --- /dev/null +++ b/test/parallel/test-crypto-keygen-async-elliptic-curve-jwk.js @@ -0,0 +1,40 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); + +// Test async elliptic curve key generation with 'jwk' encoding. +{ + [ + 'ed25519', + 'ed448', + 'x25519', + 'x448', + ].forEach((type) => { + generateKeyPair(type, { + publicKeyEncoding: { + format: 'jwk' + }, + privateKeyEncoding: { + format: 'jwk' + } + }, common.mustSucceed((publicKey, privateKey) => { + assert.strictEqual(typeof publicKey, 'object'); + assert.strictEqual(typeof privateKey, 'object'); + assert.strictEqual(publicKey.x, privateKey.x); + assert(!publicKey.d); + assert(privateKey.d); + assert.strictEqual(publicKey.kty, 'OKP'); + assert.strictEqual(publicKey.kty, privateKey.kty); + const expectedCrv = `${type.charAt(0).toUpperCase()}${type.slice(1)}`; + assert.strictEqual(publicKey.crv, expectedCrv); + assert.strictEqual(publicKey.crv, privateKey.crv); + })); + }); +} diff --git a/test/parallel/test-crypto-keygen-async-encrypted-private-key-der.js b/test/parallel/test-crypto-keygen-async-encrypted-private-key-der.js new file mode 100644 index 00000000000000..3203dfe16eb690 --- /dev/null +++ b/test/parallel/test-crypto-keygen-async-encrypted-private-key-der.js @@ -0,0 +1,50 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); +const { + assertApproximateSize, + testEncryptDecrypt, + testSignVerify, +} = require('../common/crypto'); + +// Test async RSA key generation with an encrypted private key, but encoded as DER. +{ + generateKeyPair('rsa', { + publicExponent: 0x10001, + modulusLength: 512, + publicKeyEncoding: { + type: 'pkcs1', + format: 'der' + }, + privateKeyEncoding: { + type: 'pkcs8', + format: 'der' + } + }, common.mustSucceed((publicKeyDER, privateKeyDER) => { + assert(Buffer.isBuffer(publicKeyDER)); + assertApproximateSize(publicKeyDER, 74); + + assert(Buffer.isBuffer(privateKeyDER)); + + const publicKey = { + key: publicKeyDER, + type: 'pkcs1', + format: 'der', + }; + const privateKey = { + key: privateKeyDER, + format: 'der', + type: 'pkcs8', + passphrase: 'secret' + }; + testEncryptDecrypt(publicKey, privateKey); + testSignVerify(publicKey, privateKey); + })); +} diff --git a/test/parallel/test-crypto-keygen-async-encrypted-private-key.js b/test/parallel/test-crypto-keygen-async-encrypted-private-key.js new file mode 100644 index 00000000000000..727cccc6f3eff5 --- /dev/null +++ b/test/parallel/test-crypto-keygen-async-encrypted-private-key.js @@ -0,0 +1,67 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); +const { + assertApproximateSize, + testEncryptDecrypt, + testSignVerify, +} = require('../common/crypto'); + +// Test async RSA key generation with an encrypted private key, but encoded as DER. +{ + generateKeyPair('rsa', { + publicExponent: 0x10001, + modulusLength: 512, + publicKeyEncoding: { + type: 'pkcs1', + format: 'der' + }, + privateKeyEncoding: { + type: 'pkcs8', + format: 'der', + cipher: 'aes-256-cbc', + passphrase: 'secret' + } + }, common.mustSucceed((publicKeyDER, privateKeyDER) => { + assert(Buffer.isBuffer(publicKeyDER)); + assertApproximateSize(publicKeyDER, 74); + + assert(Buffer.isBuffer(privateKeyDER)); + + // Since the private key is encrypted, signing shouldn't work anymore. + const publicKey = { + key: publicKeyDER, + type: 'pkcs1', + format: 'der', + }; + assert.throws(() => { + testSignVerify(publicKey, { + key: privateKeyDER, + format: 'der', + type: 'pkcs8' + }); + }, { + name: 'TypeError', + code: 'ERR_MISSING_PASSPHRASE', + message: 'Passphrase required for encrypted key' + }); + + // Signing should work with the correct password. + + const privateKey = { + key: privateKeyDER, + format: 'der', + type: 'pkcs8', + passphrase: 'secret' + }; + testEncryptDecrypt(publicKey, privateKey); + testSignVerify(publicKey, privateKey); + })); +} diff --git a/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted-p256.js b/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted-p256.js new file mode 100644 index 00000000000000..553674774571d3 --- /dev/null +++ b/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted-p256.js @@ -0,0 +1,55 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); +const { + testSignVerify, + spkiExp, + pkcs8EncExp, +} = require('../common/crypto'); + +// Test async elliptic curve key generation, e.g. for ECDSA, with an encrypted +// private key with paramEncoding explicit. +{ + generateKeyPair('ec', { + namedCurve: 'P-256', + paramEncoding: 'explicit', + publicKeyEncoding: { + type: 'spki', + format: 'pem' + }, + privateKeyEncoding: { + type: 'pkcs8', + format: 'pem', + cipher: 'aes-128-cbc', + passphrase: 'top secret' + } + }, common.mustSucceed((publicKey, privateKey) => { + assert.strictEqual(typeof publicKey, 'string'); + assert.match(publicKey, spkiExp); + assert.strictEqual(typeof privateKey, 'string'); + assert.match(privateKey, pkcs8EncExp); + + // Since the private key is encrypted, signing shouldn't work anymore. + assert.throws(() => testSignVerify(publicKey, privateKey), + common.hasOpenSSL3 ? { + message: 'error:07880109:common libcrypto ' + + 'routines::interrupted or cancelled' + } : { + name: 'TypeError', + code: 'ERR_MISSING_PASSPHRASE', + message: 'Passphrase required for encrypted key' + }); + + testSignVerify(publicKey, { + key: privateKey, + passphrase: 'top secret' + }); + })); +} diff --git a/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted.js.js b/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted.js.js new file mode 100644 index 00000000000000..79a132eed0b854 --- /dev/null +++ b/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted.js.js @@ -0,0 +1,52 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); +const { + testSignVerify, + spkiExp, + sec1EncExp, +} = require('../common/crypto'); + +{ + // Test async explicit elliptic curve key generation with an encrypted + // private key. + generateKeyPair('ec', { + namedCurve: 'prime256v1', + paramEncoding: 'explicit', + publicKeyEncoding: { + type: 'spki', + format: 'pem' + }, + privateKeyEncoding: { + type: 'sec1', + format: 'pem', + cipher: 'aes-128-cbc', + passphrase: 'secret' + } + }, common.mustSucceed((publicKey, privateKey) => { + assert.strictEqual(typeof publicKey, 'string'); + assert.match(publicKey, spkiExp); + assert.strictEqual(typeof privateKey, 'string'); + assert.match(privateKey, sec1EncExp('AES-128-CBC')); + + // Since the private key is encrypted, signing shouldn't work anymore. + assert.throws(() => testSignVerify(publicKey, privateKey), + common.hasOpenSSL3 ? { + message: 'error:07880109:common libcrypto ' + + 'routines::interrupted or cancelled' + } : { + name: 'TypeError', + code: 'ERR_MISSING_PASSPHRASE', + message: 'Passphrase required for encrypted key' + }); + + testSignVerify(publicKey, { key: privateKey, passphrase: 'secret' }); + })); +} diff --git a/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve.js b/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve.js new file mode 100644 index 00000000000000..46223f08d7445a --- /dev/null +++ b/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve.js @@ -0,0 +1,39 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); +const { + testSignVerify, + spkiExp, + sec1Exp, +} = require('../common/crypto'); + +// Test async explicit elliptic curve key generation, e.g. for ECDSA, +// with a SEC1 private key with paramEncoding explicit. +{ + generateKeyPair('ec', { + namedCurve: 'prime256v1', + paramEncoding: 'explicit', + publicKeyEncoding: { + type: 'spki', + format: 'pem' + }, + privateKeyEncoding: { + type: 'sec1', + format: 'pem' + } + }, common.mustSucceed((publicKey, privateKey) => { + assert.strictEqual(typeof publicKey, 'string'); + assert.match(publicKey, spkiExp); + assert.strictEqual(typeof privateKey, 'string'); + assert.match(privateKey, sec1Exp); + + testSignVerify(publicKey, privateKey); + })); +} diff --git a/test/parallel/test-crypto-keygen-async-named-elliptic-curve-encrypted-p256.js b/test/parallel/test-crypto-keygen-async-named-elliptic-curve-encrypted-p256.js new file mode 100644 index 00000000000000..5e7d1a6c9b6611 --- /dev/null +++ b/test/parallel/test-crypto-keygen-async-named-elliptic-curve-encrypted-p256.js @@ -0,0 +1,55 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); +const { + testSignVerify, + spkiExp, + pkcs8EncExp, +} = require('../common/crypto'); + +// Test async elliptic curve key generation, e.g. for ECDSA, with an encrypted +// private key. +{ + generateKeyPair('ec', { + namedCurve: 'P-256', + paramEncoding: 'named', + publicKeyEncoding: { + type: 'spki', + format: 'pem' + }, + privateKeyEncoding: { + type: 'pkcs8', + format: 'pem', + cipher: 'aes-128-cbc', + passphrase: 'top secret' + } + }, common.mustSucceed((publicKey, privateKey) => { + assert.strictEqual(typeof publicKey, 'string'); + assert.match(publicKey, spkiExp); + assert.strictEqual(typeof privateKey, 'string'); + assert.match(privateKey, pkcs8EncExp); + + // Since the private key is encrypted, signing shouldn't work anymore. + assert.throws(() => testSignVerify(publicKey, privateKey), + common.hasOpenSSL3 ? { + message: 'error:07880109:common libcrypto ' + + 'routines::interrupted or cancelled' + } : { + name: 'TypeError', + code: 'ERR_MISSING_PASSPHRASE', + message: 'Passphrase required for encrypted key' + }); + + testSignVerify(publicKey, { + key: privateKey, + passphrase: 'top secret' + }); + })); +} diff --git a/test/parallel/test-crypto-keygen-async-named-elliptic-curve-encrypted.js b/test/parallel/test-crypto-keygen-async-named-elliptic-curve-encrypted.js new file mode 100644 index 00000000000000..1cc93d0a794931 --- /dev/null +++ b/test/parallel/test-crypto-keygen-async-named-elliptic-curve-encrypted.js @@ -0,0 +1,52 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); +const { + testSignVerify, + spkiExp, + sec1EncExp, +} = require('../common/crypto'); + +{ + // Test async named elliptic curve key generation with an encrypted + // private key. + generateKeyPair('ec', { + namedCurve: 'prime256v1', + paramEncoding: 'named', + publicKeyEncoding: { + type: 'spki', + format: 'pem' + }, + privateKeyEncoding: { + type: 'sec1', + format: 'pem', + cipher: 'aes-128-cbc', + passphrase: 'secret' + } + }, common.mustSucceed((publicKey, privateKey) => { + assert.strictEqual(typeof publicKey, 'string'); + assert.match(publicKey, spkiExp); + assert.strictEqual(typeof privateKey, 'string'); + assert.match(privateKey, sec1EncExp('AES-128-CBC')); + + // Since the private key is encrypted, signing shouldn't work anymore. + assert.throws(() => testSignVerify(publicKey, privateKey), + common.hasOpenSSL3 ? { + message: 'error:07880109:common libcrypto ' + + 'routines::interrupted or cancelled' + } : { + name: 'TypeError', + code: 'ERR_MISSING_PASSPHRASE', + message: 'Passphrase required for encrypted key' + }); + + testSignVerify(publicKey, { key: privateKey, passphrase: 'secret' }); + })); +} diff --git a/test/parallel/test-crypto-keygen-async-named-elliptic-curve.js b/test/parallel/test-crypto-keygen-async-named-elliptic-curve.js new file mode 100644 index 00000000000000..a1dfdbce1f2360 --- /dev/null +++ b/test/parallel/test-crypto-keygen-async-named-elliptic-curve.js @@ -0,0 +1,39 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); +const { + testSignVerify, + spkiExp, + sec1Exp, +} = require('../common/crypto'); + +// Test async named elliptic curve key generation, e.g. for ECDSA, +// with a SEC1 private key. +{ + generateKeyPair('ec', { + namedCurve: 'prime256v1', + paramEncoding: 'named', + publicKeyEncoding: { + type: 'spki', + format: 'pem' + }, + privateKeyEncoding: { + type: 'sec1', + format: 'pem' + } + }, common.mustSucceed((publicKey, privateKey) => { + assert.strictEqual(typeof publicKey, 'string'); + assert.match(publicKey, spkiExp); + assert.strictEqual(typeof privateKey, 'string'); + assert.match(privateKey, sec1Exp); + + testSignVerify(publicKey, privateKey); + })); +} diff --git a/test/parallel/test-crypto-keygen-async-rsa.js b/test/parallel/test-crypto-keygen-async-rsa.js new file mode 100644 index 00000000000000..f4a83809dc73c7 --- /dev/null +++ b/test/parallel/test-crypto-keygen-async-rsa.js @@ -0,0 +1,61 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); +const { + assertApproximateSize, + testEncryptDecrypt, + testSignVerify, + pkcs1EncExp, +} = require('../common/crypto'); + +// Test async RSA key generation with an encrypted private key. +{ + generateKeyPair('rsa', { + publicExponent: 0x10001, + modulusLength: 512, + publicKeyEncoding: { + type: 'pkcs1', + format: 'der' + }, + privateKeyEncoding: { + type: 'pkcs1', + format: 'pem', + cipher: 'aes-256-cbc', + passphrase: 'secret' + } + }, common.mustSucceed((publicKeyDER, privateKey) => { + assert(Buffer.isBuffer(publicKeyDER)); + assertApproximateSize(publicKeyDER, 74); + + assert.strictEqual(typeof privateKey, 'string'); + assert.match(privateKey, pkcs1EncExp('AES-256-CBC')); + + // Since the private key is encrypted, signing shouldn't work anymore. + const publicKey = { + key: publicKeyDER, + type: 'pkcs1', + format: 'der', + }; + const expectedError = common.hasOpenSSL3 ? { + name: 'Error', + message: 'error:07880109:common libcrypto routines::interrupted or ' + + 'cancelled' + } : { + name: 'TypeError', + code: 'ERR_MISSING_PASSPHRASE', + message: 'Passphrase required for encrypted key' + }; + assert.throws(() => testSignVerify(publicKey, privateKey), expectedError); + + const key = { key: privateKey, passphrase: 'secret' }; + testEncryptDecrypt(publicKey, key); + testSignVerify(publicKey, key); + })); +} diff --git a/test/parallel/test-crypto-keygen-bit-length.js b/test/parallel/test-crypto-keygen-bit-length.js new file mode 100644 index 00000000000000..08772ba2e496b8 --- /dev/null +++ b/test/parallel/test-crypto-keygen-bit-length.js @@ -0,0 +1,39 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); + +// This tests check that generateKeyPair returns correct bit length in +// KeyObject's asymmetricKeyDetails. +// https://github.com/nodejs/node/issues/46102#issuecomment-1372153541 +{ + generateKeyPair('rsa', { + modulusLength: 513, + }, common.mustSucceed((publicKey, privateKey) => { + assert.strictEqual(privateKey.asymmetricKeyDetails.modulusLength, 513); + assert.strictEqual(publicKey.asymmetricKeyDetails.modulusLength, 513); + })); + + generateKeyPair('rsa-pss', { + modulusLength: 513, + }, common.mustSucceed((publicKey, privateKey) => { + assert.strictEqual(privateKey.asymmetricKeyDetails.modulusLength, 513); + assert.strictEqual(publicKey.asymmetricKeyDetails.modulusLength, 513); + })); + + if (common.hasOpenSSL3) { + generateKeyPair('dsa', { + modulusLength: 2049, + divisorLength: 256, + }, common.mustSucceed((publicKey, privateKey) => { + assert.strictEqual(privateKey.asymmetricKeyDetails.modulusLength, 2049); + assert.strictEqual(publicKey.asymmetricKeyDetails.modulusLength, 2049); + })); + } +} diff --git a/test/parallel/test-crypto-keygen-dh-classic.js b/test/parallel/test-crypto-keygen-dh-classic.js new file mode 100644 index 00000000000000..ecf5ce7863b8a4 --- /dev/null +++ b/test/parallel/test-crypto-keygen-dh-classic.js @@ -0,0 +1,23 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); + +// Test classic Diffie-Hellman key generation. +{ + generateKeyPair('dh', { + primeLength: 512 + }, common.mustSucceed((publicKey, privateKey) => { + assert.strictEqual(publicKey.type, 'public'); + assert.strictEqual(publicKey.asymmetricKeyType, 'dh'); + + assert.strictEqual(privateKey.type, 'private'); + assert.strictEqual(privateKey.asymmetricKeyType, 'dh'); + })); +} diff --git a/test/parallel/test-crypto-keygen-duplicate-deprecated-option.js b/test/parallel/test-crypto-keygen-duplicate-deprecated-option.js new file mode 100644 index 00000000000000..854ad6e35efcd3 --- /dev/null +++ b/test/parallel/test-crypto-keygen-duplicate-deprecated-option.js @@ -0,0 +1,43 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); + +// This test makes sure deprecated and new options may be used +// simultaneously so long as they're identical values. +{ + generateKeyPair('rsa-pss', { + modulusLength: 512, + saltLength: 16, + hash: 'sha256', + hashAlgorithm: 'sha256', + mgf1Hash: 'sha256', + mgf1HashAlgorithm: 'sha256' + }, common.mustSucceed((publicKey, privateKey) => { + assert.strictEqual(publicKey.type, 'public'); + assert.strictEqual(publicKey.asymmetricKeyType, 'rsa-pss'); + assert.deepStrictEqual(publicKey.asymmetricKeyDetails, { + modulusLength: 512, + publicExponent: 65537n, + hashAlgorithm: 'sha256', + mgf1HashAlgorithm: 'sha256', + saltLength: 16 + }); + + assert.strictEqual(privateKey.type, 'private'); + assert.strictEqual(privateKey.asymmetricKeyType, 'rsa-pss'); + assert.deepStrictEqual(privateKey.asymmetricKeyDetails, { + modulusLength: 512, + publicExponent: 65537n, + hashAlgorithm: 'sha256', + mgf1HashAlgorithm: 'sha256', + saltLength: 16 + }); + })); +} diff --git a/test/parallel/test-crypto-keygen-eddsa.js b/test/parallel/test-crypto-keygen-eddsa.js new file mode 100644 index 00000000000000..5a097c2524f3ea --- /dev/null +++ b/test/parallel/test-crypto-keygen-eddsa.js @@ -0,0 +1,27 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); + +// Test EdDSA key generation. +{ + if (!/^1\.1\.0/.test(process.versions.openssl)) { + ['ed25519', 'ed448', 'x25519', 'x448'].forEach((keyType) => { + generateKeyPair(keyType, common.mustSucceed((publicKey, privateKey) => { + assert.strictEqual(publicKey.type, 'public'); + assert.strictEqual(publicKey.asymmetricKeyType, keyType); + assert.deepStrictEqual(publicKey.asymmetricKeyDetails, {}); + + assert.strictEqual(privateKey.type, 'private'); + assert.strictEqual(privateKey.asymmetricKeyType, keyType); + assert.deepStrictEqual(privateKey.asymmetricKeyDetails, {}); + })); + }); + } +} diff --git a/test/parallel/test-crypto-keygen-empty-passphrase-no-error.js b/test/parallel/test-crypto-keygen-empty-passphrase-no-error.js new file mode 100644 index 00000000000000..6c7938f99e1bb6 --- /dev/null +++ b/test/parallel/test-crypto-keygen-empty-passphrase-no-error.js @@ -0,0 +1,29 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); + +// Passing an empty passphrase string should not throw ERR_OSSL_CRYPTO_MALLOC_FAILURE even on OpenSSL 3. +// Regression test for https://github.com/nodejs/node/issues/41428. +generateKeyPair('rsa', { + modulusLength: 1024, + publicKeyEncoding: { + type: 'spki', + format: 'pem' + }, + privateKeyEncoding: { + type: 'pkcs8', + format: 'pem', + cipher: 'aes-256-cbc', + passphrase: '' + } +}, common.mustSucceed((publicKey, privateKey) => { + assert.strictEqual(typeof publicKey, 'string'); + assert.strictEqual(typeof privateKey, 'string'); +})); diff --git a/test/parallel/test-crypto-keygen-empty-passphrase-no-prompt.js b/test/parallel/test-crypto-keygen-empty-passphrase-no-prompt.js new file mode 100644 index 00000000000000..7679a492c3194c --- /dev/null +++ b/test/parallel/test-crypto-keygen-empty-passphrase-no-prompt.js @@ -0,0 +1,53 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + createPrivateKey, + generateKeyPair, +} = require('crypto'); +const { + testSignVerify, +} = require('../common/crypto'); + +// Passing an empty passphrase string should not cause OpenSSL's default +// passphrase prompt in the terminal. +// See https://github.com/nodejs/node/issues/35898. +for (const type of ['pkcs1', 'pkcs8']) { + generateKeyPair('rsa', { + modulusLength: 1024, + privateKeyEncoding: { + type, + format: 'pem', + cipher: 'aes-256-cbc', + passphrase: '' + } + }, common.mustSucceed((publicKey, privateKey) => { + assert.strictEqual(publicKey.type, 'public'); + + for (const passphrase of ['', Buffer.alloc(0)]) { + const privateKeyObject = createPrivateKey({ + passphrase, + key: privateKey + }); + assert.strictEqual(privateKeyObject.asymmetricKeyType, 'rsa'); + } + + // Encrypting with an empty passphrase is not the same as not encrypting + // the key, and not specifying a passphrase should fail when decoding it. + assert.throws(() => { + return testSignVerify(publicKey, privateKey); + }, common.hasOpenSSL3 ? { + name: 'Error', + code: 'ERR_OSSL_CRYPTO_INTERRUPTED_OR_CANCELLED', + message: 'error:07880109:common libcrypto routines::interrupted or cancelled' + } : { + name: 'TypeError', + code: 'ERR_MISSING_PASSPHRASE', + message: 'Passphrase required for encrypted key' + }); + })); +} diff --git a/test/parallel/test-crypto-keygen-invalid-parameter-encoding-dsa.js b/test/parallel/test-crypto-keygen-invalid-parameter-encoding-dsa.js new file mode 100644 index 00000000000000..b5ff5dc2059c1b --- /dev/null +++ b/test/parallel/test-crypto-keygen-invalid-parameter-encoding-dsa.js @@ -0,0 +1,28 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); + +const { + generateKeyPairSync, +} = require('crypto'); + +// Test invalid parameter encoding. +{ + assert.throws(() => generateKeyPairSync('dsa', { + modulusLength: 1024, + publicKeyEncoding: { + format: 'jwk' + }, + privateKeyEncoding: { + format: 'jwk' + } + }), { + name: 'Error', + code: 'ERR_CRYPTO_JWK_UNSUPPORTED_KEY_TYPE', + message: 'Unsupported JWK Key Type.' + }); +} diff --git a/test/parallel/test-crypto-keygen-invalid-parameter-encoding-ec.js b/test/parallel/test-crypto-keygen-invalid-parameter-encoding-ec.js new file mode 100644 index 00000000000000..b4adb58d0fab5a --- /dev/null +++ b/test/parallel/test-crypto-keygen-invalid-parameter-encoding-ec.js @@ -0,0 +1,27 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); + +const { + generateKeyPairSync, +} = require('crypto'); + +{ + assert.throws(() => generateKeyPairSync('ec', { + namedCurve: 'secp224r1', + publicKeyEncoding: { + format: 'jwk' + }, + privateKeyEncoding: { + format: 'jwk' + } + }), { + name: 'Error', + code: 'ERR_CRYPTO_JWK_UNSUPPORTED_CURVE', + message: 'Unsupported JWK EC curve: secp224r1.' + }); +} diff --git a/test/parallel/test-crypto-keygen-key-object-without-encoding.js b/test/parallel/test-crypto-keygen-key-object-without-encoding.js new file mode 100644 index 00000000000000..abcd282871b638 --- /dev/null +++ b/test/parallel/test-crypto-keygen-key-object-without-encoding.js @@ -0,0 +1,55 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); +const { + testEncryptDecrypt, + testSignVerify, +} = require('../common/crypto'); + +// Tests key objects are returned when key encodings are not specified. +{ + // If no publicKeyEncoding is specified, a key object should be returned. + generateKeyPair('rsa', { + modulusLength: 1024, + privateKeyEncoding: { + type: 'pkcs1', + format: 'pem' + } + }, common.mustSucceed((publicKey, privateKey) => { + assert.strictEqual(typeof publicKey, 'object'); + assert.strictEqual(publicKey.type, 'public'); + assert.strictEqual(publicKey.asymmetricKeyType, 'rsa'); + + // The private key should still be a string. + assert.strictEqual(typeof privateKey, 'string'); + + testEncryptDecrypt(publicKey, privateKey); + testSignVerify(publicKey, privateKey); + })); + + // If no privateKeyEncoding is specified, a key object should be returned. + generateKeyPair('rsa', { + modulusLength: 1024, + publicKeyEncoding: { + type: 'pkcs1', + format: 'pem' + } + }, common.mustSucceed((publicKey, privateKey) => { + // The public key should still be a string. + assert.strictEqual(typeof publicKey, 'string'); + + assert.strictEqual(typeof privateKey, 'object'); + assert.strictEqual(privateKey.type, 'private'); + assert.strictEqual(privateKey.asymmetricKeyType, 'rsa'); + + testEncryptDecrypt(publicKey, privateKey); + testSignVerify(publicKey, privateKey); + })); +} diff --git a/test/parallel/test-crypto-keygen-key-objects.js b/test/parallel/test-crypto-keygen-key-objects.js new file mode 100644 index 00000000000000..a0f1bdf2bcb5ed --- /dev/null +++ b/test/parallel/test-crypto-keygen-key-objects.js @@ -0,0 +1,33 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPairSync, +} = require('crypto'); + +// Test sync key generation with key objects. +{ + const { publicKey, privateKey } = generateKeyPairSync('rsa', { + modulusLength: 512 + }); + + assert.strictEqual(typeof publicKey, 'object'); + assert.strictEqual(publicKey.type, 'public'); + assert.strictEqual(publicKey.asymmetricKeyType, 'rsa'); + assert.deepStrictEqual(publicKey.asymmetricKeyDetails, { + modulusLength: 512, + publicExponent: 65537n + }); + + assert.strictEqual(typeof privateKey, 'object'); + assert.strictEqual(privateKey.type, 'private'); + assert.strictEqual(privateKey.asymmetricKeyType, 'rsa'); + assert.deepStrictEqual(privateKey.asymmetricKeyDetails, { + modulusLength: 512, + publicExponent: 65537n + }); +} diff --git a/test/parallel/test-crypto-keygen-missing-oid.js b/test/parallel/test-crypto-keygen-missing-oid.js new file mode 100644 index 00000000000000..f7fefe13848d4b --- /dev/null +++ b/test/parallel/test-crypto-keygen-missing-oid.js @@ -0,0 +1,43 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, + generateKeyPairSync, + getCurves, +} = require('crypto'); + +// This test creates EC key pairs on curves without associated OIDs. +// Specifying a key encoding should not crash. +{ + if (process.versions.openssl >= '1.1.1i') { + for (const namedCurve of ['Oakley-EC2N-3', 'Oakley-EC2N-4']) { + if (!getCurves().includes(namedCurve)) + continue; + + const expectedErrorCode = + common.hasOpenSSL3 ? 'ERR_OSSL_MISSING_OID' : 'ERR_OSSL_EC_MISSING_OID'; + const params = { + namedCurve, + publicKeyEncoding: { + format: 'der', + type: 'spki' + } + }; + + assert.throws(() => { + generateKeyPairSync('ec', params); + }, { + code: expectedErrorCode + }); + + generateKeyPair('ec', params, common.mustCall((err) => { + assert.strictEqual(err.code, expectedErrorCode); + })); + } + } +} diff --git a/test/parallel/test-crypto-keygen-no-rsassa-pss-params.js b/test/parallel/test-crypto-keygen-no-rsassa-pss-params.js new file mode 100644 index 00000000000000..97dafe1be3cbd0 --- /dev/null +++ b/test/parallel/test-crypto-keygen-no-rsassa-pss-params.js @@ -0,0 +1,32 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); + +// 'rsa-pss' should not add a RSASSA-PSS-params sequence by default. +// Regression test for: https://github.com/nodejs/node/issues/39936 +{ + generateKeyPair('rsa-pss', { + modulusLength: 512 + }, common.mustSucceed((publicKey, privateKey) => { + const expectedKeyDetails = { + modulusLength: 512, + publicExponent: 65537n + }; + assert.deepStrictEqual(publicKey.asymmetricKeyDetails, expectedKeyDetails); + assert.deepStrictEqual(privateKey.asymmetricKeyDetails, expectedKeyDetails); + + // To allow backporting the fix to versions that do not support + // asymmetricKeyDetails for RSA-PSS params, also verify that the exported + // AlgorithmIdentifier member of the SubjectPublicKeyInfo has the expected + // length of 11 bytes (as opposed to > 11 bytes if node added params). + const spki = publicKey.export({ format: 'der', type: 'spki' }); + assert.strictEqual(spki[3], 11, spki.toString('hex')); + })); +} diff --git a/test/parallel/test-crypto-keygen-non-standard-public-exponent.js b/test/parallel/test-crypto-keygen-non-standard-public-exponent.js new file mode 100644 index 00000000000000..f54a9e8a6d9b5c --- /dev/null +++ b/test/parallel/test-crypto-keygen-non-standard-public-exponent.js @@ -0,0 +1,35 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPairSync, +} = require('crypto'); + +// Test sync key generation with key objects with a non-standard +// publicExponent +{ + const { publicKey, privateKey } = generateKeyPairSync('rsa', { + publicExponent: 3, + modulusLength: 512 + }); + + assert.strictEqual(typeof publicKey, 'object'); + assert.strictEqual(publicKey.type, 'public'); + assert.strictEqual(publicKey.asymmetricKeyType, 'rsa'); + assert.deepStrictEqual(publicKey.asymmetricKeyDetails, { + modulusLength: 512, + publicExponent: 3n + }); + + assert.strictEqual(typeof privateKey, 'object'); + assert.strictEqual(privateKey.type, 'private'); + assert.strictEqual(privateKey.asymmetricKeyType, 'rsa'); + assert.deepStrictEqual(privateKey.asymmetricKeyDetails, { + modulusLength: 512, + publicExponent: 3n + }); +} diff --git a/test/parallel/test-crypto-keygen-promisify.js b/test/parallel/test-crypto-keygen-promisify.js new file mode 100644 index 00000000000000..cd6ca7d6e3e65c --- /dev/null +++ b/test/parallel/test-crypto-keygen-promisify.js @@ -0,0 +1,46 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); +const { + assertApproximateSize, + testEncryptDecrypt, + testSignVerify, + pkcs1PubExp, + pkcs1PrivExp, +} = require('../common/crypto'); +const { promisify } = require('util'); + +// Test the util.promisified API with async RSA key generation. +{ + promisify(generateKeyPair)('rsa', { + publicExponent: 0x10001, + modulusLength: 512, + publicKeyEncoding: { + type: 'pkcs1', + format: 'pem' + }, + privateKeyEncoding: { + type: 'pkcs1', + format: 'pem' + } + }).then(common.mustCall((keys) => { + const { publicKey, privateKey } = keys; + assert.strictEqual(typeof publicKey, 'string'); + assert.match(publicKey, pkcs1PubExp); + assertApproximateSize(publicKey, 180); + + assert.strictEqual(typeof privateKey, 'string'); + assert.match(privateKey, pkcs1PrivExp); + assertApproximateSize(privateKey, 512); + + testEncryptDecrypt(publicKey, privateKey); + testSignVerify(publicKey, privateKey); + })); +} diff --git a/test/parallel/test-crypto-keygen-rfc8017-9-1.js b/test/parallel/test-crypto-keygen-rfc8017-9-1.js new file mode 100644 index 00000000000000..7198be1c41343b --- /dev/null +++ b/test/parallel/test-crypto-keygen-rfc8017-9-1.js @@ -0,0 +1,32 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); + +// RFC 8017, 9.1.: "Assuming that the mask generation function is based on a +// hash function, it is RECOMMENDED that the hash function be the same as the +// one that is applied to the message." +{ + + generateKeyPair('rsa-pss', { + modulusLength: 512, + hashAlgorithm: 'sha256', + saltLength: 16 + }, common.mustSucceed((publicKey, privateKey) => { + const expectedKeyDetails = { + modulusLength: 512, + publicExponent: 65537n, + hashAlgorithm: 'sha256', + mgf1HashAlgorithm: 'sha256', + saltLength: 16 + }; + assert.deepStrictEqual(publicKey.asymmetricKeyDetails, expectedKeyDetails); + assert.deepStrictEqual(privateKey.asymmetricKeyDetails, expectedKeyDetails); + })); +} diff --git a/test/parallel/test-crypto-keygen-rfc8017-a-2-3.js b/test/parallel/test-crypto-keygen-rfc8017-a-2-3.js new file mode 100644 index 00000000000000..f87dcf749bf6d0 --- /dev/null +++ b/test/parallel/test-crypto-keygen-rfc8017-a-2-3.js @@ -0,0 +1,46 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); + +// RFC 8017, A.2.3.: "For a given hashAlgorithm, the default value of +// saltLength is the octet length of the hash value." +{ + generateKeyPair('rsa-pss', { + modulusLength: 512, + hashAlgorithm: 'sha512' + }, common.mustSucceed((publicKey, privateKey) => { + const expectedKeyDetails = { + modulusLength: 512, + publicExponent: 65537n, + hashAlgorithm: 'sha512', + mgf1HashAlgorithm: 'sha512', + saltLength: 64 + }; + assert.deepStrictEqual(publicKey.asymmetricKeyDetails, expectedKeyDetails); + assert.deepStrictEqual(privateKey.asymmetricKeyDetails, expectedKeyDetails); + })); + + // It is still possible to explicitly set saltLength to 0. + generateKeyPair('rsa-pss', { + modulusLength: 512, + hashAlgorithm: 'sha512', + saltLength: 0 + }, common.mustSucceed((publicKey, privateKey) => { + const expectedKeyDetails = { + modulusLength: 512, + publicExponent: 65537n, + hashAlgorithm: 'sha512', + mgf1HashAlgorithm: 'sha512', + saltLength: 0 + }; + assert.deepStrictEqual(publicKey.asymmetricKeyDetails, expectedKeyDetails); + assert.deepStrictEqual(privateKey.asymmetricKeyDetails, expectedKeyDetails); + })); +} diff --git a/test/parallel/test-crypto-keygen-rsa-pss.js b/test/parallel/test-crypto-keygen-rsa-pss.js new file mode 100644 index 00000000000000..41ebec97a5d2dd --- /dev/null +++ b/test/parallel/test-crypto-keygen-rsa-pss.js @@ -0,0 +1,64 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + constants, + generateKeyPair, +} = require('crypto'); +const { + testEncryptDecrypt, + testSignVerify, +} = require('../common/crypto'); + +// Test RSA-PSS. +{ + generateKeyPair('rsa-pss', { + modulusLength: 512, + saltLength: 16, + hashAlgorithm: 'sha256', + mgf1HashAlgorithm: 'sha256' + }, common.mustSucceed((publicKey, privateKey) => { + assert.strictEqual(publicKey.type, 'public'); + assert.strictEqual(publicKey.asymmetricKeyType, 'rsa-pss'); + assert.deepStrictEqual(publicKey.asymmetricKeyDetails, { + modulusLength: 512, + publicExponent: 65537n, + hashAlgorithm: 'sha256', + mgf1HashAlgorithm: 'sha256', + saltLength: 16 + }); + + assert.strictEqual(privateKey.type, 'private'); + assert.strictEqual(privateKey.asymmetricKeyType, 'rsa-pss'); + assert.deepStrictEqual(privateKey.asymmetricKeyDetails, { + modulusLength: 512, + publicExponent: 65537n, + hashAlgorithm: 'sha256', + mgf1HashAlgorithm: 'sha256', + saltLength: 16 + }); + + // Unlike RSA, RSA-PSS does not allow encryption. + assert.throws(() => { + testEncryptDecrypt(publicKey, privateKey); + }, /operation not supported for this keytype/); + + // RSA-PSS also does not permit signing with PKCS1 padding. + assert.throws(() => { + testSignVerify({ + key: publicKey, + padding: constants.RSA_PKCS1_PADDING + }, { + key: privateKey, + padding: constants.RSA_PKCS1_PADDING + }); + }, /illegal or unsupported padding mode/); + + // The padding should correctly default to RSA_PKCS1_PSS_PADDING now. + testSignVerify(publicKey, privateKey); + })); +} diff --git a/test/parallel/test-crypto-keygen-sync.js b/test/parallel/test-crypto-keygen-sync.js new file mode 100644 index 00000000000000..a100379e21f1b7 --- /dev/null +++ b/test/parallel/test-crypto-keygen-sync.js @@ -0,0 +1,47 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const { + generateKeyPairSync, +} = require('crypto'); +const { + assertApproximateSize, + testEncryptDecrypt, + testSignVerify, + pkcs1PubExp, + pkcs8Exp, +} = require('../common/crypto'); + +// To make the test faster, we will only test sync key generation once and +// with a relatively small key. +{ + const ret = generateKeyPairSync('rsa', { + publicExponent: 3, + modulusLength: 512, + publicKeyEncoding: { + type: 'pkcs1', + format: 'pem' + }, + privateKeyEncoding: { + type: 'pkcs8', + format: 'pem' + } + }); + + assert.strictEqual(Object.keys(ret).length, 2); + const { publicKey, privateKey } = ret; + + assert.strictEqual(typeof publicKey, 'string'); + assert.match(publicKey, pkcs1PubExp); + assertApproximateSize(publicKey, 162); + assert.strictEqual(typeof privateKey, 'string'); + assert.match(privateKey, pkcs8Exp); + assertApproximateSize(privateKey, 512); + + testEncryptDecrypt(publicKey, privateKey); + testSignVerify(publicKey, privateKey); +} diff --git a/test/parallel/test-crypto-keygen.js b/test/parallel/test-crypto-keygen.js index df8c5d93a90342..b09ca9e7c531ea 100644 --- a/test/parallel/test-crypto-keygen.js +++ b/test/parallel/test-crypto-keygen.js @@ -1,782 +1,19 @@ 'use strict'; +// This tests early errors for invalid encodings. + const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); const assert = require('assert'); + const { - constants, - createPrivateKey, - createSign, - createVerify, generateKeyPair, generateKeyPairSync, - getCurves, - publicEncrypt, - privateDecrypt, - sign, - verify } = require('crypto'); -const { inspect, promisify } = require('util'); - -// Asserts that the size of the given key (in chars or bytes) is within 10% of -// the expected size. -function assertApproximateSize(key, expectedSize) { - const u = typeof key === 'string' ? 'chars' : 'bytes'; - const min = Math.floor(0.9 * expectedSize); - const max = Math.ceil(1.1 * expectedSize); - assert(key.length >= min, - `Key (${key.length} ${u}) is shorter than expected (${min} ${u})`); - assert(key.length <= max, - `Key (${key.length} ${u}) is longer than expected (${max} ${u})`); -} - -// Tests that a key pair can be used for encryption / decryption. -function testEncryptDecrypt(publicKey, privateKey) { - const message = 'Hello Node.js world!'; - const plaintext = Buffer.from(message, 'utf8'); - for (const key of [publicKey, privateKey]) { - const ciphertext = publicEncrypt(key, plaintext); - const received = privateDecrypt(privateKey, ciphertext); - assert.strictEqual(received.toString('utf8'), message); - } -} - -// Tests that a key pair can be used for signing / verification. -function testSignVerify(publicKey, privateKey) { - const message = Buffer.from('Hello Node.js world!'); - - function oldSign(algo, data, key) { - return createSign(algo).update(data).sign(key); - } - - function oldVerify(algo, data, key, signature) { - return createVerify(algo).update(data).verify(key, signature); - } - - for (const signFn of [sign, oldSign]) { - const signature = signFn('SHA256', message, privateKey); - for (const verifyFn of [verify, oldVerify]) { - for (const key of [publicKey, privateKey]) { - const okay = verifyFn('SHA256', message, key, signature); - assert(okay); - } - } - } -} - -// Constructs a regular expression for a PEM-encoded key with the given label. -function getRegExpForPEM(label, cipher) { - const head = `\\-\\-\\-\\-\\-BEGIN ${label}\\-\\-\\-\\-\\-`; - const rfc1421Header = cipher == null ? '' : - `\nProc-Type: 4,ENCRYPTED\nDEK-Info: ${cipher},[^\n]+\n`; - const body = '([a-zA-Z0-9\\+/=]{64}\n)*[a-zA-Z0-9\\+/=]{1,64}'; - const end = `\\-\\-\\-\\-\\-END ${label}\\-\\-\\-\\-\\-`; - return new RegExp(`^${head}${rfc1421Header}\n${body}\n${end}\n$`); -} - -const pkcs1PubExp = getRegExpForPEM('RSA PUBLIC KEY'); -const pkcs1PrivExp = getRegExpForPEM('RSA PRIVATE KEY'); -const pkcs1EncExp = (cipher) => getRegExpForPEM('RSA PRIVATE KEY', cipher); -const spkiExp = getRegExpForPEM('PUBLIC KEY'); -const pkcs8Exp = getRegExpForPEM('PRIVATE KEY'); -const pkcs8EncExp = getRegExpForPEM('ENCRYPTED PRIVATE KEY'); -const sec1Exp = getRegExpForPEM('EC PRIVATE KEY'); -const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher); - -{ - // To make the test faster, we will only test sync key generation once and - // with a relatively small key. - const ret = generateKeyPairSync('rsa', { - publicExponent: 3, - modulusLength: 512, - publicKeyEncoding: { - type: 'pkcs1', - format: 'pem' - }, - privateKeyEncoding: { - type: 'pkcs8', - format: 'pem' - } - }); - - assert.strictEqual(Object.keys(ret).length, 2); - const { publicKey, privateKey } = ret; - - assert.strictEqual(typeof publicKey, 'string'); - assert.match(publicKey, pkcs1PubExp); - assertApproximateSize(publicKey, 162); - assert.strictEqual(typeof privateKey, 'string'); - assert.match(privateKey, pkcs8Exp); - assertApproximateSize(privateKey, 512); - - testEncryptDecrypt(publicKey, privateKey); - testSignVerify(publicKey, privateKey); -} - -{ - // Test sync key generation with key objects with a non-standard - // publicExponent - const { publicKey, privateKey } = generateKeyPairSync('rsa', { - publicExponent: 3, - modulusLength: 512 - }); - - assert.strictEqual(typeof publicKey, 'object'); - assert.strictEqual(publicKey.type, 'public'); - assert.strictEqual(publicKey.asymmetricKeyType, 'rsa'); - assert.deepStrictEqual(publicKey.asymmetricKeyDetails, { - modulusLength: 512, - publicExponent: 3n - }); - - assert.strictEqual(typeof privateKey, 'object'); - assert.strictEqual(privateKey.type, 'private'); - assert.strictEqual(privateKey.asymmetricKeyType, 'rsa'); - assert.deepStrictEqual(privateKey.asymmetricKeyDetails, { - modulusLength: 512, - publicExponent: 3n - }); -} - -{ - // Test sync key generation with key objects. - const { publicKey, privateKey } = generateKeyPairSync('rsa', { - modulusLength: 512 - }); - - assert.strictEqual(typeof publicKey, 'object'); - assert.strictEqual(publicKey.type, 'public'); - assert.strictEqual(publicKey.asymmetricKeyType, 'rsa'); - assert.deepStrictEqual(publicKey.asymmetricKeyDetails, { - modulusLength: 512, - publicExponent: 65537n - }); - - assert.strictEqual(typeof privateKey, 'object'); - assert.strictEqual(privateKey.type, 'private'); - assert.strictEqual(privateKey.asymmetricKeyType, 'rsa'); - assert.deepStrictEqual(privateKey.asymmetricKeyDetails, { - modulusLength: 512, - publicExponent: 65537n - }); -} - -{ - const publicKeyEncoding = { - type: 'pkcs1', - format: 'der' - }; - - // Test async RSA key generation. - generateKeyPair('rsa', { - publicExponent: 0x10001, - modulusLength: 512, - publicKeyEncoding, - privateKeyEncoding: { - type: 'pkcs1', - format: 'pem' - } - }, common.mustSucceed((publicKeyDER, privateKey) => { - assert(Buffer.isBuffer(publicKeyDER)); - assertApproximateSize(publicKeyDER, 74); - - assert.strictEqual(typeof privateKey, 'string'); - assert.match(privateKey, pkcs1PrivExp); - assertApproximateSize(privateKey, 512); - - const publicKey = { key: publicKeyDER, ...publicKeyEncoding }; - testEncryptDecrypt(publicKey, privateKey); - testSignVerify(publicKey, privateKey); - })); - - // Now do the same with an encrypted private key. - generateKeyPair('rsa', { - publicExponent: 0x10001, - modulusLength: 512, - publicKeyEncoding, - privateKeyEncoding: { - type: 'pkcs1', - format: 'pem', - cipher: 'aes-256-cbc', - passphrase: 'secret' - } - }, common.mustSucceed((publicKeyDER, privateKey) => { - assert(Buffer.isBuffer(publicKeyDER)); - assertApproximateSize(publicKeyDER, 74); - - assert.strictEqual(typeof privateKey, 'string'); - assert.match(privateKey, pkcs1EncExp('AES-256-CBC')); - - // Since the private key is encrypted, signing shouldn't work anymore. - const publicKey = { key: publicKeyDER, ...publicKeyEncoding }; - const expectedError = common.hasOpenSSL3 ? { - name: 'Error', - message: 'error:07880109:common libcrypto routines::interrupted or ' + - 'cancelled' - } : { - name: 'TypeError', - code: 'ERR_MISSING_PASSPHRASE', - message: 'Passphrase required for encrypted key' - }; - assert.throws(() => testSignVerify(publicKey, privateKey), expectedError); - - const key = { key: privateKey, passphrase: 'secret' }; - testEncryptDecrypt(publicKey, key); - testSignVerify(publicKey, key); - })); - - // Now do the same with an encrypted private key, but encoded as DER. - generateKeyPair('rsa', { - publicExponent: 0x10001, - modulusLength: 512, - publicKeyEncoding, - privateKeyEncoding: { - type: 'pkcs8', - format: 'der', - cipher: 'aes-256-cbc', - passphrase: 'secret' - } - }, common.mustSucceed((publicKeyDER, privateKeyDER) => { - assert(Buffer.isBuffer(publicKeyDER)); - assertApproximateSize(publicKeyDER, 74); - - assert(Buffer.isBuffer(privateKeyDER)); - - // Since the private key is encrypted, signing shouldn't work anymore. - const publicKey = { key: publicKeyDER, ...publicKeyEncoding }; - assert.throws(() => { - testSignVerify(publicKey, { - key: privateKeyDER, - format: 'der', - type: 'pkcs8' - }); - }, { - name: 'TypeError', - code: 'ERR_MISSING_PASSPHRASE', - message: 'Passphrase required for encrypted key' - }); - - // Signing should work with the correct password. - - const privateKey = { - key: privateKeyDER, - format: 'der', - type: 'pkcs8', - passphrase: 'secret' - }; - testEncryptDecrypt(publicKey, privateKey); - testSignVerify(publicKey, privateKey); - })); - - // Now do the same with an encrypted private key, but encoded as DER. - generateKeyPair('rsa', { - publicExponent: 0x10001, - modulusLength: 512, - publicKeyEncoding, - privateKeyEncoding: { - type: 'pkcs8', - format: 'der' - } - }, common.mustSucceed((publicKeyDER, privateKeyDER) => { - assert(Buffer.isBuffer(publicKeyDER)); - assertApproximateSize(publicKeyDER, 74); - - assert(Buffer.isBuffer(privateKeyDER)); +const { inspect } = require('util'); - const publicKey = { key: publicKeyDER, ...publicKeyEncoding }; - const privateKey = { - key: privateKeyDER, - format: 'der', - type: 'pkcs8', - passphrase: 'secret' - }; - testEncryptDecrypt(publicKey, privateKey); - testSignVerify(publicKey, privateKey); - })); -} - -{ - // Test RSA-PSS. - generateKeyPair('rsa-pss', { - modulusLength: 512, - saltLength: 16, - hashAlgorithm: 'sha256', - mgf1HashAlgorithm: 'sha256' - }, common.mustSucceed((publicKey, privateKey) => { - assert.strictEqual(publicKey.type, 'public'); - assert.strictEqual(publicKey.asymmetricKeyType, 'rsa-pss'); - assert.deepStrictEqual(publicKey.asymmetricKeyDetails, { - modulusLength: 512, - publicExponent: 65537n, - hashAlgorithm: 'sha256', - mgf1HashAlgorithm: 'sha256', - saltLength: 16 - }); - - assert.strictEqual(privateKey.type, 'private'); - assert.strictEqual(privateKey.asymmetricKeyType, 'rsa-pss'); - assert.deepStrictEqual(privateKey.asymmetricKeyDetails, { - modulusLength: 512, - publicExponent: 65537n, - hashAlgorithm: 'sha256', - mgf1HashAlgorithm: 'sha256', - saltLength: 16 - }); - - // Unlike RSA, RSA-PSS does not allow encryption. - assert.throws(() => { - testEncryptDecrypt(publicKey, privateKey); - }, /operation not supported for this keytype/); - - // RSA-PSS also does not permit signing with PKCS1 padding. - assert.throws(() => { - testSignVerify({ - key: publicKey, - padding: constants.RSA_PKCS1_PADDING - }, { - key: privateKey, - padding: constants.RSA_PKCS1_PADDING - }); - }, /illegal or unsupported padding mode/); - - // The padding should correctly default to RSA_PKCS1_PSS_PADDING now. - testSignVerify(publicKey, privateKey); - })); -} - -{ - // 'rsa-pss' should not add a RSASSA-PSS-params sequence by default. - // Regression test for: https://github.com/nodejs/node/issues/39936 - - generateKeyPair('rsa-pss', { - modulusLength: 512 - }, common.mustSucceed((publicKey, privateKey) => { - const expectedKeyDetails = { - modulusLength: 512, - publicExponent: 65537n - }; - assert.deepStrictEqual(publicKey.asymmetricKeyDetails, expectedKeyDetails); - assert.deepStrictEqual(privateKey.asymmetricKeyDetails, expectedKeyDetails); - - // To allow backporting the fix to versions that do not support - // asymmetricKeyDetails for RSA-PSS params, also verify that the exported - // AlgorithmIdentifier member of the SubjectPublicKeyInfo has the expected - // length of 11 bytes (as opposed to > 11 bytes if node added params). - const spki = publicKey.export({ format: 'der', type: 'spki' }); - assert.strictEqual(spki[3], 11, spki.toString('hex')); - })); -} - -{ - // RFC 8017, 9.1.: "Assuming that the mask generation function is based on a - // hash function, it is RECOMMENDED that the hash function be the same as the - // one that is applied to the message." - - generateKeyPair('rsa-pss', { - modulusLength: 512, - hashAlgorithm: 'sha256', - saltLength: 16 - }, common.mustSucceed((publicKey, privateKey) => { - const expectedKeyDetails = { - modulusLength: 512, - publicExponent: 65537n, - hashAlgorithm: 'sha256', - mgf1HashAlgorithm: 'sha256', - saltLength: 16 - }; - assert.deepStrictEqual(publicKey.asymmetricKeyDetails, expectedKeyDetails); - assert.deepStrictEqual(privateKey.asymmetricKeyDetails, expectedKeyDetails); - })); -} - -{ - // RFC 8017, A.2.3.: "For a given hashAlgorithm, the default value of - // saltLength is the octet length of the hash value." - - generateKeyPair('rsa-pss', { - modulusLength: 512, - hashAlgorithm: 'sha512' - }, common.mustSucceed((publicKey, privateKey) => { - const expectedKeyDetails = { - modulusLength: 512, - publicExponent: 65537n, - hashAlgorithm: 'sha512', - mgf1HashAlgorithm: 'sha512', - saltLength: 64 - }; - assert.deepStrictEqual(publicKey.asymmetricKeyDetails, expectedKeyDetails); - assert.deepStrictEqual(privateKey.asymmetricKeyDetails, expectedKeyDetails); - })); - - // It is still possible to explicitly set saltLength to 0. - generateKeyPair('rsa-pss', { - modulusLength: 512, - hashAlgorithm: 'sha512', - saltLength: 0 - }, common.mustSucceed((publicKey, privateKey) => { - const expectedKeyDetails = { - modulusLength: 512, - publicExponent: 65537n, - hashAlgorithm: 'sha512', - mgf1HashAlgorithm: 'sha512', - saltLength: 0 - }; - assert.deepStrictEqual(publicKey.asymmetricKeyDetails, expectedKeyDetails); - assert.deepStrictEqual(privateKey.asymmetricKeyDetails, expectedKeyDetails); - })); -} - -{ - const privateKeyEncoding = { - type: 'pkcs8', - format: 'der' - }; - - // Test async DSA key generation. - generateKeyPair('dsa', { - modulusLength: common.hasOpenSSL3 ? 2048 : 512, - divisorLength: 256, - publicKeyEncoding: { - type: 'spki', - format: 'pem' - }, - privateKeyEncoding: { - cipher: 'aes-128-cbc', - passphrase: 'secret', - ...privateKeyEncoding - } - }, common.mustSucceed((publicKey, privateKeyDER) => { - assert.strictEqual(typeof publicKey, 'string'); - assert.match(publicKey, spkiExp); - // The private key is DER-encoded. - assert(Buffer.isBuffer(privateKeyDER)); - - assertApproximateSize(publicKey, common.hasOpenSSL3 ? 1194 : 440); - assertApproximateSize(privateKeyDER, common.hasOpenSSL3 ? 721 : 336); - - // Since the private key is encrypted, signing shouldn't work anymore. - assert.throws(() => { - return testSignVerify(publicKey, { - key: privateKeyDER, - ...privateKeyEncoding - }); - }, { - name: 'TypeError', - code: 'ERR_MISSING_PASSPHRASE', - message: 'Passphrase required for encrypted key' - }); - - // Signing should work with the correct password. - testSignVerify(publicKey, { - key: privateKeyDER, - ...privateKeyEncoding, - passphrase: 'secret' - }); - })); -} -{ - // Test async DSA key object generation. - generateKeyPair('dsa', { - modulusLength: common.hasOpenSSL3 ? 2048 : 512, - divisorLength: 256 - }, common.mustSucceed((publicKey, privateKey) => { - assert.strictEqual(publicKey.type, 'public'); - assert.strictEqual(publicKey.asymmetricKeyType, 'dsa'); - assert.deepStrictEqual(publicKey.asymmetricKeyDetails, { - modulusLength: common.hasOpenSSL3 ? 2048 : 512, - divisorLength: 256 - }); - - assert.strictEqual(privateKey.type, 'private'); - assert.strictEqual(privateKey.asymmetricKeyType, 'dsa'); - assert.deepStrictEqual(privateKey.asymmetricKeyDetails, { - modulusLength: common.hasOpenSSL3 ? 2048 : 512, - divisorLength: 256 - }); - })); -} - -{ - // Test async elliptic curve key generation, e.g. for ECDSA, with a SEC1 - // private key. - generateKeyPair('ec', { - namedCurve: 'prime256v1', - paramEncoding: 'named', - publicKeyEncoding: { - type: 'spki', - format: 'pem' - }, - privateKeyEncoding: { - type: 'sec1', - format: 'pem' - } - }, common.mustSucceed((publicKey, privateKey) => { - assert.strictEqual(typeof publicKey, 'string'); - assert.match(publicKey, spkiExp); - assert.strictEqual(typeof privateKey, 'string'); - assert.match(privateKey, sec1Exp); - - testSignVerify(publicKey, privateKey); - })); - - // Test async elliptic curve key generation, e.g. for ECDSA, with a SEC1 - // private key with paramEncoding explicit. - generateKeyPair('ec', { - namedCurve: 'prime256v1', - paramEncoding: 'explicit', - publicKeyEncoding: { - type: 'spki', - format: 'pem' - }, - privateKeyEncoding: { - type: 'sec1', - format: 'pem' - } - }, common.mustSucceed((publicKey, privateKey) => { - assert.strictEqual(typeof publicKey, 'string'); - assert.match(publicKey, spkiExp); - assert.strictEqual(typeof privateKey, 'string'); - assert.match(privateKey, sec1Exp); - - testSignVerify(publicKey, privateKey); - })); - - // Do the same with an encrypted private key. - generateKeyPair('ec', { - namedCurve: 'prime256v1', - paramEncoding: 'named', - publicKeyEncoding: { - type: 'spki', - format: 'pem' - }, - privateKeyEncoding: { - type: 'sec1', - format: 'pem', - cipher: 'aes-128-cbc', - passphrase: 'secret' - } - }, common.mustSucceed((publicKey, privateKey) => { - assert.strictEqual(typeof publicKey, 'string'); - assert.match(publicKey, spkiExp); - assert.strictEqual(typeof privateKey, 'string'); - assert.match(privateKey, sec1EncExp('AES-128-CBC')); - - // Since the private key is encrypted, signing shouldn't work anymore. - assert.throws(() => testSignVerify(publicKey, privateKey), - common.hasOpenSSL3 ? { - message: 'error:07880109:common libcrypto ' + - 'routines::interrupted or cancelled' - } : { - name: 'TypeError', - code: 'ERR_MISSING_PASSPHRASE', - message: 'Passphrase required for encrypted key' - }); - - testSignVerify(publicKey, { key: privateKey, passphrase: 'secret' }); - })); - - // Do the same with an encrypted private key with paramEncoding explicit. - generateKeyPair('ec', { - namedCurve: 'prime256v1', - paramEncoding: 'explicit', - publicKeyEncoding: { - type: 'spki', - format: 'pem' - }, - privateKeyEncoding: { - type: 'sec1', - format: 'pem', - cipher: 'aes-128-cbc', - passphrase: 'secret' - } - }, common.mustSucceed((publicKey, privateKey) => { - assert.strictEqual(typeof publicKey, 'string'); - assert.match(publicKey, spkiExp); - assert.strictEqual(typeof privateKey, 'string'); - assert.match(privateKey, sec1EncExp('AES-128-CBC')); - - // Since the private key is encrypted, signing shouldn't work anymore. - assert.throws(() => testSignVerify(publicKey, privateKey), - common.hasOpenSSL3 ? { - message: 'error:07880109:common libcrypto ' + - 'routines::interrupted or cancelled' - } : { - name: 'TypeError', - code: 'ERR_MISSING_PASSPHRASE', - message: 'Passphrase required for encrypted key' - }); - - testSignVerify(publicKey, { key: privateKey, passphrase: 'secret' }); - })); -} - -{ - // Test async elliptic curve key generation, e.g. for ECDSA, with an encrypted - // private key. - generateKeyPair('ec', { - namedCurve: 'P-256', - paramEncoding: 'named', - publicKeyEncoding: { - type: 'spki', - format: 'pem' - }, - privateKeyEncoding: { - type: 'pkcs8', - format: 'pem', - cipher: 'aes-128-cbc', - passphrase: 'top secret' - } - }, common.mustSucceed((publicKey, privateKey) => { - assert.strictEqual(typeof publicKey, 'string'); - assert.match(publicKey, spkiExp); - assert.strictEqual(typeof privateKey, 'string'); - assert.match(privateKey, pkcs8EncExp); - - // Since the private key is encrypted, signing shouldn't work anymore. - assert.throws(() => testSignVerify(publicKey, privateKey), - common.hasOpenSSL3 ? { - message: 'error:07880109:common libcrypto ' + - 'routines::interrupted or cancelled' - } : { - name: 'TypeError', - code: 'ERR_MISSING_PASSPHRASE', - message: 'Passphrase required for encrypted key' - }); - - testSignVerify(publicKey, { - key: privateKey, - passphrase: 'top secret' - }); - })); - - // Test async elliptic curve key generation, e.g. for ECDSA, with an encrypted - // private key with paramEncoding explicit. - generateKeyPair('ec', { - namedCurve: 'P-256', - paramEncoding: 'explicit', - publicKeyEncoding: { - type: 'spki', - format: 'pem' - }, - privateKeyEncoding: { - type: 'pkcs8', - format: 'pem', - cipher: 'aes-128-cbc', - passphrase: 'top secret' - } - }, common.mustSucceed((publicKey, privateKey) => { - assert.strictEqual(typeof publicKey, 'string'); - assert.match(publicKey, spkiExp); - assert.strictEqual(typeof privateKey, 'string'); - assert.match(privateKey, pkcs8EncExp); - - // Since the private key is encrypted, signing shouldn't work anymore. - assert.throws(() => testSignVerify(publicKey, privateKey), - common.hasOpenSSL3 ? { - message: 'error:07880109:common libcrypto ' + - 'routines::interrupted or cancelled' - } : { - name: 'TypeError', - code: 'ERR_MISSING_PASSPHRASE', - message: 'Passphrase required for encrypted key' - }); - - testSignVerify(publicKey, { - key: privateKey, - passphrase: 'top secret' - }); - })); - - // Test async elliptic curve key generation with 'jwk' encoding - [ - ['ec', ['P-384', 'P-256', 'P-521', 'secp256k1']], - ['rsa'], - ['ed25519'], - ['ed448'], - ['x25519'], - ['x448'], - ].forEach((types) => { - const [type, options] = types; - switch (type) { - case 'ec': { - return options.forEach((curve) => { - generateKeyPair(type, { - namedCurve: curve, - publicKeyEncoding: { - format: 'jwk' - }, - privateKeyEncoding: { - format: 'jwk' - } - }, common.mustSucceed((publicKey, privateKey) => { - assert.strictEqual(typeof publicKey, 'object'); - assert.strictEqual(typeof privateKey, 'object'); - assert.strictEqual(publicKey.x, privateKey.x); - assert.strictEqual(publicKey.y, privateKey.y); - assert(!publicKey.d); - assert(privateKey.d); - assert.strictEqual(publicKey.kty, 'EC'); - assert.strictEqual(publicKey.kty, privateKey.kty); - assert.strictEqual(publicKey.crv, curve); - assert.strictEqual(publicKey.crv, privateKey.crv); - })); - }); - } - case 'rsa': { - return generateKeyPair(type, { - modulusLength: 4096, - publicKeyEncoding: { - format: 'jwk' - }, - privateKeyEncoding: { - format: 'jwk' - } - }, common.mustSucceed((publicKey, privateKey) => { - assert.strictEqual(typeof publicKey, 'object'); - assert.strictEqual(typeof privateKey, 'object'); - assert.strictEqual(publicKey.kty, 'RSA'); - assert.strictEqual(publicKey.kty, privateKey.kty); - assert.strictEqual(typeof publicKey.n, 'string'); - assert.strictEqual(publicKey.n, privateKey.n); - assert.strictEqual(typeof publicKey.e, 'string'); - assert.strictEqual(publicKey.e, privateKey.e); - assert.strictEqual(typeof privateKey.d, 'string'); - assert.strictEqual(typeof privateKey.p, 'string'); - assert.strictEqual(typeof privateKey.q, 'string'); - assert.strictEqual(typeof privateKey.dp, 'string'); - assert.strictEqual(typeof privateKey.dq, 'string'); - assert.strictEqual(typeof privateKey.qi, 'string'); - })); - } - case 'ed25519': - case 'ed448': - case 'x25519': - case 'x448': { - generateKeyPair(type, { - publicKeyEncoding: { - format: 'jwk' - }, - privateKeyEncoding: { - format: 'jwk' - } - }, common.mustSucceed((publicKey, privateKey) => { - assert.strictEqual(typeof publicKey, 'object'); - assert.strictEqual(typeof privateKey, 'object'); - assert.strictEqual(publicKey.x, privateKey.x); - assert(!publicKey.d); - assert(privateKey.d); - assert.strictEqual(publicKey.kty, 'OKP'); - assert.strictEqual(publicKey.kty, privateKey.kty); - const expectedCrv = `${type.charAt(0).toUpperCase()}${type.slice(1)}`; - assert.strictEqual(publicKey.crv, expectedCrv); - assert.strictEqual(publicKey.crv, privateKey.crv); - })); - } - } - }); -} // Test invalid parameter encoding. { @@ -799,60 +36,6 @@ const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher); message: "The property 'options.paramEncoding' is invalid. " + "Received 'otherEncoding'" }); - assert.throws(() => generateKeyPairSync('dsa', { - modulusLength: 4096, - publicKeyEncoding: { - format: 'jwk' - }, - privateKeyEncoding: { - format: 'jwk' - } - }), { - name: 'Error', - code: 'ERR_CRYPTO_JWK_UNSUPPORTED_KEY_TYPE', - message: 'Unsupported JWK Key Type.' - }); - assert.throws(() => generateKeyPairSync('ec', { - namedCurve: 'secp224r1', - publicKeyEncoding: { - format: 'jwk' - }, - privateKeyEncoding: { - format: 'jwk' - } - }), { - name: 'Error', - code: 'ERR_CRYPTO_JWK_UNSUPPORTED_CURVE', - message: 'Unsupported JWK EC curve: secp224r1.' - }); -} - -{ - // Test the util.promisified API with async RSA key generation. - promisify(generateKeyPair)('rsa', { - publicExponent: 0x10001, - modulusLength: 512, - publicKeyEncoding: { - type: 'pkcs1', - format: 'pem' - }, - privateKeyEncoding: { - type: 'pkcs1', - format: 'pem' - } - }).then(common.mustCall((keys) => { - const { publicKey, privateKey } = keys; - assert.strictEqual(typeof publicKey, 'string'); - assert.match(publicKey, pkcs1PubExp); - assertApproximateSize(publicKey, 180); - - assert.strictEqual(typeof privateKey, 'string'); - assert.match(privateKey, pkcs1PrivExp); - assertApproximateSize(privateKey, 512); - - testEncryptDecrypt(publicKey, privateKey); - testSignVerify(publicKey, privateKey); - })); } { @@ -892,46 +75,6 @@ const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher); }); } -{ - // If no publicKeyEncoding is specified, a key object should be returned. - generateKeyPair('rsa', { - modulusLength: 1024, - privateKeyEncoding: { - type: 'pkcs1', - format: 'pem' - } - }, common.mustSucceed((publicKey, privateKey) => { - assert.strictEqual(typeof publicKey, 'object'); - assert.strictEqual(publicKey.type, 'public'); - assert.strictEqual(publicKey.asymmetricKeyType, 'rsa'); - - // The private key should still be a string. - assert.strictEqual(typeof privateKey, 'string'); - - testEncryptDecrypt(publicKey, privateKey); - testSignVerify(publicKey, privateKey); - })); - - // If no privateKeyEncoding is specified, a key object should be returned. - generateKeyPair('rsa', { - modulusLength: 1024, - publicKeyEncoding: { - type: 'pkcs1', - format: 'pem' - } - }, common.mustSucceed((publicKey, privateKey) => { - // The public key should still be a string. - assert.strictEqual(typeof publicKey, 'string'); - - assert.strictEqual(typeof privateKey, 'object'); - assert.strictEqual(privateKey.type, 'private'); - assert.strictEqual(privateKey.asymmetricKeyType, 'rsa'); - - testEncryptDecrypt(publicKey, privateKey); - testSignVerify(publicKey, privateKey); - })); -} - { // Invalid publicKeyEncoding. for (const enc of [0, 'a', true]) { @@ -1348,35 +491,7 @@ const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher); })); } -// Test EdDSA key generation. { - if (!/^1\.1\.0/.test(process.versions.openssl)) { - ['ed25519', 'ed448', 'x25519', 'x448'].forEach((keyType) => { - generateKeyPair(keyType, common.mustSucceed((publicKey, privateKey) => { - assert.strictEqual(publicKey.type, 'public'); - assert.strictEqual(publicKey.asymmetricKeyType, keyType); - assert.deepStrictEqual(publicKey.asymmetricKeyDetails, {}); - - assert.strictEqual(privateKey.type, 'private'); - assert.strictEqual(privateKey.asymmetricKeyType, keyType); - assert.deepStrictEqual(privateKey.asymmetricKeyDetails, {}); - })); - }); - } -} - -// Test classic Diffie-Hellman key generation. -{ - generateKeyPair('dh', { - primeLength: 1024 - }, common.mustSucceed((publicKey, privateKey) => { - assert.strictEqual(publicKey.type, 'public'); - assert.strictEqual(publicKey.asymmetricKeyType, 'dh'); - - assert.strictEqual(privateKey.type, 'private'); - assert.strictEqual(privateKey.asymmetricKeyType, 'dh'); - })); - assert.throws(() => { generateKeyPair('dh', common.mustNotCall()); }, { @@ -1685,131 +800,6 @@ const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher); }); } -// Passing an empty passphrase string should not cause OpenSSL's default -// passphrase prompt in the terminal. -// See https://github.com/nodejs/node/issues/35898. - -for (const type of ['pkcs1', 'pkcs8']) { - generateKeyPair('rsa', { - modulusLength: 1024, - privateKeyEncoding: { - type, - format: 'pem', - cipher: 'aes-256-cbc', - passphrase: '' - } - }, common.mustSucceed((publicKey, privateKey) => { - assert.strictEqual(publicKey.type, 'public'); - - for (const passphrase of ['', Buffer.alloc(0)]) { - const privateKeyObject = createPrivateKey({ - passphrase, - key: privateKey - }); - assert.strictEqual(privateKeyObject.asymmetricKeyType, 'rsa'); - } - - // Encrypting with an empty passphrase is not the same as not encrypting - // the key, and not specifying a passphrase should fail when decoding it. - assert.throws(() => { - return testSignVerify(publicKey, privateKey); - }, common.hasOpenSSL3 ? { - name: 'Error', - code: 'ERR_OSSL_CRYPTO_INTERRUPTED_OR_CANCELLED', - message: 'error:07880109:common libcrypto routines::interrupted or cancelled' - } : { - name: 'TypeError', - code: 'ERR_MISSING_PASSPHRASE', - message: 'Passphrase required for encrypted key' - }); - })); -} - -// Passing an empty passphrase string should not throw ERR_OSSL_CRYPTO_MALLOC_FAILURE even on OpenSSL 3. -// Regression test for https://github.com/nodejs/node/issues/41428. -generateKeyPair('rsa', { - modulusLength: 4096, - publicKeyEncoding: { - type: 'spki', - format: 'pem' - }, - privateKeyEncoding: { - type: 'pkcs8', - format: 'pem', - cipher: 'aes-256-cbc', - passphrase: '' - } -}, common.mustSucceed((publicKey, privateKey) => { - assert.strictEqual(typeof publicKey, 'string'); - assert.strictEqual(typeof privateKey, 'string'); -})); - -{ - // This test creates EC key pairs on curves without associated OIDs. - // Specifying a key encoding should not crash. - - if (process.versions.openssl >= '1.1.1i') { - for (const namedCurve of ['Oakley-EC2N-3', 'Oakley-EC2N-4']) { - if (!getCurves().includes(namedCurve)) - continue; - - const expectedErrorCode = - common.hasOpenSSL3 ? 'ERR_OSSL_MISSING_OID' : 'ERR_OSSL_EC_MISSING_OID'; - const params = { - namedCurve, - publicKeyEncoding: { - format: 'der', - type: 'spki' - } - }; - - assert.throws(() => { - generateKeyPairSync('ec', params); - }, { - code: expectedErrorCode - }); - - generateKeyPair('ec', params, common.mustCall((err) => { - assert.strictEqual(err.code, expectedErrorCode); - })); - } - } -} - -{ - // This test makes sure deprecated and new options may be used - // simultaneously so long as they're identical values. - - generateKeyPair('rsa-pss', { - modulusLength: 512, - saltLength: 16, - hash: 'sha256', - hashAlgorithm: 'sha256', - mgf1Hash: 'sha256', - mgf1HashAlgorithm: 'sha256' - }, common.mustSucceed((publicKey, privateKey) => { - assert.strictEqual(publicKey.type, 'public'); - assert.strictEqual(publicKey.asymmetricKeyType, 'rsa-pss'); - assert.deepStrictEqual(publicKey.asymmetricKeyDetails, { - modulusLength: 512, - publicExponent: 65537n, - hashAlgorithm: 'sha256', - mgf1HashAlgorithm: 'sha256', - saltLength: 16 - }); - - assert.strictEqual(privateKey.type, 'private'); - assert.strictEqual(privateKey.asymmetricKeyType, 'rsa-pss'); - assert.deepStrictEqual(privateKey.asymmetricKeyDetails, { - modulusLength: 512, - publicExponent: 65537n, - hashAlgorithm: 'sha256', - mgf1HashAlgorithm: 'sha256', - saltLength: 16 - }); - })); -} - { // This test makes sure deprecated and new options must // be the same value. @@ -1828,31 +818,3 @@ generateKeyPair('rsa', { hashAlgorithm: 'sha1' }, common.mustNotCall()), { code: 'ERR_INVALID_ARG_VALUE' }); } - -{ - // https://github.com/nodejs/node/issues/46102#issuecomment-1372153541 - - generateKeyPair('rsa', { - modulusLength: 513, - }, common.mustSucceed((publicKey, privateKey) => { - assert.strictEqual(privateKey.asymmetricKeyDetails.modulusLength, 513); - assert.strictEqual(publicKey.asymmetricKeyDetails.modulusLength, 513); - })); - - generateKeyPair('rsa-pss', { - modulusLength: 513, - }, common.mustSucceed((publicKey, privateKey) => { - assert.strictEqual(privateKey.asymmetricKeyDetails.modulusLength, 513); - assert.strictEqual(publicKey.asymmetricKeyDetails.modulusLength, 513); - })); - - if (common.hasOpenSSL3) { - generateKeyPair('dsa', { - modulusLength: 2049, - divisorLength: 256, - }, common.mustSucceed((publicKey, privateKey) => { - assert.strictEqual(privateKey.asymmetricKeyDetails.modulusLength, 2049); - assert.strictEqual(publicKey.asymmetricKeyDetails.modulusLength, 2049); - })); - } -} diff --git a/test/parallel/test-cwd-enoent-preload.js b/test/parallel/test-cwd-enoent-preload.js index 2077d9c1478335..21b20d6d035672 100644 --- a/test/parallel/test-cwd-enoent-preload.js +++ b/test/parallel/test-cwd-enoent-preload.js @@ -1,7 +1,7 @@ 'use strict'; const common = require('../common'); // Fails with EINVAL on SmartOS, EBUSY on Windows, EBUSY on AIX. -if (common.isSunOS || common.isWindows || common.isAIX) +if (common.isSunOS || common.isWindows || common.isAIX || common.isIBMi) common.skip('cannot rmdir current working directory'); if (!common.isMainThread) common.skip('process.chdir is not available in Workers'); diff --git a/test/parallel/test-cwd-enoent-repl.js b/test/parallel/test-cwd-enoent-repl.js index 5ea8abc7e42b52..0a61cbfbced9b4 100644 --- a/test/parallel/test-cwd-enoent-repl.js +++ b/test/parallel/test-cwd-enoent-repl.js @@ -1,7 +1,7 @@ 'use strict'; const common = require('../common'); // Fails with EINVAL on SmartOS, EBUSY on Windows, EBUSY on AIX. -if (common.isSunOS || common.isWindows || common.isAIX) +if (common.isSunOS || common.isWindows || common.isAIX || common.isIBMi) common.skip('cannot rmdir current working directory'); if (!common.isMainThread) common.skip('process.chdir is not available in Workers'); diff --git a/test/parallel/test-cwd-enoent.js b/test/parallel/test-cwd-enoent.js index 8beb1e3fbe0a05..876888bc2be518 100644 --- a/test/parallel/test-cwd-enoent.js +++ b/test/parallel/test-cwd-enoent.js @@ -1,7 +1,7 @@ 'use strict'; const common = require('../common'); // Fails with EINVAL on SmartOS, EBUSY on Windows, EBUSY on AIX. -if (common.isSunOS || common.isWindows || common.isAIX) +if (common.isSunOS || common.isWindows || common.isAIX || common.isIBMi) common.skip('cannot rmdir current working directory'); if (!common.isMainThread) common.skip('process.chdir is not available in Workers'); diff --git a/test/parallel/test-diagnostics-channel-bind-store.js b/test/parallel/test-diagnostics-channel-bind-store.js new file mode 100644 index 00000000000000..81fb299c2f637c --- /dev/null +++ b/test/parallel/test-diagnostics-channel-bind-store.js @@ -0,0 +1,108 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const dc = require('diagnostics_channel'); +const { AsyncLocalStorage } = require('async_hooks'); + +let n = 0; +const thisArg = new Date(); +const inputs = [ + { foo: 'bar' }, + { baz: 'buz' }, +]; + +const channel = dc.channel('test'); + +// Bind a storage directly to published data +const store1 = new AsyncLocalStorage(); +channel.bindStore(store1); +let store1bound = true; + +// Bind a store with transformation of published data +const store2 = new AsyncLocalStorage(); +channel.bindStore(store2, common.mustCall((data) => { + assert.strictEqual(data, inputs[n]); + return { data }; +}, 4)); + +// Regular subscribers should see publishes from runStores calls +channel.subscribe(common.mustCall((data) => { + if (store1bound) { + assert.deepStrictEqual(data, store1.getStore()); + } + assert.deepStrictEqual({ data }, store2.getStore()); + assert.strictEqual(data, inputs[n]); +}, 4)); + +// Verify stores are empty before run +assert.strictEqual(store1.getStore(), undefined); +assert.strictEqual(store2.getStore(), undefined); + +channel.runStores(inputs[n], common.mustCall(function(a, b) { + // Verify this and argument forwarding + assert.strictEqual(this, thisArg); + assert.strictEqual(a, 1); + assert.strictEqual(b, 2); + + // Verify store 1 state matches input + assert.strictEqual(store1.getStore(), inputs[n]); + + // Verify store 2 state has expected transformation + assert.deepStrictEqual(store2.getStore(), { data: inputs[n] }); + + // Should support nested contexts + n++; + channel.runStores(inputs[n], common.mustCall(function() { + // Verify this and argument forwarding + assert.strictEqual(this, undefined); + + // Verify store 1 state matches input + assert.strictEqual(store1.getStore(), inputs[n]); + + // Verify store 2 state has expected transformation + assert.deepStrictEqual(store2.getStore(), { data: inputs[n] }); + })); + n--; + + // Verify store 1 state matches input + assert.strictEqual(store1.getStore(), inputs[n]); + + // Verify store 2 state has expected transformation + assert.deepStrictEqual(store2.getStore(), { data: inputs[n] }); +}), thisArg, 1, 2); + +// Verify stores are empty after run +assert.strictEqual(store1.getStore(), undefined); +assert.strictEqual(store2.getStore(), undefined); + +// Verify unbinding works +assert.ok(channel.unbindStore(store1)); +store1bound = false; + +// Verify unbinding a store that is not bound returns false +assert.ok(!channel.unbindStore(store1)); + +n++; +channel.runStores(inputs[n], common.mustCall(() => { + // Verify after unbinding store 1 will remain undefined + assert.strictEqual(store1.getStore(), undefined); + + // Verify still bound store 2 receives expected data + assert.deepStrictEqual(store2.getStore(), { data: inputs[n] }); +})); + +// Contain transformer errors and emit on next tick +const fail = new Error('fail'); +channel.bindStore(store1, () => { + throw fail; +}); + +let calledRunStores = false; +process.once('uncaughtException', common.mustCall((err) => { + assert.strictEqual(calledRunStores, true); + assert.strictEqual(err, fail); +})); + +channel.runStores(inputs[n], common.mustCall()); +calledRunStores = true; diff --git a/test/parallel/test-diagnostics-channel-pub-sub.js b/test/parallel/test-diagnostics-channel-pub-sub.js index 2317d90dbbc554..a7232ab58ce8a5 100644 --- a/test/parallel/test-diagnostics-channel-pub-sub.js +++ b/test/parallel/test-diagnostics-channel-pub-sub.js @@ -42,3 +42,10 @@ assert.ok(!dc.unsubscribe(name, subscriber)); assert.throws(() => { dc.subscribe(name, null); }, { code: 'ERR_INVALID_ARG_TYPE' }); + +// Reaching zero subscribers should not delete from the channels map as there +// will be no more weakref to incRef if another subscribe happens while the +// channel object itself exists. +channel.subscribe(subscriber); +channel.unsubscribe(subscriber); +channel.subscribe(subscriber); diff --git a/test/parallel/test-diagnostics-channel-tracing-channel-async-error.js b/test/parallel/test-diagnostics-channel-tracing-channel-async-error.js new file mode 100644 index 00000000000000..7335e15de9dfb5 --- /dev/null +++ b/test/parallel/test-diagnostics-channel-tracing-channel-async-error.js @@ -0,0 +1,46 @@ +'use strict'; + +const common = require('../common'); +const dc = require('diagnostics_channel'); +const assert = require('assert'); + +const channel = dc.tracingChannel('test'); + +const expectedError = new Error('test'); +const input = { foo: 'bar' }; +const thisArg = { baz: 'buz' }; + +function check(found) { + assert.deepStrictEqual(found, input); +} + +const handlers = { + start: common.mustCall(check, 2), + end: common.mustCall(check, 2), + asyncStart: common.mustCall(check, 2), + asyncEnd: common.mustCall(check, 2), + error: common.mustCall((found) => { + check(found); + assert.deepStrictEqual(found.error, expectedError); + }, 2) +}; + +channel.subscribe(handlers); + +channel.traceCallback(function(cb, err) { + assert.deepStrictEqual(this, thisArg); + setImmediate(cb, err); +}, 0, input, thisArg, common.mustCall((err, res) => { + assert.strictEqual(err, expectedError); + assert.strictEqual(res, undefined); +}), expectedError); + +channel.tracePromise(function(value) { + assert.deepStrictEqual(this, thisArg); + return Promise.reject(value); +}, input, thisArg, expectedError).then( + common.mustNotCall(), + common.mustCall((value) => { + assert.deepStrictEqual(value, expectedError); + }) +); diff --git a/test/parallel/test-diagnostics-channel-tracing-channel-async.js b/test/parallel/test-diagnostics-channel-tracing-channel-async.js new file mode 100644 index 00000000000000..03bdc85fb14e70 --- /dev/null +++ b/test/parallel/test-diagnostics-channel-tracing-channel-async.js @@ -0,0 +1,60 @@ +'use strict'; + +const common = require('../common'); +const dc = require('diagnostics_channel'); +const assert = require('assert'); + +const channel = dc.tracingChannel('test'); + +const expectedResult = { foo: 'bar' }; +const input = { foo: 'bar' }; +const thisArg = { baz: 'buz' }; + +function check(found) { + assert.deepStrictEqual(found, input); +} + +const handlers = { + start: common.mustCall(check, 2), + end: common.mustCall(check, 2), + asyncStart: common.mustCall((found) => { + check(found); + assert.strictEqual(found.error, undefined); + assert.deepStrictEqual(found.result, expectedResult); + }, 2), + asyncEnd: common.mustCall((found) => { + check(found); + assert.strictEqual(found.error, undefined); + assert.deepStrictEqual(found.result, expectedResult); + }, 2), + error: common.mustNotCall() +}; + +channel.subscribe(handlers); + +channel.traceCallback(function(cb, err, res) { + assert.deepStrictEqual(this, thisArg); + setImmediate(cb, err, res); +}, 0, input, thisArg, common.mustCall((err, res) => { + assert.strictEqual(err, null); + assert.deepStrictEqual(res, expectedResult); +}), null, expectedResult); + +channel.tracePromise(function(value) { + assert.deepStrictEqual(this, thisArg); + return Promise.resolve(value); +}, input, thisArg, expectedResult).then( + common.mustCall((value) => { + assert.deepStrictEqual(value, expectedResult); + }), + common.mustNotCall() +); + +let failed = false; +try { + channel.traceCallback(common.mustNotCall(), 0, input, thisArg, 1, 2, 3); +} catch (err) { + assert.ok(/"callback" argument must be of type function/.test(err.message)); + failed = true; +} +assert.strictEqual(failed, true); diff --git a/test/parallel/test-diagnostics-channel-tracing-channel-callback-run-stores.js b/test/parallel/test-diagnostics-channel-tracing-channel-callback-run-stores.js new file mode 100644 index 00000000000000..874433efd2cb4a --- /dev/null +++ b/test/parallel/test-diagnostics-channel-tracing-channel-callback-run-stores.js @@ -0,0 +1,29 @@ +'use strict'; + +const common = require('../common'); +const { AsyncLocalStorage } = require('async_hooks'); +const dc = require('diagnostics_channel'); +const assert = require('assert'); + +const channel = dc.tracingChannel('test'); +const store = new AsyncLocalStorage(); + +const firstContext = { foo: 'bar' }; +const secondContext = { baz: 'buz' }; + +channel.start.bindStore(store, common.mustCall(() => { + return firstContext; +})); + +channel.asyncStart.bindStore(store, common.mustCall(() => { + return secondContext; +})); + +assert.strictEqual(store.getStore(), undefined); +channel.traceCallback(common.mustCall((cb) => { + assert.deepStrictEqual(store.getStore(), firstContext); + setImmediate(cb); +}), 0, {}, null, common.mustCall(() => { + assert.deepStrictEqual(store.getStore(), secondContext); +})); +assert.strictEqual(store.getStore(), undefined); diff --git a/test/parallel/test-diagnostics-channel-tracing-channel-promise-run-stores.js b/test/parallel/test-diagnostics-channel-tracing-channel-promise-run-stores.js new file mode 100644 index 00000000000000..5292a6fe096bae --- /dev/null +++ b/test/parallel/test-diagnostics-channel-tracing-channel-promise-run-stores.js @@ -0,0 +1,31 @@ +'use strict'; + +const common = require('../common'); +const { setTimeout } = require('node:timers/promises'); +const { AsyncLocalStorage } = require('async_hooks'); +const dc = require('diagnostics_channel'); +const assert = require('assert'); + +const channel = dc.tracingChannel('test'); +const store = new AsyncLocalStorage(); + +const firstContext = { foo: 'bar' }; +const secondContext = { baz: 'buz' }; + +channel.start.bindStore(store, common.mustCall(() => { + return firstContext; +})); + +channel.asyncStart.bindStore(store, common.mustNotCall(() => { + return secondContext; +})); + +assert.strictEqual(store.getStore(), undefined); +channel.tracePromise(common.mustCall(async () => { + assert.deepStrictEqual(store.getStore(), firstContext); + await setTimeout(1); + // Should _not_ switch to second context as promises don't have an "after" + // point at which to do a runStores. + assert.deepStrictEqual(store.getStore(), firstContext); +})); +assert.strictEqual(store.getStore(), undefined); diff --git a/test/parallel/test-diagnostics-channel-tracing-channel-run-stores.js b/test/parallel/test-diagnostics-channel-tracing-channel-run-stores.js new file mode 100644 index 00000000000000..3ffe5e6720c0e4 --- /dev/null +++ b/test/parallel/test-diagnostics-channel-tracing-channel-run-stores.js @@ -0,0 +1,21 @@ +'use strict'; + +const common = require('../common'); +const { AsyncLocalStorage } = require('async_hooks'); +const dc = require('diagnostics_channel'); +const assert = require('assert'); + +const channel = dc.tracingChannel('test'); +const store = new AsyncLocalStorage(); + +const context = { foo: 'bar' }; + +channel.start.bindStore(store, common.mustCall(() => { + return context; +})); + +assert.strictEqual(store.getStore(), undefined); +channel.traceSync(common.mustCall(() => { + assert.deepStrictEqual(store.getStore(), context); +})); +assert.strictEqual(store.getStore(), undefined); diff --git a/test/parallel/test-diagnostics-channel-tracing-channel-sync-error.js b/test/parallel/test-diagnostics-channel-tracing-channel-sync-error.js new file mode 100644 index 00000000000000..0965bf3fb495f0 --- /dev/null +++ b/test/parallel/test-diagnostics-channel-tracing-channel-sync-error.js @@ -0,0 +1,39 @@ +'use strict'; + +const common = require('../common'); +const dc = require('diagnostics_channel'); +const assert = require('assert'); + +const channel = dc.tracingChannel('test'); + +const expectedError = new Error('test'); +const input = { foo: 'bar' }; +const thisArg = { baz: 'buz' }; + +function check(found) { + assert.deepStrictEqual(found, input); +} + +const handlers = { + start: common.mustCall(check), + end: common.mustCall(check), + asyncStart: common.mustNotCall(), + asyncEnd: common.mustNotCall(), + error: common.mustCall((found) => { + check(found); + assert.deepStrictEqual(found.error, expectedError); + }) +}; + +channel.subscribe(handlers); +try { + channel.traceSync(function(err) { + assert.deepStrictEqual(this, thisArg); + assert.strictEqual(err, expectedError); + throw err; + }, input, thisArg, expectedError); + + throw new Error('It should not reach this error'); +} catch (error) { + assert.deepStrictEqual(error, expectedError); +} diff --git a/test/parallel/test-diagnostics-channel-tracing-channel-sync.js b/test/parallel/test-diagnostics-channel-tracing-channel-sync.js new file mode 100644 index 00000000000000..b28b47256b755d --- /dev/null +++ b/test/parallel/test-diagnostics-channel-tracing-channel-sync.js @@ -0,0 +1,46 @@ +'use strict'; + +const common = require('../common'); +const dc = require('diagnostics_channel'); +const assert = require('assert'); + +const channel = dc.tracingChannel('test'); + +const expectedResult = { foo: 'bar' }; +const input = { foo: 'bar' }; +const thisArg = { baz: 'buz' }; +const arg = { baz: 'buz' }; + +function check(found) { + assert.strictEqual(found, input); +} + +const handlers = { + start: common.mustCall(check), + end: common.mustCall((found) => { + check(found); + assert.strictEqual(found.result, expectedResult); + }), + asyncStart: common.mustNotCall(), + asyncEnd: common.mustNotCall(), + error: common.mustNotCall() +}; + +assert.strictEqual(channel.start.hasSubscribers, false); +channel.subscribe(handlers); +assert.strictEqual(channel.start.hasSubscribers, true); +const result1 = channel.traceSync(function(arg1) { + assert.strictEqual(arg1, arg); + assert.strictEqual(this, thisArg); + return expectedResult; +}, input, thisArg, arg); +assert.strictEqual(result1, expectedResult); + +channel.unsubscribe(handlers); +assert.strictEqual(channel.start.hasSubscribers, false); +const result2 = channel.traceSync(function(arg1) { + assert.strictEqual(arg1, arg); + assert.strictEqual(this, thisArg); + return expectedResult; +}, input, thisArg, arg); +assert.strictEqual(result2, expectedResult); diff --git a/test/parallel/test-eventtarget-memoryleakwarning.js b/test/parallel/test-eventtarget-memoryleakwarning.js index bb4002e30c6e6d..36fe068fb806d6 100644 --- a/test/parallel/test-eventtarget-memoryleakwarning.js +++ b/test/parallel/test-eventtarget-memoryleakwarning.js @@ -1,4 +1,4 @@ -// Flags: --no-warnings +// Flags: --expose-internals --no-warnings --expose-gc 'use strict'; const common = require('../common'); const { @@ -6,6 +6,8 @@ const { EventEmitter, } = require('events'); const assert = require('assert'); +const { kWeakHandler } = require('internal/event_target'); +const { setTimeout } = require('timers/promises'); common.expectWarning({ MaxListenersExceededWarning: [ @@ -73,3 +75,20 @@ common.expectWarning({ setMaxListeners(2, ee); assert.strictEqual(ee.getMaxListeners(), 2); } + +{ + (async () => { + // Test that EventTarget listener don't emit MaxListenersExceededWarning for weak listeners that GCed + const et = new EventTarget(); + setMaxListeners(2, et); + + for (let i = 0; i <= 3; i++) { + et.addEventListener('foo', () => {}, { + [kWeakHandler]: {}, + }); + + await setTimeout(0); + global.gc(); + } + })().then(common.mustCall(), common.mustNotCall()); +} diff --git a/test/parallel/test-eventtarget.js b/test/parallel/test-eventtarget.js index 31446e216444ff..0d8c1b748d01cc 100644 --- a/test/parallel/test-eventtarget.js +++ b/test/parallel/test-eventtarget.js @@ -16,8 +16,8 @@ const { const { once } = require('events'); -const { promisify, inspect } = require('util'); -const delay = promisify(setTimeout); +const { inspect } = require('util'); +const { setTimeout: delay } = require('timers/promises'); // The globals are defined. ok(Event); diff --git a/test/parallel/test-fs-mkdtemp.js b/test/parallel/test-fs-mkdtemp.js index 950a524368c00b..9c5b952cfc9e79 100644 --- a/test/parallel/test-fs-mkdtemp.js +++ b/test/parallel/test-fs-mkdtemp.js @@ -8,29 +8,100 @@ const path = require('path'); const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); -const tmpFolder = fs.mkdtempSync(path.join(tmpdir.path, 'foo.')); - -assert.strictEqual(path.basename(tmpFolder).length, 'foo.XXXXXX'.length); -assert(fs.existsSync(tmpFolder)); - -const utf8 = fs.mkdtempSync(path.join(tmpdir.path, '\u0222abc.')); -assert.strictEqual(Buffer.byteLength(path.basename(utf8)), - Buffer.byteLength('\u0222abc.XXXXXX')); -assert(fs.existsSync(utf8)); - function handler(err, folder) { assert.ifError(err); assert(fs.existsSync(folder)); assert.strictEqual(this, undefined); } -fs.mkdtemp(path.join(tmpdir.path, 'bar.'), common.mustCall(handler)); +// Test with plain string +{ + const tmpFolder = fs.mkdtempSync(path.join(tmpdir.path, 'foo.')); + + assert.strictEqual(path.basename(tmpFolder).length, 'foo.XXXXXX'.length); + assert(fs.existsSync(tmpFolder)); -// Same test as above, but making sure that passing an options object doesn't -// affect the way the callback function is handled. -fs.mkdtemp(path.join(tmpdir.path, 'bar.'), {}, common.mustCall(handler)); + const utf8 = fs.mkdtempSync(path.join(tmpdir.path, '\u0222abc.')); + assert.strictEqual(Buffer.byteLength(path.basename(utf8)), + Buffer.byteLength('\u0222abc.XXXXXX')); + assert(fs.existsSync(utf8)); + + fs.mkdtemp(path.join(tmpdir.path, 'bar.'), common.mustCall(handler)); + + // Same test as above, but making sure that passing an options object doesn't + // affect the way the callback function is handled. + fs.mkdtemp(path.join(tmpdir.path, 'bar.'), {}, common.mustCall(handler)); + + const warningMsg = 'mkdtemp() templates ending with X are not portable. ' + + 'For details see: https://nodejs.org/api/fs.html'; + common.expectWarning('Warning', warningMsg); + fs.mkdtemp(path.join(tmpdir.path, 'bar.X'), common.mustCall(handler)); +} + +// Test with URL object +{ + const tmpFolder = fs.mkdtempSync(tmpdir.fileURL('foo.')); + + assert.strictEqual(path.basename(tmpFolder).length, 'foo.XXXXXX'.length); + assert(fs.existsSync(tmpFolder)); + + const utf8 = fs.mkdtempSync(tmpdir.fileURL('\u0222abc.')); + assert.strictEqual(Buffer.byteLength(path.basename(utf8)), + Buffer.byteLength('\u0222abc.XXXXXX')); + assert(fs.existsSync(utf8)); + + fs.mkdtemp(tmpdir.fileURL('bar.'), common.mustCall(handler)); + + // Same test as above, but making sure that passing an options object doesn't + // affect the way the callback function is handled. + fs.mkdtemp(tmpdir.fileURL('bar.'), {}, common.mustCall(handler)); + + // Warning fires only once + fs.mkdtemp(tmpdir.fileURL('bar.X'), common.mustCall(handler)); +} -const warningMsg = 'mkdtemp() templates ending with X are not portable. ' + - 'For details see: https://nodejs.org/api/fs.html'; -common.expectWarning('Warning', warningMsg); -fs.mkdtemp(path.join(tmpdir.path, 'bar.X'), common.mustCall(handler)); +// Test with Buffer +{ + const tmpFolder = fs.mkdtempSync(Buffer.from(path.join(tmpdir.path, 'foo.'))); + + assert.strictEqual(path.basename(tmpFolder).length, 'foo.XXXXXX'.length); + assert(fs.existsSync(tmpFolder)); + + const utf8 = fs.mkdtempSync(Buffer.from(path.join(tmpdir.path, '\u0222abc.'))); + assert.strictEqual(Buffer.byteLength(path.basename(utf8)), + Buffer.byteLength('\u0222abc.XXXXXX')); + assert(fs.existsSync(utf8)); + + fs.mkdtemp(Buffer.from(path.join(tmpdir.path, 'bar.')), common.mustCall(handler)); + + // Same test as above, but making sure that passing an options object doesn't + // affect the way the callback function is handled. + fs.mkdtemp(Buffer.from(path.join(tmpdir.path, 'bar.')), {}, common.mustCall(handler)); + + // Warning fires only once + fs.mkdtemp(Buffer.from(path.join(tmpdir.path, 'bar.X')), common.mustCall(handler)); +} + +// Test with Uint8Array +{ + const encoder = new TextEncoder(); + + const tmpFolder = fs.mkdtempSync(encoder.encode(path.join(tmpdir.path, 'foo.'))); + + assert.strictEqual(path.basename(tmpFolder).length, 'foo.XXXXXX'.length); + assert(fs.existsSync(tmpFolder)); + + const utf8 = fs.mkdtempSync(encoder.encode(path.join(tmpdir.path, '\u0222abc.'))); + assert.strictEqual(Buffer.byteLength(path.basename(utf8)), + Buffer.byteLength('\u0222abc.XXXXXX')); + assert(fs.existsSync(utf8)); + + fs.mkdtemp(encoder.encode(path.join(tmpdir.path, 'bar.')), common.mustCall(handler)); + + // Same test as above, but making sure that passing an options object doesn't + // affect the way the callback function is handled. + fs.mkdtemp(encoder.encode(path.join(tmpdir.path, 'bar.')), {}, common.mustCall(handler)); + + // Warning fires only once + fs.mkdtemp(encoder.encode(path.join(tmpdir.path, 'bar.X')), common.mustCall(handler)); +} diff --git a/test/parallel/test-fs-null-bytes.js b/test/parallel/test-fs-null-bytes.js index d4548c02c07009..2851ac657ded33 100644 --- a/test/parallel/test-fs-null-bytes.js +++ b/test/parallel/test-fs-null-bytes.js @@ -66,6 +66,7 @@ check(fs.mkdir, fs.mkdirSync, 'foo\u0000bar', '0755'); check(fs.open, fs.openSync, 'foo\u0000bar', 'r'); check(fs.readFile, fs.readFileSync, 'foo\u0000bar'); check(fs.readdir, fs.readdirSync, 'foo\u0000bar'); +check(fs.readdir, fs.readdirSync, 'foo\u0000bar', { recursive: true }); check(fs.readlink, fs.readlinkSync, 'foo\u0000bar'); check(fs.realpath, fs.realpathSync, 'foo\u0000bar'); check(fs.rename, fs.renameSync, 'foo\u0000bar', 'foobar'); @@ -100,6 +101,7 @@ check(fs.mkdir, fs.mkdirSync, fileUrl, '0755'); check(fs.open, fs.openSync, fileUrl, 'r'); check(fs.readFile, fs.readFileSync, fileUrl); check(fs.readdir, fs.readdirSync, fileUrl); +check(fs.readdir, fs.readdirSync, fileUrl, { recursive: true }); check(fs.readlink, fs.readlinkSync, fileUrl); check(fs.realpath, fs.realpathSync, fileUrl); check(fs.rename, fs.renameSync, fileUrl, 'foobar'); @@ -131,6 +133,7 @@ check(fs.mkdir, fs.mkdirSync, fileUrl2, '0755'); check(fs.open, fs.openSync, fileUrl2, 'r'); check(fs.readFile, fs.readFileSync, fileUrl2); check(fs.readdir, fs.readdirSync, fileUrl2); +check(fs.readdir, fs.readdirSync, fileUrl2, { recursive: true }); check(fs.readlink, fs.readlinkSync, fileUrl2); check(fs.realpath, fs.realpathSync, fileUrl2); check(fs.rename, fs.renameSync, fileUrl2, 'foobar'); diff --git a/test/parallel/test-fs-readfile-pipe-large.js b/test/parallel/test-fs-readfile-pipe-large.js index 14a0793620b7b9..3e8ca1ecab6ea2 100644 --- a/test/parallel/test-fs-readfile-pipe-large.js +++ b/test/parallel/test-fs-readfile-pipe-large.js @@ -3,7 +3,7 @@ const common = require('../common'); // Simulate `cat readfile.js | node readfile.js` -if (common.isWindows || common.isAIX) +if (common.isWindows || common.isAIX || common.isIBMi) common.skip(`No /dev/stdin on ${process.platform}.`); const assert = require('assert'); diff --git a/test/parallel/test-fs-readfile-pipe.js b/test/parallel/test-fs-readfile-pipe.js index 0cffbd0f5aa162..79d5699fef64a4 100644 --- a/test/parallel/test-fs-readfile-pipe.js +++ b/test/parallel/test-fs-readfile-pipe.js @@ -24,7 +24,7 @@ const common = require('../common'); // Simulate `cat readfile.js | node readfile.js` -if (common.isWindows || common.isAIX) +if (common.isWindows || common.isAIX || common.isIBMi) common.skip(`No /dev/stdin on ${process.platform}.`); const assert = require('assert'); diff --git a/test/parallel/test-fs-readfilesync-pipe-large.js b/test/parallel/test-fs-readfilesync-pipe-large.js index 7c2a5e7fd01ae3..722689aeac7668 100644 --- a/test/parallel/test-fs-readfilesync-pipe-large.js +++ b/test/parallel/test-fs-readfilesync-pipe-large.js @@ -3,7 +3,7 @@ const common = require('../common'); // Simulate `cat readfile.js | node readfile.js` -if (common.isWindows || common.isAIX) +if (common.isWindows || common.isAIX || common.isIBMi) common.skip(`No /dev/stdin on ${process.platform}.`); const assert = require('assert'); diff --git a/test/parallel/test-fs-realpath-pipe.js b/test/parallel/test-fs-realpath-pipe.js index 29fe1d3b7d28e1..f637642ca21d67 100644 --- a/test/parallel/test-fs-realpath-pipe.js +++ b/test/parallel/test-fs-realpath-pipe.js @@ -2,7 +2,7 @@ const common = require('../common'); -if (common.isWindows || common.isAIX) +if (common.isWindows || common.isAIX || common.isIBMi) common.skip(`No /dev/stdin on ${process.platform}.`); const assert = require('assert'); diff --git a/test/parallel/test-fs-rm.js b/test/parallel/test-fs-rm.js index e6bc47038b8d92..93f59544a87e99 100644 --- a/test/parallel/test-fs-rm.js +++ b/test/parallel/test-fs-rm.js @@ -270,7 +270,7 @@ if (isGitPresent) { } // Should accept URL - const fileURL = pathToFileURL(path.join(tmpdir.path, 'rm-file.txt')); + const fileURL = tmpdir.fileURL('rm-file.txt'); fs.writeFileSync(fileURL, ''); try { @@ -376,7 +376,7 @@ if (isGitPresent) { } // Should accept URL - const fileURL = pathToFileURL(path.join(tmpdir.path, 'rm-promises-file.txt')); + const fileURL = tmpdir.fileURL('rm-promises-file.txt'); fs.writeFileSync(fileURL, ''); try { diff --git a/test/parallel/test-fs-utimes.js b/test/parallel/test-fs-utimes.js index 8f8286f8a3343f..e6ae75d4e33a5f 100644 --- a/test/parallel/test-fs-utimes.js +++ b/test/parallel/test-fs-utimes.js @@ -39,7 +39,7 @@ function stat_resource(resource, statSync = fs.statSync) { const stats = fs.fstatSync(resource); // Ensure mtime has been written to disk // except for directories on AIX where it cannot be synced - if (common.isAIX && stats.isDirectory()) + if ((common.isAIX || common.isIBMi) && stats.isDirectory()) return stats; fs.fsyncSync(resource); return fs.fstatSync(resource); diff --git a/test/parallel/test-fs-whatwg-url.js b/test/parallel/test-fs-whatwg-url.js index 829cfa92fafebd..5e9ea98a5820ed 100644 --- a/test/parallel/test-fs-whatwg-url.js +++ b/test/parallel/test-fs-whatwg-url.js @@ -3,20 +3,10 @@ const common = require('../common'); const fixtures = require('../common/fixtures'); const assert = require('assert'); -const path = require('path'); const fs = require('fs'); const os = require('os'); -function pathToFileURL(p) { - if (!path.isAbsolute(p)) - throw new Error('Path must be absolute'); - if (common.isWindows && p.startsWith('\\\\')) - p = p.slice(2); - return new URL(`file://${p}`); -} - -const p = path.resolve(fixtures.fixturesDir, 'a.js'); -const url = pathToFileURL(p); +const url = fixtures.fileURL('a.js'); assert(url instanceof URL); diff --git a/test/parallel/test-http-perf_hooks.js b/test/parallel/test-http-perf_hooks.js index de6ed0295a1152..2ed1a736fa8841 100644 --- a/test/parallel/test-http-perf_hooks.js +++ b/test/parallel/test-http-perf_hooks.js @@ -57,7 +57,7 @@ server.listen(0, common.mustCall(async () => { process.on('exit', () => { let numberOfHttpClients = 0; let numberOfHttpRequests = 0; - entries.forEach((entry) => { + for (const entry of entries) { assert.strictEqual(entry.entryType, 'http'); assert.strictEqual(typeof entry.startTime, 'number'); assert.strictEqual(typeof entry.duration, 'number'); @@ -72,7 +72,7 @@ process.on('exit', () => { assert.strictEqual(typeof entry.detail.res.statusCode, 'number'); assert.strictEqual(typeof entry.detail.res.statusMessage, 'string'); assert.strictEqual(typeof entry.detail.res.headers, 'object'); - }); + } assert.strictEqual(numberOfHttpClients, 2); assert.strictEqual(numberOfHttpRequests, 2); }); diff --git a/test/parallel/test-http-server-close-destroy-timeout.js b/test/parallel/test-http-server-close-destroy-timeout.js new file mode 100644 index 00000000000000..b1138ee36d5a90 --- /dev/null +++ b/test/parallel/test-http-server-close-destroy-timeout.js @@ -0,0 +1,13 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const { createServer } = require('http'); +const { kConnectionsCheckingInterval } = require('_http_server'); + +const server = createServer(function(req, res) {}); +server.listen(0, common.mustCall(function() { + assert.strictEqual(server[kConnectionsCheckingInterval]._destroyed, false); + server.close(common.mustCall(() => { + assert(server[kConnectionsCheckingInterval]._destroyed); + })); +})); diff --git a/test/parallel/test-http-server-close-idle.js b/test/parallel/test-http-server-close-idle.js index 361ccf990fabcc..36e9752d36b528 100644 --- a/test/parallel/test-http-server-close-idle.js +++ b/test/parallel/test-http-server-close-idle.js @@ -42,7 +42,6 @@ server.listen(0, function() { assert(response.startsWith('HTTP/1.1 200 OK\r\nConnection: keep-alive')); assert.strictEqual(connections, 2); - server.closeIdleConnections(); server.close(common.mustCall()); // Check that only the idle connection got closed diff --git a/test/parallel/test-http-server-connections-checking-leak.js b/test/parallel/test-http-server-connections-checking-leak.js new file mode 100644 index 00000000000000..e28cf117c65f87 --- /dev/null +++ b/test/parallel/test-http-server-connections-checking-leak.js @@ -0,0 +1,24 @@ +'use strict'; + +// Flags: --expose-gc + +// Check that creating a server without listening does not leak resources. + +require('../common'); +const onGC = require('../common/ongc'); +const Countdown = require('../common/countdown'); + +const http = require('http'); +const max = 100; + +// Note that Countdown internally calls common.mustCall, that's why it's not done here. +const countdown = new Countdown(max, () => {}); + +for (let i = 0; i < max; i++) { + const server = http.createServer((req, res) => {}); + onGC(server, { ongc: countdown.dec.bind(countdown) }); +} + +setImmediate(() => { + global.gc(); +}); diff --git a/test/parallel/test-http2-client-connection-tunnelling.js b/test/parallel/test-http2-client-connection-tunnelling.js new file mode 100644 index 00000000000000..6e04121ca71ea8 --- /dev/null +++ b/test/parallel/test-http2-client-connection-tunnelling.js @@ -0,0 +1,71 @@ +'use strict'; + +const common = require('../common'); +const fixtures = require('../common/fixtures'); +if (!common.hasCrypto) + common.skip('missing crypto'); +const assert = require('assert'); +const net = require('net'); +const tls = require('tls'); +const h2 = require('http2'); + +// This test sets up an H2 proxy server, and tunnels a request over one of its streams +// back to itself, via TLS, and then closes the TLS connection. On some Node versions +// (v18 & v20 up to 20.5.1) the resulting JS Stream Socket fails to shutdown correctly +// in this case, and crashes due to a null pointer in finishShutdown. + +const tlsOptions = { + key: fixtures.readKey('agent1-key.pem'), + cert: fixtures.readKey('agent1-cert.pem'), + ALPNProtocols: ['h2'] +}; + +const netServer = net.createServer((socket) => { + socket.allowHalfOpen = false; + // ^ This allows us to trigger this reliably, but it's not strictly required + // for the bug and crash to happen, skipping this just fails elsewhere later. + + h2Server.emit('connection', socket); +}); + +const h2Server = h2.createSecureServer(tlsOptions, (req, res) => { + res.writeHead(200); + res.end(); +}); + +h2Server.on('connect', (req, res) => { + res.writeHead(200, {}); + netServer.emit('connection', res.stream); +}); + +netServer.listen(0, common.mustCall(() => { + const proxyClient = h2.connect(`https://localhost:${netServer.address().port}`, { + rejectUnauthorized: false + }); + + const proxyReq = proxyClient.request({ + ':method': 'CONNECT', + ':authority': 'example.com:443' + }); + + proxyReq.on('response', common.mustCall((response) => { + assert.strictEqual(response[':status'], 200); + + // Create a TLS socket within the tunnel, and start sending a request: + const tlsSocket = tls.connect({ + socket: proxyReq, + ALPNProtocols: ['h2'], + rejectUnauthorized: false + }); + + proxyReq.on('close', common.mustCall(() => { + proxyClient.close(); + netServer.close(); + })); + + // Forcibly kill the TLS socket + tlsSocket.destroy(); + + // This results in an async error in affected Node versions, before the 'close' event + })); +})); diff --git a/test/parallel/test-http2-client-destroy.js b/test/parallel/test-http2-client-destroy.js index 6973cfa1df1e61..d7609fc33391ac 100644 --- a/test/parallel/test-http2-client-destroy.js +++ b/test/parallel/test-http2-client-destroy.js @@ -22,7 +22,7 @@ const { getEventListeners } = require('events'); server.close(); }); - destroyCallbacks.forEach((destroyCallback) => { + for (const destroyCallback of destroyCallbacks) { const client = h2.connect(`http://localhost:${server.address().port}`); client.on('connect', common.mustCall(() => { const socket = client[kSocket]; @@ -45,7 +45,7 @@ const { getEventListeners } = require('events'); countdown.dec(); })); - }); + } })); } diff --git a/test/parallel/test-http2-server-shutdown-options-errors.js b/test/parallel/test-http2-server-shutdown-options-errors.js index e6a69b54627e00..5a2ca62a6c8e31 100644 --- a/test/parallel/test-http2-server-shutdown-options-errors.js +++ b/test/parallel/test-http2-server-shutdown-options-errors.js @@ -19,7 +19,7 @@ const types = [ server.on('stream', common.mustCall((stream) => { const session = stream.session; - types.forEach((input) => { + for (const input of types) { const received = common.invalidArgTypeHelper(input); assert.throws( () => session.goaway(input), @@ -48,7 +48,7 @@ server.on('stream', common.mustCall((stream) => { `TypedArray, or DataView.${received}` } ); - }); + } stream.session.destroy(); })); diff --git a/test/parallel/test-https-agent-session-eviction.js b/test/parallel/test-https-agent-session-eviction.js index 940c43cc40bf15..36c360a96503d5 100644 --- a/test/parallel/test-https-agent-session-eviction.js +++ b/test/parallel/test-https-agent-session-eviction.js @@ -54,6 +54,7 @@ function faultyServer(port) { function second(server, session) { const req = https.request({ port: server.address().port, + ciphers: (common.hasOpenSSL31 ? 'DEFAULT:@SECLEVEL=0' : 'DEFAULT'), rejectUnauthorized: false }, function(res) { res.resume(); diff --git a/test/parallel/test-https-server-close-destroy-timeout.js b/test/parallel/test-https-server-close-destroy-timeout.js new file mode 100644 index 00000000000000..e876721f610964 --- /dev/null +++ b/test/parallel/test-https-server-close-destroy-timeout.js @@ -0,0 +1,24 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +if (!common.hasCrypto) { + common.skip('missing crypto'); +} + +const { createServer } = require('https'); +const { kConnectionsCheckingInterval } = require('_http_server'); + +const fixtures = require('../common/fixtures'); + +const options = { + key: fixtures.readKey('agent1-key.pem'), + cert: fixtures.readKey('agent1-cert.pem') +}; + +const server = createServer(options, function(req, res) {}); +server.listen(0, common.mustCall(function() { + assert.strictEqual(server[kConnectionsCheckingInterval]._destroyed, false); + server.close(common.mustCall(() => { + assert(server[kConnectionsCheckingInterval]._destroyed); + })); +})); diff --git a/test/parallel/test-https-server-close-idle.js b/test/parallel/test-https-server-close-idle.js index 7f093c47cd8609..49b525dd05f117 100644 --- a/test/parallel/test-https-server-close-idle.js +++ b/test/parallel/test-https-server-close-idle.js @@ -52,7 +52,6 @@ server.listen(0, function() { assert(response.startsWith('HTTP/1.1 200 OK\r\nConnection: keep-alive')); assert.strictEqual(connections, 2); - server.closeIdleConnections(); server.close(common.mustCall()); // Check that only the idle connection got closed diff --git a/test/parallel/test-https-server-connections-checking-leak.js b/test/parallel/test-https-server-connections-checking-leak.js new file mode 100644 index 00000000000000..3e7c45e4660ed4 --- /dev/null +++ b/test/parallel/test-https-server-connections-checking-leak.js @@ -0,0 +1,29 @@ +'use strict'; + +// Flags: --expose-gc + +// Check that creating a server without listening does not leak resources. + +const common = require('../common'); + +if (!common.hasCrypto) { + common.skip('missing crypto'); +} + +const onGC = require('../common/ongc'); +const Countdown = require('../common/countdown'); + +const https = require('https'); +const max = 100; + +// Note that Countdown internally calls common.mustCall, that's why it's not done here. +const countdown = new Countdown(max, () => {}); + +for (let i = 0; i < max; i++) { + const server = https.createServer((req, res) => {}); + onGC(server, { ongc: countdown.dec.bind(countdown) }); +} + +setImmediate(() => { + global.gc(); +}); diff --git a/test/parallel/test-inspector-break-when-eval.js b/test/parallel/test-inspector-break-when-eval.js index 1e7ab513dadbbb..bd9969e0dcfffd 100644 --- a/test/parallel/test-inspector-break-when-eval.js +++ b/test/parallel/test-inspector-break-when-eval.js @@ -6,7 +6,10 @@ const { NodeInstance } = require('../common/inspector-helper.js'); const fixtures = require('../common/fixtures'); const { pathToFileURL } = require('url'); -const script = fixtures.path('inspector-global-function.js'); +// This needs to be an ES module file to ensure that internal modules are +// loaded before pausing. See +// https://bugs.chromium.org/p/chromium/issues/detail?id=1246905 +const script = fixtures.path('inspector-global-function.mjs'); async function setupDebugger(session) { console.log('[test]', 'Setting up a debugger'); @@ -23,7 +26,7 @@ async function setupDebugger(session) { // NOTE(mmarchini): We wait for the second console.log to ensure we loaded // every internal module before pausing. See - // https://bugs.chromium.org/p/v8/issues/detail?id=10287. + // https://bugs.chromium.org/p/chromium/issues/detail?id=1246905 const waitForReady = session.waitForConsoleOutput('log', 'Ready!'); session.send({ 'method': 'Debugger.resume' }); await waitForReady; diff --git a/test/parallel/test-inspector-inspect-brk-node.js b/test/parallel/test-inspector-inspect-brk-node.js index 0f4795ed7b87e4..04bac6dc7cf0df 100644 --- a/test/parallel/test-inspector-inspect-brk-node.js +++ b/test/parallel/test-inspector-inspect-brk-node.js @@ -16,7 +16,7 @@ async function runTest() { await session.waitForNotification((notification) => { // The main assertion here is that we do hit the loader script first. return notification.method === 'Debugger.scriptParsed' && - notification.params.url === 'node:internal/bootstrap/loaders'; + notification.params.url === 'node:internal/bootstrap/realm'; }); await session.waitForNotification('Debugger.paused'); diff --git a/test/parallel/test-internal-util-decorate-error-stack.js b/test/parallel/test-internal-util-decorate-error-stack.js index 3566d9375fb81c..f3034fbb05ae54 100644 --- a/test/parallel/test-internal-util-decorate-error-stack.js +++ b/test/parallel/test-internal-util-decorate-error-stack.js @@ -58,7 +58,7 @@ checkStack(err.stack); // Verify that the stack is only decorated once for uncaught exceptions. const args = [ '-e', - `require('${badSyntaxPath}')`, + `require(${JSON.stringify(badSyntaxPath)})`, ]; const result = spawnSync(process.argv[0], args, { encoding: 'utf8' }); checkStack(result.stderr); diff --git a/test/parallel/test-module-binding.js b/test/parallel/test-module-binding.js index a0fa0a038990f0..47170785434099 100644 --- a/test/parallel/test-module-binding.js +++ b/test/parallel/test-module-binding.js @@ -3,35 +3,27 @@ require('../common'); const fixtures = require('../common/fixtures'); const { internalBinding } = require('internal/test/binding'); +const { filterOwnProperties } = require('internal/util'); const { internalModuleReadJSON } = internalBinding('fs'); const { readFileSync } = require('fs'); -const { strictEqual } = require('assert'); +const { strictEqual, deepStrictEqual } = require('assert'); + { - const [string, containsKeys] = internalModuleReadJSON('nosuchfile'); - strictEqual(string, undefined); - strictEqual(containsKeys, undefined); + strictEqual(internalModuleReadJSON('nosuchfile')[0], undefined); } { - const [string, containsKeys] = - internalModuleReadJSON(fixtures.path('empty.txt')); - strictEqual(string, ''); - strictEqual(containsKeys, false); + strictEqual(internalModuleReadJSON(fixtures.path('empty.txt'))[0], ''); } { - const [string, containsKeys] = - internalModuleReadJSON(fixtures.path('empty.txt')); - strictEqual(string, ''); - strictEqual(containsKeys, false); -} -{ - const [string, containsKeys] = - internalModuleReadJSON(fixtures.path('empty-with-bom.txt')); - strictEqual(string, ''); - strictEqual(containsKeys, false); + strictEqual(internalModuleReadJSON(fixtures.path('empty-with-bom.txt'))[0], ''); } { const filename = fixtures.path('require-bin/package.json'); - const [string, containsKeys] = internalModuleReadJSON(filename); - strictEqual(string, readFileSync(filename, 'utf8')); - strictEqual(containsKeys, true); + const returnValue = JSON.parse(internalModuleReadJSON(filename)[0]); + const file = JSON.parse(readFileSync(filename, 'utf-8')); + const expectedValue = filterOwnProperties(file, ['name', 'main', 'exports', 'imports', 'type']); + deepStrictEqual({ + __proto__: null, + ...returnValue, + }, expectedValue); } diff --git a/test/parallel/test-module-create-require.js b/test/parallel/test-module-create-require.js index e0e34e9f127bd3..30ebf96652390d 100644 --- a/test/parallel/test-module-create-require.js +++ b/test/parallel/test-module-create-require.js @@ -1,13 +1,12 @@ 'use strict'; require('../common'); +const fixtures = require('../common/fixtures'); const assert = require('assert'); -const path = require('path'); const { createRequire } = require('module'); -const p = path.resolve(__dirname, '..', 'fixtures', 'fake.js'); -const u = new URL(`file://${p}`); +const u = fixtures.fileURL('fake.js'); const reqToo = createRequire(u); assert.deepStrictEqual(reqToo('./experimental'), { ofLife: 42 }); diff --git a/test/parallel/test-net-autoselectfamily.js b/test/parallel/test-net-autoselectfamily.js index 6990b57652fa5f..904b795f927138 100644 --- a/test/parallel/test-net-autoselectfamily.js +++ b/test/parallel/test-net-autoselectfamily.js @@ -282,6 +282,10 @@ if (common.hasIPv6) { assert.strictEqual(error.message, `connect ECONNREFUSED ::1:${port}`); } else if (error.code === 'EAFNOSUPPORT') { assert.strictEqual(error.message, `connect EAFNOSUPPORT ::1:${port} - Local (undefined:undefined)`); + } else if (common.isIBMi) { + // IBMi returns EUNATCH (ERRNO 42) when IPv6 is disabled + // keep this errno assertion until EUNATCH is recognized by libuv + assert.strictEqual(error.errno, -42); } else { assert.strictEqual(error.code, 'EADDRNOTAVAIL'); assert.strictEqual(error.message, `connect EADDRNOTAVAIL ::1:${port} - Local (:::0)`); diff --git a/test/parallel/test-net-autoselectfamilydefault.js b/test/parallel/test-net-autoselectfamilydefault.js index a3faa9c3c1e118..be110a836a057b 100644 --- a/test/parallel/test-net-autoselectfamilydefault.js +++ b/test/parallel/test-net-autoselectfamilydefault.js @@ -129,6 +129,10 @@ function createDnsServer(ipv6Addr, ipv4Addr, cb) { assert.strictEqual(error.message, `connect ECONNREFUSED ::1:${port}`); } else if (error.code === 'EAFNOSUPPORT') { assert.strictEqual(error.message, `connect EAFNOSUPPORT ::1:${port} - Local (undefined:undefined)`); + } else if (common.isIBMi) { + // IBMi returns EUNATCH (ERRNO 42) when IPv6 is disabled + // keep this errno assertion until EUNATCH is recognized by libuv + assert.strictEqual(error.errno, -42); } else { assert.strictEqual(error.code, 'EADDRNOTAVAIL'); assert.strictEqual(error.message, `connect EADDRNOTAVAIL ::1:${port} - Local (:::0)`); diff --git a/test/parallel/test-net-isipv4.js b/test/parallel/test-net-isipv4.js index 8f5c30569ce988..2c478e6ac678b7 100644 --- a/test/parallel/test-net-isipv4.js +++ b/test/parallel/test-net-isipv4.js @@ -37,10 +37,10 @@ const v4not = [ '192.168.0.2000000000', ]; -v4.forEach((ip) => { +for (const ip of v4) { assert.strictEqual(net.isIPv4(ip), true); -}); +} -v4not.forEach((ip) => { +for (const ip of v4not) { assert.strictEqual(net.isIPv4(ip), false); -}); +} diff --git a/test/parallel/test-net-socket-connect-invalid-autoselectfamilyattempttimeout.js b/test/parallel/test-net-socket-connect-invalid-autoselectfamilyattempttimeout.js index adec8200f697d2..0fc813781c95ec 100644 --- a/test/parallel/test-net-socket-connect-invalid-autoselectfamilyattempttimeout.js +++ b/test/parallel/test-net-socket-connect-invalid-autoselectfamilyattempttimeout.js @@ -18,3 +18,10 @@ for (const autoSelectFamilyAttemptTimeout of [-10, 0]) { net.setDefaultAutoSelectFamilyAttemptTimeout(autoSelectFamilyAttemptTimeout); }, { code: 'ERR_OUT_OF_RANGE' }); } + +// Check the default value of autoSelectFamilyAttemptTimeout is 10 +// if passed number is less than 10 +for (const autoSelectFamilyAttemptTimeout of [1, 9]) { + net.setDefaultAutoSelectFamilyAttemptTimeout(autoSelectFamilyAttemptTimeout); + assert.strictEqual(net.getDefaultAutoSelectFamilyAttemptTimeout(), 10); +} diff --git a/test/parallel/test-node-output-errors.mjs b/test/parallel/test-node-output-errors.mjs index fca2149fea3212..5be920627ad70e 100644 --- a/test/parallel/test-node-output-errors.mjs +++ b/test/parallel/test-node-output-errors.mjs @@ -3,6 +3,7 @@ import * as fixtures from '../common/fixtures.mjs'; import * as snapshot from '../common/assertSnapshot.js'; import * as os from 'node:os'; import { describe, it } from 'node:test'; +import { pathToFileURL } from 'node:url'; const skipForceColors = process.config.variables.icu_gyp_path !== 'tools/icu/icu-generic.gyp' || @@ -10,17 +11,24 @@ const skipForceColors = (common.isWindows && (Number(os.release().split('.')[0]) !== 10 || Number(os.release().split('.')[2]) < 14393)); // See https://github.com/nodejs/node/pull/33132 -function replaceNodeVersion(str) { - return str.replaceAll(process.version, '*'); -} - function replaceStackTrace(str) { return snapshot.replaceStackTrace(str, '$1at *$7\n'); } +function replaceForceColorsStackTrace(str) { + // eslint-disable-next-line no-control-regex + return str.replaceAll(/(\[90m\W+)at .*node:.*/g, '$1at *'); +} + describe('errors output', { concurrency: true }, () => { function normalize(str) { - return str.replaceAll(snapshot.replaceWindowsPaths(process.cwd()), '').replaceAll('//', '*').replaceAll(/\/(\w)/g, '*$1').replaceAll('*test*', '*').replaceAll('*fixtures*errors*', '*').replaceAll('file:**', 'file:*/'); + return str.replaceAll(snapshot.replaceWindowsPaths(process.cwd()), '') + .replaceAll(pathToFileURL(process.cwd()).pathname, '') + .replaceAll('//', '*') + .replaceAll(/\/(\w)/g, '*$1') + .replaceAll('*test*', '*') + .replaceAll('*fixtures*errors*', '*') + .replaceAll('file:**', 'file:*/'); } function normalizeNoNumbers(str) { @@ -28,9 +36,12 @@ describe('errors output', { concurrency: true }, () => { } const common = snapshot .transform(snapshot.replaceWindowsLineEndings, snapshot.replaceWindowsPaths); - const defaultTransform = snapshot.transform(common, normalize, replaceNodeVersion); - const errTransform = snapshot.transform(common, normalizeNoNumbers, replaceNodeVersion); - const promiseTransform = snapshot.transform(common, replaceStackTrace, normalizeNoNumbers, replaceNodeVersion); + const defaultTransform = snapshot.transform(common, normalize, snapshot.replaceNodeVersion); + const errTransform = snapshot.transform(common, normalizeNoNumbers, snapshot.replaceNodeVersion); + const promiseTransform = snapshot.transform(common, replaceStackTrace, + normalizeNoNumbers, snapshot.replaceNodeVersion); + const forceColorsTransform = snapshot.transform(common, normalize, + replaceForceColorsStackTrace, snapshot.replaceNodeVersion); const tests = [ { name: 'errors/async_error_eval_cjs.js' }, @@ -50,11 +61,12 @@ describe('errors output', { concurrency: true }, () => { { name: 'errors/throw_in_line_with_tabs.js', transform: errTransform }, { name: 'errors/throw_non_error.js', transform: errTransform }, { name: 'errors/promise_always_throw_unhandled.js', transform: promiseTransform }, - !skipForceColors ? { name: 'errors/force_colors.js', env: { FORCE_COLOR: 1 } } : null, - ].filter(Boolean); - for (const { name, transform, env } of tests) { - it(name, async () => { - await snapshot.spawnAndAssert(fixtures.path(name), transform ?? defaultTransform, { env }); + { skip: skipForceColors, name: 'errors/force_colors.js', + transform: forceColorsTransform, env: { FORCE_COLOR: 1 } }, + ]; + for (const { name, transform = defaultTransform, env, skip = false } of tests) { + it(name, { skip }, async () => { + await snapshot.spawnAndAssert(fixtures.path(name), transform, { env }); }); } }); diff --git a/test/parallel/test-node-output-sourcemaps.mjs b/test/parallel/test-node-output-sourcemaps.mjs index 8e43947ab2188f..b01f30765c7de8 100644 --- a/test/parallel/test-node-output-sourcemaps.mjs +++ b/test/parallel/test-node-output-sourcemaps.mjs @@ -4,10 +4,6 @@ import * as snapshot from '../common/assertSnapshot.js'; import * as path from 'node:path'; import { describe, it } from 'node:test'; -function replaceNodeVersion(str) { - return str.replaceAll(process.version, '*'); -} - describe('sourcemaps output', { concurrency: true }, () => { function normalize(str) { const result = str @@ -16,7 +12,8 @@ describe('sourcemaps output', { concurrency: true }, () => { .replaceAll('/Users/bencoe/oss/coffee-script-test', '') .replaceAll(/\/(\w)/g, '*$1') .replaceAll('*test*', '*') - .replaceAll('*fixtures*source-map*', '*'); + .replaceAll('*fixtures*source-map*', '*') + .replaceAll(/(\W+).*node:internal\*modules.*/g, '$1*'); if (common.isWindows) { const currentDeviceLetter = path.parse(process.cwd()).root.substring(0, 1).toLowerCase(); const regex = new RegExp(`${currentDeviceLetter}:/?`, 'gi'); @@ -25,14 +22,21 @@ describe('sourcemaps output', { concurrency: true }, () => { return result; } const defaultTransform = snapshot - .transform(snapshot.replaceWindowsLineEndings, snapshot.replaceWindowsPaths, normalize, replaceNodeVersion); + .transform(snapshot.replaceWindowsLineEndings, snapshot.replaceWindowsPaths, + normalize, snapshot.replaceNodeVersion); const tests = [ { name: 'source-map/output/source_map_disabled_by_api.js' }, { name: 'source-map/output/source_map_enabled_by_api.js' }, + { name: 'source-map/output/source_map_enclosing_function.js' }, { name: 'source-map/output/source_map_eval.js' }, { name: 'source-map/output/source_map_no_source_file.js' }, + { name: 'source-map/output/source_map_reference_error_tabs.js' }, + { name: 'source-map/output/source_map_sourcemapping_url_string.js' }, + { name: 'source-map/output/source_map_throw_catch.js' }, { name: 'source-map/output/source_map_throw_first_tick.js' }, + { name: 'source-map/output/source_map_throw_icu.js' }, + { name: 'source-map/output/source_map_throw_set_immediate.js' }, ]; for (const { name, transform } of tests) { it(name, async () => { diff --git a/test/parallel/test-os.js b/test/parallel/test-os.js index f0f55fbe261946..f7059260ce507e 100644 --- a/test/parallel/test-os.js +++ b/test/parallel/test-os.js @@ -81,6 +81,15 @@ const hostname = os.hostname(); is.string(hostname); assert.ok(hostname.length > 0); +// IBMi process priority is different. +if (!common.isIBMi) { + const DUMMY_PRIORITY = 10; + os.setPriority(DUMMY_PRIORITY); + const priority = os.getPriority(); + is.number(priority); + assert.strictEqual(priority, DUMMY_PRIORITY); +} + // On IBMi, os.uptime() returns 'undefined' if (!common.isIBMi) { const uptime = os.uptime(); diff --git a/test/parallel/test-policy-manifest.js b/test/parallel/test-policy-manifest.js index 3f5057ff4a2cd4..3c4b1695d28835 100644 --- a/test/parallel/test-policy-manifest.js +++ b/test/parallel/test-policy-manifest.js @@ -9,7 +9,9 @@ common.requireNoPackageJSONAbove(); const assert = require('assert'); const { spawnSync } = require('child_process'); +const { cpSync, rmSync } = require('fs'); const fixtures = require('../common/fixtures.js'); +const tmpdir = require('../common/tmpdir.js'); { const policyFilepath = fixtures.path('policy-manifest', 'invalid.json'); @@ -25,6 +27,23 @@ const fixtures = require('../common/fixtures.js'); assert.match(stderr, /pattern needs to have a single trailing "\*"/); } +{ + tmpdir.refresh(); + const policyFilepath = tmpdir.resolve('file with % in its name.json'); + cpSync(fixtures.path('policy-manifest', 'invalid.json'), policyFilepath); + const result = spawnSync(process.execPath, [ + '--experimental-policy', + policyFilepath, + './fhqwhgads.js', + ]); + + assert.notStrictEqual(result.status, 0); + const stderr = result.stderr.toString(); + assert.match(stderr, /ERR_MANIFEST_INVALID_SPECIFIER/); + assert.match(stderr, /pattern needs to have a single trailing "\*"/); + rmSync(policyFilepath); +} + { const policyFilepath = fixtures.path('policy-manifest', 'onerror-exit.json'); const result = spawnSync(process.execPath, [ diff --git a/test/parallel/test-process-dlopen-error-message-crash.js b/test/parallel/test-process-dlopen-error-message-crash.js index d678021764e8f4..de8b3033195a46 100644 --- a/test/parallel/test-process-dlopen-error-message-crash.js +++ b/test/parallel/test-process-dlopen-error-message-crash.js @@ -17,7 +17,7 @@ assert.throws(() => { }, ({ name, code, message }) => { assert.strictEqual(name, 'Error'); assert.strictEqual(code, 'ERR_DLOPEN_FAILED'); - if (!common.isAIX) { + if (!common.isAIX && !common.isIBMi) { assert.match(message, /foo-%s\.node/); } return true; diff --git a/test/parallel/test-process-versions.js b/test/parallel/test-process-versions.js index 0fdc07b939e87e..98dbda9ee8f20b 100644 --- a/test/parallel/test-process-versions.js +++ b/test/parallel/test-process-versions.js @@ -4,6 +4,7 @@ const assert = require('assert'); // Import of pure js (non-shared) deps for comparison const acorn = require('../../deps/acorn/acorn/package.json'); +const cjs_module_lexer = require('../../deps/cjs-module-lexer/package.json'); const expected_keys = [ 'ares', @@ -19,6 +20,8 @@ const expected_keys = [ 'acorn', 'simdutf', 'ada', + 'cjs_module_lexer', + 'base64', ]; const hasUndici = process.config.variables.node_builtin_shareable_builtins.includes('deps/undici/undici.js'); @@ -58,7 +61,7 @@ assert.match(process.versions.brotli, commonTemplate); assert.match(process.versions.llhttp, commonTemplate); assert.match(process.versions.node, commonTemplate); assert.match(process.versions.uv, commonTemplate); -assert.match(process.versions.zlib, /^\d+(?:\.\d+){2,3}(?:-.*)?$/); +assert.match(process.versions.zlib, /^\d+(?:\.\d+){1,3}(?:-.*)?$/); if (hasUndici) { assert.match(process.versions.undici, commonTemplate); @@ -69,15 +72,20 @@ assert.match( /^\d+\.\d+\.\d+(?:\.\d+)?-node\.\d+(?: \(candidate\))?$/ ); assert.match(process.versions.modules, /^\d+$/); +assert.match(process.versions.cjs_module_lexer, commonTemplate); if (common.hasCrypto) { - const versionRegex = common.hasOpenSSL3 ? - // The following also matches a development version of OpenSSL 3.x which - // can be in the format '3.0.0-alpha4-dev'. This can be handy when building - // and linking against the main development branch of OpenSSL. - /^\d+\.\d+\.\d+(?:[-+][a-z0-9]+)*$/ : - /^\d+\.\d+\.\d+[a-z]?(\+quic)?(-fips)?$/; - assert.match(process.versions.openssl, versionRegex); + if (process.config.variables.node_shared_openssl) { + assert.ok(process.versions.openssl); + } else { + const versionRegex = common.hasOpenSSL3 ? + // The following also matches a development version of OpenSSL 3.x which + // can be in the format '3.0.0-alpha4-dev'. This can be handy when + // building and linking against the main development branch of OpenSSL. + /^\d+\.\d+\.\d+(?:[-+][a-z0-9]+)*$/ : + /^\d+\.\d+\.\d+[a-z]?(\+quic)?(-fips)?$/; + assert.match(process.versions.openssl, versionRegex); + } } for (let i = 0; i < expected_keys.length; i++) { @@ -97,3 +105,5 @@ if (hasUndici) { const expectedAcornVersion = acorn.version; assert.strictEqual(process.versions.acorn, expectedAcornVersion); +const expectedCjsModuleLexerVersion = cjs_module_lexer.version; +assert.strictEqual(process.versions.cjs_module_lexer, expectedCjsModuleLexerVersion); diff --git a/test/parallel/test-repl-require-context.js b/test/parallel/test-repl-require-context.js index 750235818b8bfc..af09249c2de919 100644 --- a/test/parallel/test-repl-require-context.js +++ b/test/parallel/test-repl-require-context.js @@ -19,6 +19,6 @@ child.on('exit', common.mustCall(() => { child.stdin.write('const isObject = (obj) => obj.constructor === Object;\n'); child.stdin.write('isObject({});\n'); -child.stdin.write(`require('${fixture}').isObject({});\n`); +child.stdin.write(`require(${JSON.stringify(fixture)}).isObject({});\n`); child.stdin.write('.exit'); child.stdin.end(); diff --git a/test/parallel/test-repl.js b/test/parallel/test-repl.js index 3eb5d255927421..ac499625ae7648 100644 --- a/test/parallel/test-repl.js +++ b/test/parallel/test-repl.js @@ -817,7 +817,74 @@ const tcpTests = [ kArrow, '', 'Uncaught:', - /^SyntaxError: .* dynamic import/, + 'SyntaxError: Cannot use import statement inside the Node.js REPL, \ +alternatively use dynamic import: const { default: comeOn } = await import("fhqwhgads");', + ] + }, + { + send: 'import { export1, export2 } from "module-name"', + expect: [ + kSource, + kArrow, + '', + 'Uncaught:', + 'SyntaxError: Cannot use import statement inside the Node.js REPL, \ +alternatively use dynamic import: const { export1, export2 } = await import("module-name");', + ] + }, + { + send: 'import * as name from "module-name";', + expect: [ + kSource, + kArrow, + '', + 'Uncaught:', + 'SyntaxError: Cannot use import statement inside the Node.js REPL, \ +alternatively use dynamic import: const name = await import("module-name");', + ] + }, + { + send: 'import "module-name";', + expect: [ + kSource, + kArrow, + '', + 'Uncaught:', + 'SyntaxError: Cannot use import statement inside the Node.js REPL, \ +alternatively use dynamic import: await import("module-name");', + ] + }, + { + send: 'import { export1 as localName1, export2 } from "bar";', + expect: [ + kSource, + kArrow, + '', + 'Uncaught:', + 'SyntaxError: Cannot use import statement inside the Node.js REPL, \ +alternatively use dynamic import: const { export1: localName1, export2 } = await import("bar");', + ] + }, + { + send: 'import alias from "bar";', + expect: [ + kSource, + kArrow, + '', + 'Uncaught:', + 'SyntaxError: Cannot use import statement inside the Node.js REPL, \ +alternatively use dynamic import: const { default: alias } = await import("bar");', + ] + }, + { + send: 'import alias, {namedExport} from "bar";', + expect: [ + kSource, + kArrow, + '', + 'Uncaught:', + 'SyntaxError: Cannot use import statement inside the Node.js REPL, \ +alternatively use dynamic import: const { default: alias, namedExport } = await import("bar");', ] }, ]; diff --git a/test/parallel/test-runner-cli-concurrency.js b/test/parallel/test-runner-cli-concurrency.js new file mode 100644 index 00000000000000..fbabaf08e27279 --- /dev/null +++ b/test/parallel/test-runner-cli-concurrency.js @@ -0,0 +1,26 @@ +'use strict'; +require('../common'); +const fixtures = require('../common/fixtures'); +const assert = require('node:assert'); +const { spawnSync } = require('node:child_process'); +const { test } = require('node:test'); +const cwd = fixtures.path('test-runner', 'default-behavior'); +const env = { ...process.env, 'NODE_DEBUG': 'test_runner' }; + +test('default concurrency', async () => { + const args = ['--test']; + const cp = spawnSync(process.execPath, args, { cwd, env }); + assert.match(cp.stderr.toString(), /concurrency: true,/); +}); + +test('concurrency of one', async () => { + const args = ['--test', '--test-concurrency=1']; + const cp = spawnSync(process.execPath, args, { cwd, env }); + assert.match(cp.stderr.toString(), /concurrency: 1,/); +}); + +test('concurrency of two', async () => { + const args = ['--test', '--test-concurrency=2']; + const cp = spawnSync(process.execPath, args, { cwd, env }); + assert.match(cp.stderr.toString(), /concurrency: 2,/); +}); diff --git a/test/parallel/test-runner-cli.js b/test/parallel/test-runner-cli.js index 60da7b67037456..81e20045e33bdd 100644 --- a/test/parallel/test-runner-cli.js +++ b/test/parallel/test-runner-cli.js @@ -4,6 +4,7 @@ require('../common'); const assert = require('assert'); const { spawnSync } = require('child_process'); const { join } = require('path'); +const { readdirSync } = require('fs'); const fixtures = require('../common/fixtures'); const testFixtures = fixtures.path('test-runner'); @@ -21,8 +22,8 @@ const testFixtures = fixtures.path('test-runner'); { // Default behavior. node_modules is ignored. Files that don't match the // pattern are ignored except in test/ directories. - const args = ['--test', testFixtures]; - const child = spawnSync(process.execPath, args); + const args = ['--test']; + const child = spawnSync(process.execPath, args, { cwd: join(testFixtures, 'default-behavior') }); assert.strictEqual(child.status, 1); assert.strictEqual(child.signal, null); @@ -38,8 +39,8 @@ const testFixtures = fixtures.path('test-runner'); { // Same but with a prototype mutation in require scripts. - const args = ['--require', join(testFixtures, 'protoMutation.js'), '--test', testFixtures]; - const child = spawnSync(process.execPath, args); + const args = ['--require', join(testFixtures, 'protoMutation.js'), '--test']; + const child = spawnSync(process.execPath, args, { cwd: join(testFixtures, 'default-behavior') }); const stdout = child.stdout.toString(); assert.match(stdout, /ok 1 - this should pass/); @@ -55,23 +56,19 @@ const testFixtures = fixtures.path('test-runner'); { // User specified files that don't match the pattern are still run. - const args = ['--test', testFixtures, join(testFixtures, 'index.js')]; - const child = spawnSync(process.execPath, args); + const args = ['--test', join(testFixtures, 'index.js')]; + const child = spawnSync(process.execPath, args, { cwd: testFixtures }); assert.strictEqual(child.status, 1); assert.strictEqual(child.signal, null); assert.strictEqual(child.stderr.toString(), ''); const stdout = child.stdout.toString(); assert.match(stdout, /not ok 1 - .+index\.js/); - assert.match(stdout, /ok 2 - this should pass/); - assert.match(stdout, /not ok 3 - this should fail/); - assert.match(stdout, /ok 4 - .+subdir.+subdir_test\.js/); - assert.match(stdout, /ok 5 - this should pass/); } { // Searches node_modules if specified. - const args = ['--test', join(testFixtures, 'node_modules')]; + const args = ['--test', join(testFixtures, 'default-behavior/node_modules')]; const child = spawnSync(process.execPath, args); assert.strictEqual(child.status, 1); @@ -84,7 +81,7 @@ const testFixtures = fixtures.path('test-runner'); { // The current directory is used by default. const args = ['--test']; - const options = { cwd: testFixtures }; + const options = { cwd: join(testFixtures, 'default-behavior') }; const child = spawnSync(process.execPath, args, options); assert.strictEqual(child.status, 1); @@ -123,7 +120,7 @@ const testFixtures = fixtures.path('test-runner'); // Test combined stream outputs const args = [ '--test', - 'test/fixtures/test-runner/index.test.js', + 'test/fixtures/test-runner/default-behavior/index.test.js', 'test/fixtures/test-runner/nested.js', 'test/fixtures/test-runner/invalid-tap.js', ]; @@ -201,7 +198,7 @@ const testFixtures = fixtures.path('test-runner'); const args = ['--no-warnings', '--experimental-loader', 'data:text/javascript,', '--require', fixtures.path('empty.js'), - '--test', join(testFixtures, 'index.test.js')]; + '--test', join(testFixtures, 'default-behavior', 'index.test.js')]; const child = spawnSync(process.execPath, args); assert.strictEqual(child.stderr.toString(), ''); @@ -210,3 +207,135 @@ const testFixtures = fixtures.path('test-runner'); const stdout = child.stdout.toString(); assert.match(stdout, /ok 1 - this should pass/); } + +{ + // --test-shard option validation + const args = ['--test', '--test-shard=1', join(testFixtures, 'index.js')]; + const child = spawnSync(process.execPath, args, { cwd: testFixtures }); + + assert.strictEqual(child.status, 1); + assert.strictEqual(child.signal, null); + assert.match(child.stderr.toString(), /The argument '--test-shard' must be in the form of \/\. Received '1'/); + const stdout = child.stdout.toString(); + assert.strictEqual(stdout, ''); +} + +{ + // --test-shard option validation + const args = ['--test', '--test-shard=1/2/3', join(testFixtures, 'index.js')]; + const child = spawnSync(process.execPath, args, { cwd: testFixtures }); + + assert.strictEqual(child.status, 1); + assert.strictEqual(child.signal, null); + assert.match(child.stderr.toString(), /The argument '--test-shard' must be in the form of \/\. Received '1\/2\/3'/); + const stdout = child.stdout.toString(); + assert.strictEqual(stdout, ''); +} + +{ + // --test-shard option validation + const args = ['--test', '--test-shard=0/3', join(testFixtures, 'index.js')]; + const child = spawnSync(process.execPath, args, { cwd: testFixtures }); + + assert.strictEqual(child.status, 1); + assert.strictEqual(child.signal, null); + assert.match(child.stderr.toString(), /The value of "options\.shard\.index" is out of range\. It must be >= 1 && <= 3 \("options\.shard\.total"\)\. Received 0/); + const stdout = child.stdout.toString(); + assert.strictEqual(stdout, ''); +} + +{ + // --test-shard option validation + const args = ['--test', '--test-shard=0xf/20abcd', join(testFixtures, 'index.js')]; + const child = spawnSync(process.execPath, args, { cwd: testFixtures }); + + assert.strictEqual(child.status, 1); + assert.strictEqual(child.signal, null); + assert.match(child.stderr.toString(), /The argument '--test-shard' must be in the form of \/\. Received '0xf\/20abcd'/); + const stdout = child.stdout.toString(); + assert.strictEqual(stdout, ''); +} + +{ + // --test-shard option validation + const args = ['--test', '--test-shard=hello', join(testFixtures, 'index.js')]; + const child = spawnSync(process.execPath, args, { cwd: testFixtures }); + + assert.strictEqual(child.status, 1); + assert.strictEqual(child.signal, null); + assert.match(child.stderr.toString(), /The argument '--test-shard' must be in the form of \/\. Received 'hello'/); + const stdout = child.stdout.toString(); + assert.strictEqual(stdout, ''); +} + +{ + // --test-shard option, first shard + const shardsTestPath = join(testFixtures, 'shards'); + const allShardsTestsFiles = readdirSync(shardsTestPath).map((file) => join(shardsTestPath, file)); + const args = [ + '--test', + '--test-shard=1/2', + ...allShardsTestsFiles, + ]; + const child = spawnSync(process.execPath, args); + + assert.strictEqual(child.status, 0); + assert.strictEqual(child.signal, null); + assert.strictEqual(child.stderr.toString(), ''); + const stdout = child.stdout.toString(); + assert.match(stdout, /# Subtest: a\.cjs this should pass/); + assert.match(stdout, /ok 1 - a\.cjs this should pass/); + + assert.match(stdout, /# Subtest: c\.cjs this should pass/); + assert.match(stdout, /ok 2 - c\.cjs this should pass/); + + assert.match(stdout, /# Subtest: e\.cjs this should pass/); + assert.match(stdout, /ok 3 - e\.cjs this should pass/); + + assert.match(stdout, /# Subtest: g\.cjs this should pass/); + assert.match(stdout, /ok 4 - g\.cjs this should pass/); + + assert.match(stdout, /# Subtest: i\.cjs this should pass/); + assert.match(stdout, /ok 5 - i\.cjs this should pass/); + + assert.match(stdout, /# tests 5/); + assert.match(stdout, /# pass 5/); + assert.match(stdout, /# fail 0/); + assert.match(stdout, /# skipped 0/); +} + +{ + // --test-shard option, last shard + const shardsTestPath = join(testFixtures, 'shards'); + const allShardsTestsFiles = readdirSync(shardsTestPath).map((file) => join(shardsTestPath, file)); + const args = [ + '--test', + '--test-shard=2/2', + ...allShardsTestsFiles, + ]; + const child = spawnSync(process.execPath, args); + + assert.strictEqual(child.status, 0); + assert.strictEqual(child.signal, null); + assert.strictEqual(child.stderr.toString(), ''); + const stdout = child.stdout.toString(); + assert.match(stdout, /# Subtest: b\.cjs this should pass/); + assert.match(stdout, /ok 1 - b\.cjs this should pass/); + + assert.match(stdout, /# Subtest: d\.cjs this should pass/); + assert.match(stdout, /ok 2 - d\.cjs this should pass/); + + assert.match(stdout, /# Subtest: f\.cjs this should pass/); + assert.match(stdout, /ok 3 - f\.cjs this should pass/); + + assert.match(stdout, /# Subtest: h\.cjs this should pass/); + assert.match(stdout, /ok 4 - h\.cjs this should pass/); + + assert.match(stdout, /# Subtest: j\.cjs this should pass/); + assert.match(stdout, /ok 5 - j\.cjs this should pass/); + + assert.match(stdout, /# tests 5/); + assert.match(stdout, /# pass 5/); + assert.match(stdout, /# fail 0/); + assert.match(stdout, /# skipped 0/); +} diff --git a/test/parallel/test-runner-exit-code.js b/test/parallel/test-runner-exit-code.js index 1c28c2439050fc..700480386d5b4a 100644 --- a/test/parallel/test-runner-exit-code.js +++ b/test/parallel/test-runner-exit-code.js @@ -20,7 +20,7 @@ async function runAndKill(file) { }); const [code, signal] = await once(child, 'exit'); await finished(child.stdout); - assert.strictEqual(stdout, 'TAP version 13\n'); + assert(stdout.startsWith('TAP version 13\n')); assert.strictEqual(signal, null); assert.strictEqual(code, 1); } @@ -43,10 +43,26 @@ if (process.argv[2] === 'child') { assert.strictEqual(child.status, 0); assert.strictEqual(child.signal, null); - child = spawnSync(process.execPath, ['--test', fixtures.path('test-runner', 'subdir', 'subdir_test.js')]); + child = spawnSync(process.execPath, [ + '--test', + fixtures.path('test-runner', 'default-behavior', 'subdir', 'subdir_test.js'), + ]); assert.strictEqual(child.status, 0); assert.strictEqual(child.signal, null); + + child = spawnSync(process.execPath, [ + '--test', + fixtures.path('test-runner', 'todo_exit_code.js'), + ]); + assert.strictEqual(child.status, 0); + assert.strictEqual(child.signal, null); + const stdout = child.stdout.toString(); + assert.match(stdout, /# tests 3/); + assert.match(stdout, /# pass 0/); + assert.match(stdout, /# fail 0/); + assert.match(stdout, /# todo 3/); + child = spawnSync(process.execPath, [__filename, 'child', 'fail']); assert.strictEqual(child.status, 1); assert.strictEqual(child.signal, null); diff --git a/test/parallel/test-runner-filetest-location.js b/test/parallel/test-runner-filetest-location.js new file mode 100644 index 00000000000000..4e09bcd35eea4f --- /dev/null +++ b/test/parallel/test-runner-filetest-location.js @@ -0,0 +1,20 @@ +'use strict'; +const common = require('../common'); +const fixtures = require('../common/fixtures'); +const { strictEqual } = require('node:assert'); +const { relative } = require('node:path'); +const { run } = require('node:test'); +const fixture = fixtures.path('test-runner', 'never_ending_sync.js'); +const relativePath = relative(process.cwd(), fixture); +const stream = run({ + files: [relativePath], + timeout: common.platformTimeout(100), +}); + +stream.on('test:fail', common.mustCall((result) => { + strictEqual(result.name, relativePath); + strictEqual(result.details.error.failureType, 'testTimeoutFailure'); + strictEqual(result.line, 1); + strictEqual(result.column, 1); + strictEqual(result.file, fixture); +})); diff --git a/test/parallel/test-runner-inspect.mjs b/test/parallel/test-runner-inspect.mjs index bdff1ce7ceb84f..fb8e0ef9031571 100644 --- a/test/parallel/test-runner-inspect.mjs +++ b/test/parallel/test-runner-inspect.mjs @@ -1,6 +1,6 @@ import * as common from '../common/index.mjs'; -import * as tmpdir from '../common/tmpdir.js'; import * as fixtures from '../common/fixtures.mjs'; +import tmpdir from '../common/tmpdir.js'; import assert from 'node:assert'; import path from 'node:path'; import fs from 'node:fs/promises'; @@ -11,7 +11,11 @@ common.skipIfInspectorDisabled(); tmpdir.refresh(); { - const child = new NodeInstance(['--test', '--inspect-brk=0'], undefined, fixtures.path('test-runner/index.test.js')); + const child = new NodeInstance( + ['--test', '--inspect-brk=0'], + undefined, + fixtures.path('test-runner/default-behavior/index.test.js') + ); let stdout = ''; let stderr = ''; diff --git a/test/parallel/test-runner-mock-timers.js b/test/parallel/test-runner-mock-timers.js new file mode 100644 index 00000000000000..3a2203091337c6 --- /dev/null +++ b/test/parallel/test-runner-mock-timers.js @@ -0,0 +1,874 @@ +'use strict'; +process.env.NODE_TEST_KNOWN_GLOBALS = 0; +const common = require('../common'); + +const assert = require('node:assert'); +const { it, mock, describe } = require('node:test'); +const nodeTimers = require('node:timers'); +const nodeTimersPromises = require('node:timers/promises'); + +describe('Mock Timers Test Suite', () => { + describe('MockTimers API', () => { + it('should throw an error if trying to enable a timer that is not supported', (t) => { + assert.throws(() => { + t.mock.timers.enable(['DOES_NOT_EXIST']); + }, { + code: 'ERR_INVALID_ARG_VALUE', + }); + }); + + it('should throw an error if trying to enable a timer twice', (t) => { + t.mock.timers.enable(); + assert.throws(() => { + t.mock.timers.enable(); + }, { + code: 'ERR_INVALID_STATE', + }); + }); + + it('should not throw if calling reset without enabling timers', (t) => { + t.mock.timers.reset(); + }); + + it('should throw an error if calling tick without enabling timers', (t) => { + assert.throws(() => { + t.mock.timers.tick(); + }, { + code: 'ERR_INVALID_STATE', + }); + }); + + it('should throw an error if calling tick with a negative number', (t) => { + t.mock.timers.enable(); + assert.throws(() => { + t.mock.timers.tick(-1); + }, { + code: 'ERR_INVALID_ARG_VALUE', + }); + }); + it('should check that propertyDescriptor gets back after resetting timers', (t) => { + const getDescriptor = (ctx, fn) => Object.getOwnPropertyDescriptor(ctx, fn); + const getCurrentTimersDescriptors = () => { + const timers = [ + 'setTimeout', + 'clearTimeout', + 'setInterval', + 'clearInterval', + 'setImmediate', + 'clearImmediate', + ]; + + const globalTimersDescriptors = timers.map((fn) => getDescriptor(global, fn)); + const nodeTimersDescriptors = timers.map((fn) => getDescriptor(nodeTimers, fn)); + const nodeTimersPromisesDescriptors = timers + .filter((fn) => !fn.includes('clear')) + .map((fn) => getDescriptor(nodeTimersPromises, fn)); + + return { + global: globalTimersDescriptors, + nodeTimers: nodeTimersDescriptors, + nodeTimersPromises: nodeTimersPromisesDescriptors, + }; + }; + + const originalDescriptors = getCurrentTimersDescriptors(); + + t.mock.timers.enable(); + const during = getCurrentTimersDescriptors(); + t.mock.timers.reset(); + const after = getCurrentTimersDescriptors(); + + for (const env in originalDescriptors) { + for (const prop in originalDescriptors[env]) { + const originalDescriptor = originalDescriptors[env][prop]; + const afterDescriptor = after[env][prop]; + + assert.deepStrictEqual( + originalDescriptor, + afterDescriptor, + ); + + assert.notDeepStrictEqual( + originalDescriptor, + during[env][prop], + ); + + assert.notDeepStrictEqual( + during[env][prop], + after[env][prop], + ); + + } + } + }); + + it('should reset all timers when calling .reset function', (t) => { + t.mock.timers.enable(); + const fn = t.mock.fn(); + global.setTimeout(fn, 1000); + t.mock.timers.reset(); + assert.throws(() => { + t.mock.timers.tick(1000); + }, { + code: 'ERR_INVALID_STATE', + }); + + assert.strictEqual(fn.mock.callCount(), 0); + }); + + it('should reset all timers when calling Symbol.dispose', (t) => { + t.mock.timers.enable(); + const fn = t.mock.fn(); + global.setTimeout(fn, 1000); + // TODO(benjamingr) refactor to `using` + t.mock.timers[Symbol.dispose](); + assert.throws(() => { + t.mock.timers.tick(1000); + }, { + code: 'ERR_INVALID_STATE', + }); + + assert.strictEqual(fn.mock.callCount(), 0); + }); + + it('should execute in order if timeout is the same', (t) => { + t.mock.timers.enable(); + const order = []; + const fn1 = t.mock.fn(() => order.push('f1')); + const fn2 = t.mock.fn(() => order.push('f2')); + global.setTimeout(fn1, 1000); + global.setTimeout(fn2, 1000); + t.mock.timers.tick(1000); + assert.strictEqual(fn1.mock.callCount(), 1); + assert.strictEqual(fn2.mock.callCount(), 1); + assert.deepStrictEqual(order, ['f1', 'f2']); + }); + + describe('runAll Suite', () => { + it('should throw an error if calling runAll without enabling timers', (t) => { + assert.throws(() => { + t.mock.timers.runAll(); + }, { + code: 'ERR_INVALID_STATE', + }); + }); + + it('should trigger all timers when calling .runAll function', async (t) => { + const timeoutFn = t.mock.fn(); + const intervalFn = t.mock.fn(); + + t.mock.timers.enable(); + global.setTimeout(timeoutFn, 1111); + const id = global.setInterval(intervalFn, 9999); + t.mock.timers.runAll(); + + global.clearInterval(id); + assert.strictEqual(timeoutFn.mock.callCount(), 1); + assert.strictEqual(intervalFn.mock.callCount(), 1); + }); + }); + + }); + + describe('globals/timers', () => { + describe('setTimeout Suite', () => { + it('should advance in time and trigger timers when calling the .tick function', (t) => { + mock.timers.enable(['setTimeout']); + + const fn = mock.fn(); + + global.setTimeout(fn, 4000); + + mock.timers.tick(4000); + assert.strictEqual(fn.mock.callCount(), 1); + mock.timers.reset(); + }); + + it('should advance in time and trigger timers when calling the .tick function multiple times', (t) => { + t.mock.timers.enable(['setTimeout']); + const fn = t.mock.fn(); + + global.setTimeout(fn, 2000); + + t.mock.timers.tick(1000); + assert.strictEqual(fn.mock.callCount(), 0); + t.mock.timers.tick(500); + assert.strictEqual(fn.mock.callCount(), 0); + t.mock.timers.tick(500); + assert.strictEqual(fn.mock.callCount(), 1); + }); + + it('should work with the same params as the original setTimeout', (t) => { + t.mock.timers.enable(['setTimeout']); + const fn = t.mock.fn(); + const args = ['a', 'b', 'c']; + global.setTimeout(fn, 2000, ...args); + + t.mock.timers.tick(1000); + t.mock.timers.tick(500); + t.mock.timers.tick(500); + + assert.strictEqual(fn.mock.callCount(), 1); + assert.deepStrictEqual(fn.mock.calls[0].arguments, args); + }); + + it('should keep setTimeout working if timers are disabled', (t, done) => { + const now = Date.now(); + const timeout = 2; + const expected = () => now - timeout; + global.setTimeout(common.mustCall(() => { + assert.strictEqual(now - timeout, expected()); + done(); + }), timeout); + }); + + }); + + describe('clearTimeout Suite', () => { + it('should not advance in time if clearTimeout was invoked', (t) => { + t.mock.timers.enable(['setTimeout']); + + const fn = mock.fn(); + + const id = global.setTimeout(fn, 4000); + global.clearTimeout(id); + t.mock.timers.tick(4000); + + assert.strictEqual(fn.mock.callCount(), 0); + }); + }); + + describe('setInterval Suite', () => { + it('should tick three times using fake setInterval', (t) => { + t.mock.timers.enable(['setInterval']); + const fn = t.mock.fn(); + + const id = global.setInterval(fn, 200); + + t.mock.timers.tick(200); + t.mock.timers.tick(200); + t.mock.timers.tick(200); + + global.clearInterval(id); + + assert.strictEqual(fn.mock.callCount(), 3); + }); + + it('should work with the same params as the original setInterval', (t) => { + t.mock.timers.enable(['setInterval']); + const fn = t.mock.fn(); + const args = ['a', 'b', 'c']; + const id = global.setInterval(fn, 200, ...args); + + t.mock.timers.tick(200); + t.mock.timers.tick(200); + t.mock.timers.tick(200); + + global.clearInterval(id); + + assert.strictEqual(fn.mock.callCount(), 3); + assert.deepStrictEqual(fn.mock.calls[0].arguments, args); + assert.deepStrictEqual(fn.mock.calls[1].arguments, args); + assert.deepStrictEqual(fn.mock.calls[2].arguments, args); + + }); + }); + + describe('clearInterval Suite', () => { + it('should not advance in time if clearInterval was invoked', (t) => { + t.mock.timers.enable(['setInterval']); + + const fn = mock.fn(); + const id = global.setInterval(fn, 200); + global.clearInterval(id); + t.mock.timers.tick(200); + + assert.strictEqual(fn.mock.callCount(), 0); + }); + }); + + describe('setImmediate Suite', () => { + it('should keep setImmediate working if timers are disabled', (t, done) => { + const now = Date.now(); + const timeout = 2; + const expected = () => now - timeout; + global.setImmediate(common.mustCall(() => { + assert.strictEqual(now - timeout, expected()); + done(); + })); + }); + + it('should work with the same params as the original setImmediate', (t) => { + t.mock.timers.enable(['setImmediate']); + const fn = t.mock.fn(); + const args = ['a', 'b', 'c']; + global.setImmediate(fn, ...args); + t.mock.timers.tick(9999); + + assert.strictEqual(fn.mock.callCount(), 1); + assert.deepStrictEqual(fn.mock.calls[0].arguments, args); + }); + + it('should not advance in time if clearImmediate was invoked', (t) => { + t.mock.timers.enable(['setImmediate']); + + const id = global.setImmediate(common.mustNotCall()); + global.clearImmediate(id); + t.mock.timers.tick(200); + }); + + it('should advance in time and trigger timers when calling the .tick function', (t) => { + t.mock.timers.enable(['setImmediate']); + global.setImmediate(common.mustCall(1)); + t.mock.timers.tick(0); + }); + + it('should execute in order if setImmediate is called multiple times', (t) => { + t.mock.timers.enable(['setImmediate']); + const order = []; + const fn1 = t.mock.fn(common.mustCall(() => order.push('f1'), 1)); + const fn2 = t.mock.fn(common.mustCall(() => order.push('f2'), 1)); + + global.setImmediate(fn1); + global.setImmediate(fn2); + + t.mock.timers.tick(0); + + assert.deepStrictEqual(order, ['f1', 'f2']); + }); + + it('should execute setImmediate first if setTimeout was also called', (t) => { + t.mock.timers.enable(['setImmediate', 'setTimeout']); + const order = []; + const fn1 = t.mock.fn(common.mustCall(() => order.push('f1'), 1)); + const fn2 = t.mock.fn(common.mustCall(() => order.push('f2'), 1)); + + global.setTimeout(fn2, 0); + global.setImmediate(fn1); + + t.mock.timers.tick(100); + + assert.deepStrictEqual(order, ['f1', 'f2']); + }); + }); + }); + + describe('timers Suite', () => { + describe('setTimeout Suite', () => { + it('should advance in time and trigger timers when calling the .tick function multiple times', (t) => { + t.mock.timers.enable(['setTimeout']); + const fn = t.mock.fn(); + const { setTimeout } = nodeTimers; + setTimeout(fn, 2000); + + t.mock.timers.tick(1000); + t.mock.timers.tick(500); + t.mock.timers.tick(500); + + assert.strictEqual(fn.mock.callCount(), 1); + }); + + it('should work with the same params as the original timers.setTimeout', (t) => { + t.mock.timers.enable(['setTimeout']); + const fn = t.mock.fn(); + const { setTimeout } = nodeTimers; + const args = ['a', 'b', 'c']; + setTimeout(fn, 2000, ...args); + + t.mock.timers.tick(1000); + t.mock.timers.tick(500); + t.mock.timers.tick(500); + + assert.strictEqual(fn.mock.callCount(), 1); + assert.deepStrictEqual(fn.mock.calls[0].arguments, args); + }); + }); + + describe('clearTimeout Suite', () => { + it('should not advance in time if clearTimeout was invoked', (t) => { + t.mock.timers.enable(['setTimeout']); + + const fn = mock.fn(); + const { setTimeout, clearTimeout } = nodeTimers; + const id = setTimeout(fn, 2000); + clearTimeout(id); + t.mock.timers.tick(2000); + + assert.strictEqual(fn.mock.callCount(), 0); + }); + }); + + describe('setInterval Suite', () => { + it('should tick three times using fake setInterval', (t) => { + t.mock.timers.enable(['setInterval']); + const fn = t.mock.fn(); + + const id = nodeTimers.setInterval(fn, 200); + + t.mock.timers.tick(200); + t.mock.timers.tick(200); + t.mock.timers.tick(200); + t.mock.timers.tick(200); + + nodeTimers.clearInterval(id); + + assert.strictEqual(fn.mock.callCount(), 4); + }); + + it('should work with the same params as the original timers.setInterval', (t) => { + t.mock.timers.enable(['setInterval']); + const fn = t.mock.fn(); + const args = ['a', 'b', 'c']; + const id = nodeTimers.setInterval(fn, 200, ...args); + + t.mock.timers.tick(200); + t.mock.timers.tick(200); + t.mock.timers.tick(200); + t.mock.timers.tick(200); + + nodeTimers.clearInterval(id); + + assert.strictEqual(fn.mock.callCount(), 4); + assert.deepStrictEqual(fn.mock.calls[0].arguments, args); + assert.deepStrictEqual(fn.mock.calls[1].arguments, args); + assert.deepStrictEqual(fn.mock.calls[2].arguments, args); + assert.deepStrictEqual(fn.mock.calls[3].arguments, args); + + }); + }); + + describe('clearInterval Suite', () => { + it('should not advance in time if clearInterval was invoked', (t) => { + t.mock.timers.enable(['setInterval']); + + const fn = mock.fn(); + const { setInterval, clearInterval } = nodeTimers; + const id = setInterval(fn, 200); + clearInterval(id); + t.mock.timers.tick(200); + + assert.strictEqual(fn.mock.callCount(), 0); + }); + }); + + describe('setImmediate Suite', () => { + it('should keep setImmediate working if timers are disabled', (t, done) => { + const now = Date.now(); + const timeout = 2; + const expected = () => now - timeout; + nodeTimers.setImmediate(common.mustCall(() => { + assert.strictEqual(now - timeout, expected()); + done(); + }, 1)); + }); + + it('should work with the same params as the original setImmediate', (t) => { + t.mock.timers.enable(['setImmediate']); + const fn = t.mock.fn(); + const args = ['a', 'b', 'c']; + nodeTimers.setImmediate(fn, ...args); + t.mock.timers.tick(9999); + + assert.strictEqual(fn.mock.callCount(), 1); + assert.deepStrictEqual(fn.mock.calls[0].arguments, args); + }); + + it('should not advance in time if clearImmediate was invoked', (t) => { + t.mock.timers.enable(['setImmediate']); + + const id = nodeTimers.setImmediate(common.mustNotCall()); + nodeTimers.clearImmediate(id); + t.mock.timers.tick(200); + }); + + it('should advance in time and trigger timers when calling the .tick function', (t) => { + t.mock.timers.enable(['setImmediate']); + nodeTimers.setImmediate(common.mustCall(1)); + t.mock.timers.tick(0); + }); + + it('should execute in order if setImmediate is called multiple times', (t) => { + t.mock.timers.enable(['setImmediate']); + const order = []; + const fn1 = t.mock.fn(common.mustCall(() => order.push('f1'), 1)); + const fn2 = t.mock.fn(common.mustCall(() => order.push('f2'), 1)); + + nodeTimers.setImmediate(fn1); + nodeTimers.setImmediate(fn2); + + t.mock.timers.tick(0); + + assert.deepStrictEqual(order, ['f1', 'f2']); + }); + + it('should execute setImmediate first if setTimeout was also called', (t) => { + t.mock.timers.enable(['setImmediate', 'setTimeout']); + const order = []; + const fn1 = t.mock.fn(common.mustCall(() => order.push('f1'), 1)); + const fn2 = t.mock.fn(common.mustCall(() => order.push('f2'), 1)); + + nodeTimers.setTimeout(fn2, 0); + nodeTimers.setImmediate(fn1); + + t.mock.timers.tick(100); + + assert.deepStrictEqual(order, ['f1', 'f2']); + }); + }); + }); + + describe('timers/promises', () => { + describe('setTimeout Suite', () => { + it('should advance in time and trigger timers when calling the .tick function multiple times', async (t) => { + t.mock.timers.enable(['setTimeout']); + + const p = nodeTimersPromises.setTimeout(2000); + + t.mock.timers.tick(1000); + t.mock.timers.tick(500); + t.mock.timers.tick(500); + t.mock.timers.tick(500); + + p.then(common.mustCall((result) => { + assert.strictEqual(result, undefined); + })); + }); + + it('should work with the same params as the original timers/promises/setTimeout', async (t) => { + t.mock.timers.enable(['setTimeout']); + const expectedResult = 'result'; + const controller = new AbortController(); + const p = nodeTimersPromises.setTimeout(2000, expectedResult, { + ref: true, + signal: controller.signal + }); + + t.mock.timers.tick(1000); + t.mock.timers.tick(500); + t.mock.timers.tick(500); + t.mock.timers.tick(500); + + const result = await p; + assert.strictEqual(result, expectedResult); + }); + + it('should abort operation if timers/promises/setTimeout received an aborted signal', async (t) => { + t.mock.timers.enable(['setTimeout']); + const expectedResult = 'result'; + const controller = new AbortController(); + const p = nodeTimersPromises.setTimeout(2000, expectedResult, { + ref: true, + signal: controller.signal + }); + + t.mock.timers.tick(1000); + controller.abort(); + t.mock.timers.tick(500); + t.mock.timers.tick(500); + t.mock.timers.tick(500); + await assert.rejects(() => p, { + name: 'AbortError', + }); + + }); + it('should abort operation even if the .tick wasn\'t called', async (t) => { + t.mock.timers.enable(['setTimeout']); + const expectedResult = 'result'; + const controller = new AbortController(); + const p = nodeTimersPromises.setTimeout(2000, expectedResult, { + ref: true, + signal: controller.signal + }); + + controller.abort(); + + await assert.rejects(() => p, { + name: 'AbortError', + }); + + }); + + it('should abort operation when .abort is called before calling setTimeout', async (t) => { + t.mock.timers.enable(['setTimeout']); + const expectedResult = 'result'; + const controller = new AbortController(); + controller.abort(); + const p = nodeTimersPromises.setTimeout(2000, expectedResult, { + ref: true, + signal: controller.signal + }); + + await assert.rejects(() => p, { + name: 'AbortError', + }); + + }); + + it('should reject given an an invalid signal instance', async (t) => { + t.mock.timers.enable(['setTimeout']); + const expectedResult = 'result'; + const p = nodeTimersPromises.setTimeout(2000, expectedResult, { + ref: true, + signal: {} + }); + + await assert.rejects(() => p, { + name: 'TypeError', + code: 'ERR_INVALID_ARG_TYPE' + }); + + }); + }); + + describe('setInterval Suite', () => { + it('should tick three times using fake setInterval', async (t) => { + t.mock.timers.enable(['setInterval']); + + const interval = 100; + const intervalIterator = nodeTimersPromises.setInterval(interval, Date.now()); + + const first = intervalIterator.next(); + const second = intervalIterator.next(); + const third = intervalIterator.next(); + + t.mock.timers.tick(interval); + t.mock.timers.tick(interval); + t.mock.timers.tick(interval); + t.mock.timers.tick(interval); + + const results = await Promise.all([ + first, + second, + third, + ]); + + const finished = await intervalIterator.return(); + assert.deepStrictEqual(finished, { done: true, value: undefined }); + + results.forEach((result) => { + assert.strictEqual(typeof result.value, 'number'); + assert.strictEqual(result.done, false); + }); + + }); + it('should tick five times testing a real use case', async (t) => { + + t.mock.timers.enable(['setInterval']); + + const expectedIterations = 5; + const interval = 1000; + const startedAt = Date.now(); + async function run() { + const times = []; + for await (const time of nodeTimersPromises.setInterval(interval, startedAt)) { + times.push(time); + if (times.length === expectedIterations) break; + + } + return times; + } + + const r = run(); + t.mock.timers.tick(interval); + t.mock.timers.tick(interval); + t.mock.timers.tick(interval); + t.mock.timers.tick(interval); + t.mock.timers.tick(interval); + + const timeResults = await r; + assert.strictEqual(timeResults.length, expectedIterations); + for (let it = 1; it < expectedIterations; it++) { + assert.strictEqual(timeResults[it - 1], startedAt + (interval * it)); + } + }); + + it('should abort operation given an abort controller signal', async (t) => { + t.mock.timers.enable(['setInterval']); + + const interval = 100; + const abortController = new AbortController(); + const intervalIterator = nodeTimersPromises.setInterval(interval, Date.now(), { + signal: abortController.signal + }); + + const first = intervalIterator.next(); + const second = intervalIterator.next(); + + t.mock.timers.tick(interval); + abortController.abort(); + t.mock.timers.tick(interval); + + const firstResult = await first; + // Interval * 2 because value can be a little bit greater than interval + assert.ok(firstResult.value < Date.now() + interval * 2); + assert.strictEqual(firstResult.done, false); + + await assert.rejects(() => second, { + name: 'AbortError', + }); + + }); + + it('should abort operation when .abort is called before calling setInterval', async (t) => { + t.mock.timers.enable(['setInterval']); + + const interval = 100; + const abortController = new AbortController(); + abortController.abort(); + const intervalIterator = nodeTimersPromises.setInterval(interval, Date.now(), { + signal: abortController.signal + }); + + const first = intervalIterator.next(); + t.mock.timers.tick(interval); + + await assert.rejects(() => first, { + name: 'AbortError', + }); + }); + + it('should abort operation given an abort controller signal on a real use case', async (t) => { + t.mock.timers.enable(['setInterval']); + const controller = new AbortController(); + const signal = controller.signal; + const interval = 200; + const expectedIterations = 2; + const startedAt = Date.now(); + const timeResults = []; + async function run() { + const it = nodeTimersPromises.setInterval(interval, startedAt, { signal }); + for await (const time of it) { + timeResults.push(time); + if (timeResults.length === 5) break; + } + } + + const r = run(); + t.mock.timers.tick(interval); + t.mock.timers.tick(interval); + controller.abort(); + t.mock.timers.tick(interval); + t.mock.timers.tick(interval); + t.mock.timers.tick(interval); + t.mock.timers.tick(interval); + + await assert.rejects(() => r, { + name: 'AbortError', + }); + assert.strictEqual(timeResults.length, expectedIterations); + + for (let it = 1; it < expectedIterations; it++) { + assert.strictEqual(timeResults[it - 1], startedAt + (interval * it)); + } + + }); + + }); + + describe('setImmediate Suite', () => { + it('should advance in time and trigger timers when calling the .tick function multiple times', (t, done) => { + t.mock.timers.enable(['setImmediate']); + const p = nodeTimersPromises.setImmediate(); + + t.mock.timers.tick(5555); + + p.then(common.mustCall((result) => { + assert.strictEqual(result, undefined); + done(); + }, 1)); + }); + + it('should work with the same params as the original timers/promises/setImmediate', async (t) => { + t.mock.timers.enable(['setImmediate']); + const expectedResult = 'result'; + const controller = new AbortController(); + const p = nodeTimersPromises.setImmediate(expectedResult, { + ref: true, + signal: controller.signal + }); + + t.mock.timers.tick(500); + + const result = await p; + assert.strictEqual(result, expectedResult); + }); + + it('should abort operation if timers/promises/setImmediate received an aborted signal', async (t) => { + t.mock.timers.enable(['setImmediate']); + const expectedResult = 'result'; + const controller = new AbortController(); + const p = nodeTimersPromises.setImmediate(expectedResult, { + ref: true, + signal: controller.signal + }); + + controller.abort(); + t.mock.timers.tick(0); + + await assert.rejects(() => p, { + name: 'AbortError', + }); + + }); + it('should abort operation even if the .tick wasn\'t called', async (t) => { + t.mock.timers.enable(['setImmediate']); + const expectedResult = 'result'; + const controller = new AbortController(); + const p = nodeTimersPromises.setImmediate(expectedResult, { + ref: true, + signal: controller.signal + }); + + controller.abort(); + + await assert.rejects(() => p, { + name: 'AbortError', + }); + }); + + it('should abort operation when .abort is called before calling setImmediate', async (t) => { + t.mock.timers.enable(['setImmediate']); + const expectedResult = 'result'; + const controller = new AbortController(); + controller.abort(); + const p = nodeTimersPromises.setImmediate(expectedResult, { + ref: true, + signal: controller.signal + }); + + await assert.rejects(() => p, { + name: 'AbortError', + }); + + }); + + it('should reject given an an invalid signal instance', async (t) => { + t.mock.timers.enable(['setImmediate']); + const expectedResult = 'result'; + const p = nodeTimersPromises.setImmediate(expectedResult, { + ref: true, + signal: {} + }); + + await assert.rejects(() => p, { + name: 'TypeError', + code: 'ERR_INVALID_ARG_TYPE' + }); + + }); + + it('should execute in order if setImmediate is called multiple times', async (t) => { + t.mock.timers.enable(['setImmediate']); + + const p1 = nodeTimersPromises.setImmediate('fn1'); + const p2 = nodeTimersPromises.setImmediate('fn2'); + + t.mock.timers.tick(0); + + const results = await Promise.race([p1, p2]); + + assert.strictEqual(results, 'fn1'); + }); + }); + }); +}); diff --git a/test/parallel/test-runner-output.mjs b/test/parallel/test-runner-output.mjs index 0d670c37bc9319..372ca8f3bae0ff 100644 --- a/test/parallel/test-runner-output.mjs +++ b/test/parallel/test-runner-output.mjs @@ -2,6 +2,7 @@ import * as common from '../common/index.mjs'; import * as fixtures from '../common/fixtures.mjs'; import * as snapshot from '../common/assertSnapshot.js'; import { describe, it } from 'node:test'; +import { hostname } from 'node:os'; const skipForceColors = process.config.variables.icu_gyp_path !== 'tools/icu/icu-generic.gyp' || @@ -9,7 +10,6 @@ const skipForceColors = function replaceTestDuration(str) { return str - .replaceAll(/duration_ms: 0(\r?\n)/g, 'duration_ms: ZERO$1') .replaceAll(/duration_ms: [0-9.]+/g, 'duration_ms: *') .replaceAll(/duration_ms [0-9.]+/g, 'duration_ms *'); } @@ -19,27 +19,64 @@ const stackTraceBasePath = new RegExp(`${color}\\(${process.cwd()}/?${color}(.*) function replaceSpecDuration(str) { return str - .replaceAll(/\(0(\r?\n)ms\)/g, '(ZEROms)') .replaceAll(/[0-9.]+ms/g, '*ms') .replaceAll(/duration_ms [0-9.]+/g, 'duration_ms *') .replace(stackTraceBasePath, '$3'); } -const defaultTransform = snapshot - .transform(snapshot.replaceWindowsLineEndings, snapshot.replaceStackTrace, replaceTestDuration); -const specTransform = snapshot - .transform(replaceSpecDuration, snapshot.replaceWindowsLineEndings, snapshot.replaceStackTrace); +function replaceJunitDuration(str) { + return str + .replaceAll(/time="[0-9.]+"/g, 'time="*"') + .replaceAll(/duration_ms [0-9.]+/g, 'duration_ms *') + .replaceAll(hostname(), 'HOSTNAME') + .replace(stackTraceBasePath, '$3'); +} + +function removeWindowsPathEscaping(str) { + return common.isWindows ? str.replaceAll(/\\\\/g, '\\') : str; +} + +function replaceTestLocationLine(str) { + return str.replaceAll(/(js:)(\d+)(:\d+)/g, '$1(LINE)$3'); +} + +const defaultTransform = snapshot.transform( + snapshot.replaceWindowsLineEndings, + snapshot.replaceStackTrace, + removeWindowsPathEscaping, + snapshot.replaceFullPaths, + snapshot.replaceWindowsPaths, + replaceTestDuration, + replaceTestLocationLine, +); +const specTransform = snapshot.transform( + replaceSpecDuration, + snapshot.replaceWindowsLineEndings, + snapshot.replaceStackTrace, +); +const junitTransform = snapshot.transform( + replaceJunitDuration, + snapshot.replaceWindowsLineEndings, + snapshot.replaceStackTrace, +); const tests = [ { name: 'test-runner/output/abort.js' }, { name: 'test-runner/output/abort_suite.js' }, + { name: 'test-runner/output/abort_hooks.js' }, { name: 'test-runner/output/describe_it.js' }, { name: 'test-runner/output/describe_nested.js' }, { name: 'test-runner/output/hooks.js' }, + { name: 'test-runner/output/timeout_in_before_each_should_not_affect_further_tests.js' }, + { name: 'test-runner/output/hooks-with-no-global-test.js' }, + { name: 'test-runner/output/before-and-after-each-too-many-listeners.js' }, + { name: 'test-runner/output/before-and-after-each-with-timeout-too-many-listeners.js' }, + { name: 'test-runner/output/global_after_should_fail_the_test.js' }, { name: 'test-runner/output/no_refs.js' }, { name: 'test-runner/output/no_tests.js' }, { name: 'test-runner/output/only_tests.js' }, { name: 'test-runner/output/dot_reporter.js' }, + { name: 'test-runner/output/junit_reporter.js', transform: junitTransform }, { name: 'test-runner/output/spec_reporter_successful.js', transform: specTransform }, { name: 'test-runner/output/spec_reporter.js', transform: specTransform }, { name: 'test-runner/output/spec_reporter_cli.js', transform: specTransform }, @@ -50,11 +87,20 @@ const tests = [ { name: 'test-runner/output/unresolved_promise.js' }, { name: 'test-runner/output/default_output.js', transform: specTransform, tty: true }, { name: 'test-runner/output/arbitrary-output.js' }, + { name: 'test-runner/output/async-test-scheduling.mjs' }, !skipForceColors ? { name: 'test-runner/output/arbitrary-output-colored.js', transform: snapshot.transform(specTransform, replaceTestDuration), tty: true } : false, { name: 'test-runner/output/dot_output_custom_columns.js', transform: specTransform, tty: true }, + { + name: 'test-runner/output/tap_escape.js', + transform: snapshot.transform( + snapshot.replaceWindowsLineEndings, + replaceTestDuration, + ), + }, + process.features.inspector ? { name: 'test-runner/output/coverage_failure.js' } : false, ] .filter(Boolean) .map(({ name, tty, transform }) => ({ diff --git a/test/parallel/test-runner-reporters.js b/test/parallel/test-runner-reporters.js index f25e1a18b9d78d..e5d41f0f21f49c 100644 --- a/test/parallel/test-runner-reporters.js +++ b/test/parallel/test-runner-reporters.js @@ -135,4 +135,25 @@ describe('node:test reporters', { concurrency: true }, () => { assert.strictEqual(child.stdout.toString(), ''); assert.match(child.stderr.toString(), /ERR_INVALID_ARG_TYPE/); }); + + it('should throw when reporter errors', async () => { + const child = spawnSync(process.execPath, + ['--test', '--test-reporter', fixtures.fileURL('test-runner/custom_reporters/throwing.js'), + fixtures.path('test-runner/default-behavior/index.test.js')]); + assert.strictEqual(child.status, 7); + assert.strictEqual(child.signal, null); + assert.strictEqual(child.stdout.toString(), 'Going to throw an error\n'); + assert.match(child.stderr.toString(), /Error: Reporting error\r?\n\s+at customReporter/); + }); + + it('should throw when reporter errors asynchronously', async () => { + const child = spawnSync(process.execPath, + ['--test', '--test-reporter', + fixtures.fileURL('test-runner/custom_reporters/throwing-async.js'), + fixtures.path('test-runner/default-behavior/index.test.js')]); + assert.strictEqual(child.status, 7); + assert.strictEqual(child.signal, null); + assert.strictEqual(child.stdout.toString(), 'Going to throw an error\n'); + assert.match(child.stderr.toString(), /Emitted 'error' event on Duplex instance/); + }); }); diff --git a/test/parallel/test-runner-root-after-with-refed-handles.js b/test/parallel/test-runner-root-after-with-refed-handles.js new file mode 100644 index 00000000000000..2149c2dba236cf --- /dev/null +++ b/test/parallel/test-runner-root-after-with-refed-handles.js @@ -0,0 +1,26 @@ +'use strict'; +const common = require('../common'); +const { before, after, test } = require('node:test'); +const { createServer } = require('node:http'); + +let server; + +before(common.mustCall(() => { + server = createServer(); + + return new Promise(common.mustCall((resolve, reject) => { + server.listen(0, common.mustCall((err) => { + if (err) { + reject(err); + } else { + resolve(); + } + })); + })); +})); + +after(common.mustCall(() => { + server.close(common.mustCall()); +})); + +test(); diff --git a/test/parallel/test-runner-run.mjs b/test/parallel/test-runner-run.mjs index 0e92abd92bb5a2..02fed7a3659162 100644 --- a/test/parallel/test-runner-run.mjs +++ b/test/parallel/test-runner-run.mjs @@ -26,7 +26,7 @@ describe('require(\'node:test\').run', { concurrency: true }, () => { }); it('should succeed with a file', async () => { - const stream = run({ files: [join(testFixtures, 'test/random.cjs')] }); + const stream = run({ files: [join(testFixtures, 'default-behavior/test/random.cjs')] }); stream.on('test:fail', common.mustNotCall()); stream.on('test:pass', common.mustCall(1)); // eslint-disable-next-line no-unused-vars @@ -34,7 +34,12 @@ describe('require(\'node:test\').run', { concurrency: true }, () => { }); it('should run same file twice', async () => { - const stream = run({ files: [join(testFixtures, 'test/random.cjs'), join(testFixtures, 'test/random.cjs')] }); + const stream = run({ + files: [ + join(testFixtures, 'default-behavior/test/random.cjs'), + join(testFixtures, 'default-behavior/test/random.cjs'), + ] + }); stream.on('test:fail', common.mustNotCall()); stream.on('test:pass', common.mustCall(2)); // eslint-disable-next-line no-unused-vars @@ -68,24 +73,43 @@ describe('require(\'node:test\').run', { concurrency: true }, () => { }); it('should be piped with dot', async () => { - const result = await run({ files: [join(testFixtures, 'test/random.cjs')] }).compose(dot).toArray(); + const result = await run({ + files: [join(testFixtures, 'default-behavior/test/random.cjs')] + }).compose(dot).toArray(); assert.deepStrictEqual(result, [ '.', '\n', ]); }); - it('should be piped with spec', async () => { - const specReporter = new spec(); - const result = await run({ files: [join(testFixtures, 'test/random.cjs')] }).compose(specReporter).toArray(); - const stringResults = result.map((bfr) => bfr.toString()); - assert.match(stringResults[0], /this should pass/); - assert.match(stringResults[1], /tests 1/); - assert.match(stringResults[1], /pass 1/); + describe('should be piped with spec reporter', () => { + it('new spec', async () => { + const specReporter = new spec(); + const result = await run({ + files: [join(testFixtures, 'default-behavior/test/random.cjs')] + }).compose(specReporter).toArray(); + const stringResults = result.map((bfr) => bfr.toString()); + assert.match(stringResults[0], /this should pass/); + assert.match(stringResults[1], /tests 1/); + assert.match(stringResults[1], /pass 1/); + }); + + it('spec()', async () => { + const specReporter = spec(); + const result = await run({ + files: [join(testFixtures, 'default-behavior/test/random.cjs')] + }).compose(specReporter).toArray(); + const stringResults = result.map((bfr) => bfr.toString()); + assert.match(stringResults[0], /this should pass/); + assert.match(stringResults[1], /tests 1/); + assert.match(stringResults[1], /pass 1/); + }); }); it('should be piped with tap', async () => { - const result = await run({ files: [join(testFixtures, 'test/random.cjs')] }).compose(tap).toArray(); + const result = await run({ + files: [join(testFixtures, 'default-behavior/test/random.cjs')] + }).compose(tap).toArray(); assert.strictEqual(result.length, 13); assert.strictEqual(result[0], 'TAP version 13\n'); assert.strictEqual(result[1], '# Subtest: this should pass\n'); @@ -103,7 +127,10 @@ describe('require(\'node:test\').run', { concurrency: true }, () => { }); it('should skip tests not matching testNamePatterns - RegExp', async () => { - const result = await run({ files: [join(testFixtures, 'test/skip_by_name.cjs')], testNamePatterns: [/executed/] }) + const result = await run({ + files: [join(testFixtures, 'default-behavior/test/skip_by_name.cjs')], + testNamePatterns: [/executed/] + }) .compose(tap) .toArray(); assert.strictEqual(result[2], 'ok 1 - this should be skipped # SKIP test name does not match pattern\n'); @@ -111,35 +138,303 @@ describe('require(\'node:test\').run', { concurrency: true }, () => { }); it('should skip tests not matching testNamePatterns - string', async () => { - const result = await run({ files: [join(testFixtures, 'test/skip_by_name.cjs')], testNamePatterns: ['executed'] }) + const result = await run({ + files: [join(testFixtures, 'default-behavior/test/skip_by_name.cjs')], + testNamePatterns: ['executed'] + }) .compose(tap) .toArray(); assert.strictEqual(result[2], 'ok 1 - this should be skipped # SKIP test name does not match pattern\n'); assert.strictEqual(result[5], 'ok 2 - this should be executed\n'); }); - it('should stop watch mode when abortSignal aborts', async () => { - const controller = new AbortController(); - const result = await run({ files: [join(testFixtures, 'test/random.cjs')], watch: true, signal: controller.signal }) - .compose(async function* (source) { - for await (const chunk of source) { - if (chunk.type === 'test:pass') { - controller.abort(); - yield chunk.data.name; - } - } - }) + it('should pass only to children', async () => { + const result = await run({ + files: [join(testFixtures, 'test_only.js')], + only: true + }) + .compose(tap) .toArray(); - assert.deepStrictEqual(result, ['this should pass']); + + assert.strictEqual(result[2], 'ok 1 - this should be skipped # SKIP \'only\' option not set\n'); + assert.strictEqual(result[5], 'ok 2 - this should be executed\n'); }); it('should emit "test:watch:drained" event on watch mode', async () => { const controller = new AbortController(); - await run({ files: [join(testFixtures, 'test/random.cjs')], watch: true, signal: controller.signal }) - .on('data', function({ type }) { - if (type === 'test:watch:drained') { - controller.abort(); + await run({ + files: [join(testFixtures, 'default-behavior/test/random.cjs')], + watch: true, + signal: controller.signal, + }).on('data', function({ type }) { + if (type === 'test:watch:drained') { + controller.abort(); + } + }); + }); + + describe('AbortSignal', () => { + it('should stop watch mode when abortSignal aborts', async () => { + const controller = new AbortController(); + const result = await run({ + files: [join(testFixtures, 'default-behavior/test/random.cjs')], + watch: true, + signal: controller.signal, + }) + .compose(async function* (source) { + for await (const chunk of source) { + if (chunk.type === 'test:pass') { + controller.abort(); + yield chunk.data.name; + } + } + }) + .toArray(); + assert.deepStrictEqual(result, ['this should pass']); + }); + + it('should abort when test succeeded', async () => { + const stream = run({ + files: [ + fixtures.path( + 'test-runner', + 'aborts', + 'successful-test-still-call-abort.js' + ), + ], + }); + + let passedTestCount = 0; + let failedTestCount = 0; + + let output = ''; + for await (const data of stream) { + if (data.type === 'test:stdout') { + output += data.data.message.toString(); } + if (data.type === 'test:fail') { + failedTestCount++; + } + if (data.type === 'test:pass') { + passedTestCount++; + } + } + + assert.match(output, /abort called for test 1/); + assert.match(output, /abort called for test 2/); + assert.strictEqual(failedTestCount, 0, new Error('no tests should fail')); + assert.strictEqual(passedTestCount, 2); + }); + + it('should abort when test failed', async () => { + const stream = run({ + files: [ + fixtures.path( + 'test-runner', + 'aborts', + 'failed-test-still-call-abort.js' + ), + ], + }); + + let passedTestCount = 0; + let failedTestCount = 0; + + let output = ''; + for await (const data of stream) { + if (data.type === 'test:stdout') { + output += data.data.message.toString(); + } + if (data.type === 'test:fail') { + failedTestCount++; + } + if (data.type === 'test:pass') { + passedTestCount++; + } + } + + assert.match(output, /abort called for test 1/); + assert.match(output, /abort called for test 2/); + assert.strictEqual(passedTestCount, 0, new Error('no tests should pass')); + assert.strictEqual(failedTestCount, 2); + }); + }); + + describe('sharding', () => { + const shardsTestsFixtures = fixtures.path('test-runner', 'shards'); + const shardsTestsFiles = [ + 'a.cjs', + 'b.cjs', + 'c.cjs', + 'd.cjs', + 'e.cjs', + 'f.cjs', + 'g.cjs', + 'h.cjs', + 'i.cjs', + 'j.cjs', + ].map((file) => join(shardsTestsFixtures, file)); + + describe('validation', () => { + it('should require shard.total when having shard option', () => { + assert.throws(() => run({ files: shardsTestsFiles, shard: {} }), { + name: 'TypeError', + code: 'ERR_INVALID_ARG_TYPE', + message: 'The "options.shard.total" property must be of type number. Received undefined' + }); }); + + it('should require shard.index when having shards option', () => { + assert.throws(() => run({ + files: shardsTestsFiles, + shard: { + total: 5 + } + }), { + name: 'TypeError', + code: 'ERR_INVALID_ARG_TYPE', + message: 'The "options.shard.index" property must be of type number. Received undefined' + }); + }); + + it('should require shard.total to be greater than 0 when having shard option', () => { + assert.throws(() => run({ + files: shardsTestsFiles, + shard: { + total: 0, + index: 1 + } + }), { + name: 'RangeError', + code: 'ERR_OUT_OF_RANGE', + message: + 'The value of "options.shard.total" is out of range. It must be >= 1 && <= 9007199254740991. Received 0' + }); + }); + + it('should require shard.index to be greater than 0 when having shard option', () => { + assert.throws(() => run({ + files: shardsTestsFiles, + shard: { + total: 6, + index: 0 + } + }), { + name: 'RangeError', + code: 'ERR_OUT_OF_RANGE', + // eslint-disable-next-line max-len + message: 'The value of "options.shard.index" is out of range. It must be >= 1 && <= 6 ("options.shard.total"). Received 0' + }); + }); + + it('should require shard.index to not be greater than the shards total when having shard option', () => { + assert.throws(() => run({ + files: shardsTestsFiles, + shard: { + total: 6, + index: 7 + } + }), { + name: 'RangeError', + code: 'ERR_OUT_OF_RANGE', + // eslint-disable-next-line max-len + message: 'The value of "options.shard.index" is out of range. It must be >= 1 && <= 6 ("options.shard.total"). Received 7' + }); + }); + + it('should require watch mode to be disabled when having shard option', () => { + assert.throws(() => run({ + files: shardsTestsFiles, + watch: true, + shard: { + total: 6, + index: 1 + } + }), { + name: 'TypeError', + code: 'ERR_INVALID_ARG_VALUE', + message: 'The property \'options.shard\' shards not supported with watch mode. Received true' + }); + }); + }); + + it('should run only the tests files matching the shard index', async () => { + const stream = run({ + files: shardsTestsFiles, + shard: { + total: 5, + index: 1 + } + }); + + const executedTestFiles = []; + stream.on('test:fail', common.mustNotCall()); + stream.on('test:pass', (passedTest) => { + executedTestFiles.push(passedTest.file); + }); + // eslint-disable-next-line no-unused-vars + for await (const _ of stream) ; + + assert.deepStrictEqual(executedTestFiles, [ + join(shardsTestsFixtures, 'a.cjs'), + join(shardsTestsFixtures, 'f.cjs'), + ]); + }); + + it('different shards should not run the same file', async () => { + const executedTestFiles = []; + + const testStreams = []; + const shards = 5; + for (let i = 1; i <= shards; i++) { + const stream = run({ + files: shardsTestsFiles, + shard: { + total: shards, + index: i + } + }); + stream.on('test:fail', common.mustNotCall()); + stream.on('test:pass', (passedTest) => { + executedTestFiles.push(passedTest.file); + }); + testStreams.push(stream); + } + + await Promise.all(testStreams.map(async (stream) => { + // eslint-disable-next-line no-unused-vars + for await (const _ of stream) ; + })); + + assert.deepStrictEqual(executedTestFiles, [...new Set(executedTestFiles)]); + }); + + it('combination of all shards should be all the tests', async () => { + const executedTestFiles = []; + + const testStreams = []; + const shards = 5; + for (let i = 1; i <= shards; i++) { + const stream = run({ + files: shardsTestsFiles, + shard: { + total: shards, + index: i + } + }); + stream.on('test:fail', common.mustNotCall()); + stream.on('test:pass', (passedTest) => { + executedTestFiles.push(passedTest.file); + }); + testStreams.push(stream); + } + + await Promise.all(testStreams.map(async (stream) => { + // eslint-disable-next-line no-unused-vars + for await (const _ of stream) ; + })); + + assert.deepStrictEqual(executedTestFiles.sort(), [...shardsTestsFiles].sort()); + }); }); }); diff --git a/test/parallel/test-runner-watch-mode.mjs b/test/parallel/test-runner-watch-mode.mjs index 0a577140db3075..b0095f80e05a5d 100644 --- a/test/parallel/test-runner-watch-mode.mjs +++ b/test/parallel/test-runner-watch-mode.mjs @@ -18,7 +18,7 @@ tmpdir.refresh(); const fixtureContent = { 'dependency.js': 'module.exports = {};', 'dependency.mjs': 'export const a = 1;', - 'dependent.js': ` + 'test.js': ` const test = require('node:test'); require('./dependency.js'); import('./dependency.mjs'); @@ -30,12 +30,12 @@ const fixturePaths = Object.keys(fixtureContent) Object.entries(fixtureContent) .forEach(([file, content]) => writeFileSync(fixturePaths[file], content)); -async function testWatch({ fileToUpdate }) { +async function testWatch({ fileToUpdate, file }) { const ran1 = util.createDeferredPromise(); const ran2 = util.createDeferredPromise(); const child = spawn(process.execPath, - ['--watch', '--test', '--no-warnings', fixturePaths['dependent.js']], - { encoding: 'utf8', stdio: 'pipe' }); + ['--watch', '--test', file ? fixturePaths[file] : undefined].filter(Boolean), + { encoding: 'utf8', stdio: 'pipe', cwd: tmpdir.path }); let stdout = ''; child.stdout.on('data', (data) => { @@ -48,10 +48,7 @@ async function testWatch({ fileToUpdate }) { await ran1.promise; const content = fixtureContent[fileToUpdate]; const path = fixturePaths[fileToUpdate]; - const interval = setInterval(() => { - console.log(`Updating ${path}`); - writeFileSync(path, content); - }, 50); + const interval = setInterval(() => writeFileSync(path, content), common.platformTimeout(1000)); await ran2.promise; clearInterval(interval); child.kill(); @@ -59,14 +56,18 @@ async function testWatch({ fileToUpdate }) { describe('test runner watch mode', () => { it('should run tests repeatedly', async () => { - await testWatch({ fileToUpdate: 'dependent.js' }); + await testWatch({ file: 'test.js', fileToUpdate: 'test.js' }); }); it('should run tests with dependency repeatedly', async () => { - await testWatch({ fileToUpdate: 'dependency.js' }); + await testWatch({ file: 'test.js', fileToUpdate: 'dependency.js' }); }); it('should run tests with ESM dependency', async () => { - await testWatch({ fileToUpdate: 'dependency.mjs' }); + await testWatch({ file: 'test.js', fileToUpdate: 'dependency.mjs' }); + }); + + it('should support running tests without a file', async () => { + await testWatch({ fileToUpdate: 'test.js' }); }); }); diff --git a/test/parallel/test-single-executable-application.js b/test/parallel/test-single-executable-application.js index 01329ff2ae46a0..902093dc6e412d 100644 --- a/test/parallel/test-single-executable-application.js +++ b/test/parallel/test-single-executable-application.js @@ -16,6 +16,11 @@ if (!process.config.variables.single_executable_application) if (!['darwin', 'win32', 'linux'].includes(process.platform)) common.skip(`Unsupported platform ${process.platform}.`); +if (process.platform === 'linux' && process.config.variables.asan) { + // Source of the memory leak - https://github.com/nodejs/node/blob/da0bc6db98cef98686122ea1e2cd2dbd2f52d123/src/node_sea.cc#L94. + common.skip('Running the resultant binary fails because of a memory leak ASAN error.'); +} + if (process.platform === 'linux' && process.config.variables.is_debug === 1) common.skip('Running the resultant binary fails with `Couldn\'t read target executable"`.'); @@ -36,17 +41,16 @@ if (process.config.variables.want_separate_host_toolset !== 0) common.skip('Running the resultant binary fails with `Segmentation fault (core dumped)`.'); if (process.platform === 'linux') { - try { - const osReleaseText = readFileSync('/etc/os-release', { encoding: 'utf-8' }); - if (!/^NAME="Ubuntu"/m.test(osReleaseText)) { - throw new Error('Not Ubuntu.'); - } - } catch { - common.skip('Only supported Linux distribution is Ubuntu.'); + const osReleaseText = readFileSync('/etc/os-release', { encoding: 'utf-8' }); + const isAlpine = /^NAME="Alpine Linux"/m.test(osReleaseText); + if (isAlpine) common.skip('Alpine Linux is not supported.'); + + if (process.arch === 's390x') { + common.skip('On s390x, postject fails with `memory access out of bounds`.'); } - if (process.arch !== 'x64') { - common.skip(`Unsupported architecture for Linux - ${process.arch}.`); + if (process.arch === 'ppc64') { + common.skip('On ppc64, this test times out.'); } } diff --git a/test/parallel/test-stdio-pipe-stderr.js b/test/parallel/test-stdio-pipe-stderr.js index 9ec41b4159fdf6..1737424bb049fc 100644 --- a/test/parallel/test-stdio-pipe-stderr.js +++ b/test/parallel/test-stdio-pipe-stderr.js @@ -22,7 +22,7 @@ fs.writeFileSync(fakeModulePath, '', 'utf8'); stream.on('open', () => { spawnSync(process.execPath, { - input: `require("${fakeModulePath.replace(/\\/g, '/')}")`, + input: `require(${JSON.stringify(fakeModulePath)})`, stdio: ['pipe', 'pipe', stream] }); const stderr = fs.readFileSync(stderrOutputPath, 'utf8').trim(); diff --git a/test/parallel/test-stream-forEach.js b/test/parallel/test-stream-forEach.js index 7a21e299534742..627ea0ccf1be60 100644 --- a/test/parallel/test-stream-forEach.js +++ b/test/parallel/test-stream-forEach.js @@ -96,7 +96,7 @@ const { once } = require('events'); Readable.from([1, 2, 3, 4]).forEach(async (_, { signal }) => { calls++; await once(signal, 'abort'); - }, { signal: ac.signal, concurrency: 2 }); + }, { signal: ac.signal, concurrency: 2, highWaterMark: 0 }); // pump assert.rejects(async () => { await forEachPromise; diff --git a/test/parallel/test-stream-map.js b/test/parallel/test-stream-map.js index ba0571fe3a7b95..4a7a53c55960ea 100644 --- a/test/parallel/test-stream-map.js +++ b/test/parallel/test-stream-map.js @@ -8,6 +8,25 @@ const assert = require('assert'); const { once } = require('events'); const { setTimeout } = require('timers/promises'); +function createDependentPromises(n) { + const promiseAndResolveArray = []; + + for (let i = 0; i < n; i++) { + let res; + const promise = new Promise((resolve) => { + if (i === 0) { + res = resolve; + return; + } + res = () => promiseAndResolveArray[i - 1][0].then(resolve); + }); + + promiseAndResolveArray.push([promise, res]); + } + + return promiseAndResolveArray; +} + { // Map works on synchronous streams with a synchronous mapper const stream = Readable.from([1, 2, 3, 4, 5]).map((x) => x + x); @@ -143,7 +162,7 @@ const { setTimeout } = require('timers/promises'); const stream = range.map(common.mustCall(async (_, { signal }) => { await once(signal, 'abort'); throw signal.reason; - }, 2), { signal: ac.signal, concurrency: 2 }); + }, 2), { signal: ac.signal, concurrency: 2, highWaterMark: 0 }); // pump assert.rejects(async () => { for await (const item of stream) { @@ -173,12 +192,164 @@ const { setTimeout } = require('timers/promises'); })().then(common.mustCall()); } + +{ + // highWaterMark with small concurrency + const finishOrder = []; + + const promises = createDependentPromises(4); + + const raw = Readable.from([2, 0, 1, 3]); + const stream = raw.map(async (item) => { + const [promise, resolve] = promises[item]; + resolve(); + + await promise; + finishOrder.push(item); + return item; + }, { concurrency: 2 }); + + (async () => { + await stream.toArray(); + + assert.deepStrictEqual(finishOrder, [0, 1, 2, 3]); + })().then(common.mustCall(), common.mustNotCall()); +} + +{ + // highWaterMark with a lot of items and large concurrency + const finishOrder = []; + + const promises = createDependentPromises(20); + + const input = [10, 1, 0, 3, 4, 2, 5, 7, 8, 9, 6, 11, 12, 13, 18, 15, 16, 17, 14, 19]; + const raw = Readable.from(input); + // Should be + // 10, 1, 0, 3, 4, 2 | next: 0 + // 10, 1, 3, 4, 2, 5 | next: 1 + // 10, 3, 4, 2, 5, 7 | next: 2 + // 10, 3, 4, 5, 7, 8 | next: 3 + // 10, 4, 5, 7, 8, 9 | next: 4 + // 10, 5, 7, 8, 9, 6 | next: 5 + // 10, 7, 8, 9, 6, 11 | next: 6 + // 10, 7, 8, 9, 11, 12 | next: 7 + // 10, 8, 9, 11, 12, 13 | next: 8 + // 10, 9, 11, 12, 13, 18 | next: 9 + // 10, 11, 12, 13, 18, 15 | next: 10 + // 11, 12, 13, 18, 15, 16 | next: 11 + // 12, 13, 18, 15, 16, 17 | next: 12 + // 13, 18, 15, 16, 17, 14 | next: 13 + // 18, 15, 16, 17, 14, 19 | next: 14 + // 18, 15, 16, 17, 19 | next: 15 + // 18, 16, 17, 19 | next: 16 + // 18, 17, 19 | next: 17 + // 18, 19 | next: 18 + // 19 | next: 19 + // + + const stream = raw.map(async (item) => { + const [promise, resolve] = promises[item]; + resolve(); + + await promise; + finishOrder.push(item); + return item; + }, { concurrency: 6 }); + + (async () => { + const outputOrder = await stream.toArray(); + + assert.deepStrictEqual(outputOrder, input); + assert.deepStrictEqual(finishOrder, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]); + })().then(common.mustCall(), common.mustNotCall()); +} + +{ + // Custom highWaterMark with a lot of items and large concurrency + const finishOrder = []; + + const promises = createDependentPromises(20); + + const input = [11, 1, 0, 3, 4, 2, 5, 7, 8, 9, 6, 10, 12, 13, 18, 15, 16, 17, 14, 19]; + const raw = Readable.from(input); + // Should be + // 11, 1, 0, 3, 4 | next: 0, buffer: [] + // 11, 1, 3, 4, 2 | next: 1, buffer: [0] + // 11, 3, 4, 2, 5 | next: 2, buffer: [0, 1] + // 11, 3, 4, 5, 7 | next: 3, buffer: [0, 1, 2] + // 11, 4, 5, 7, 8 | next: 4, buffer: [0, 1, 2, 3] + // 11, 5, 7, 8, 9 | next: 5, buffer: [0, 1, 2, 3, 4] + // 11, 7, 8, 9, 6 | next: 6, buffer: [0, 1, 2, 3, 4, 5] + // 11, 7, 8, 9, 10 | next: 7, buffer: [0, 1, 2, 3, 4, 5, 6] -- buffer full + // 11, 8, 9, 10, 12 | next: 8, buffer: [0, 1, 2, 3, 4, 5, 6] + // 11, 9, 10, 12, 13 | next: 9, buffer: [0, 1, 2, 3, 4, 5, 6] + // 11, 10, 12, 13, 18 | next: 10, buffer: [0, 1, 2, 3, 4, 5, 6] + // 11, 12, 13, 18, 15 | next: 11, buffer: [0, 1, 2, 3, 4, 5, 6] + // 12, 13, 18, 15, 16 | next: 12, buffer: [] -- all items flushed as 11 is consumed and all the items wait for it + // 13, 18, 15, 16, 17 | next: 13, buffer: [] + // 18, 15, 16, 17, 14 | next: 14, buffer: [] + // 18, 15, 16, 17, 19 | next: 15, buffer: [14] + // 18, 16, 17, 19 | next: 16, buffer: [14, 15] + // 18, 17, 19 | next: 17, buffer: [14, 15, 16] + // 18, 19 | next: 18, buffer: [14, 15, 16, 17] + // 19 | next: 19, buffer: [] -- all items flushed + // + + const stream = raw.map(async (item) => { + const [promise, resolve] = promises[item]; + resolve(); + + await promise; + finishOrder.push(item); + return item; + }, { concurrency: 5, highWaterMark: 7 }); + + (async () => { + const outputOrder = await stream.toArray(); + + assert.deepStrictEqual(outputOrder, input); + assert.deepStrictEqual(finishOrder, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]); + })().then(common.mustCall(), common.mustNotCall()); +} + +{ + // Where there is a delay between the first and the next item it should not wait for filled queue + // before yielding to the user + const promises = createDependentPromises(3); + + const raw = Readable.from([0, 1, 2]); + + const stream = raw + .map(async (item) => { + if (item !== 0) { + await promises[item][0]; + } + + return item; + }, { concurrency: 2 }) + .map((item) => { + // eslint-disable-next-line no-unused-vars + for (const [_, resolve] of promises) { + resolve(); + } + + return item; + }); + + (async () => { + await stream.toArray(); + })().then(common.mustCall(), common.mustNotCall()); +} + { // Error cases assert.throws(() => Readable.from([1]).map(1), /ERR_INVALID_ARG_TYPE/); assert.throws(() => Readable.from([1]).map((x) => x, { concurrency: 'Foo' }), /ERR_OUT_OF_RANGE/); + assert.throws(() => Readable.from([1]).map((x) => x, { + concurrency: -1 + }), /ERR_OUT_OF_RANGE/); assert.throws(() => Readable.from([1]).map((x) => x, 1), /ERR_INVALID_ARG_TYPE/); assert.throws(() => Readable.from([1]).map((x) => x, { signal: true }), /ERR_INVALID_ARG_TYPE/); } diff --git a/test/parallel/test-tls-alert.js b/test/parallel/test-tls-alert.js index 31b07104c241a9..04000771aa977b 100644 --- a/test/parallel/test-tls-alert.js +++ b/test/parallel/test-tls-alert.js @@ -42,6 +42,7 @@ const server = tls.Server({ cert: loadPEM('agent2-cert') }, null).listen(0, common.mustCall(() => { const args = ['s_client', '-quiet', '-tls1_1', + '-cipher', (common.hasOpenSSL31 ? 'DEFAULT:@SECLEVEL=0' : 'DEFAULT'), '-connect', `127.0.0.1:${server.address().port}`]; execFile(common.opensslCli, args, common.mustCall((err, _, stderr) => { diff --git a/test/parallel/test-tls-alpn-server-client.js b/test/parallel/test-tls-alpn-server-client.js index 3da24c67fbe522..522dd34ad21567 100644 --- a/test/parallel/test-tls-alpn-server-client.js +++ b/test/parallel/test-tls-alpn-server-client.js @@ -40,9 +40,8 @@ function runTest(clientsOptions, serverOptions, cb) { opt.rejectUnauthorized = false; results[clientIndex] = {}; - const client = tls.connect(opt, function() { - results[clientIndex].client = { ALPN: client.alpnProtocol }; - client.end(); + + function startNextClient() { if (options.length) { clientIndex++; connectClient(options); @@ -52,6 +51,15 @@ function runTest(clientsOptions, serverOptions, cb) { cb(results); }); } + } + + const client = tls.connect(opt, function() { + results[clientIndex].client = { ALPN: client.alpnProtocol }; + client.end(); + startNextClient(); + }).on('error', function(err) { + results[clientIndex].client = { error: err }; + startNextClient(); }); } @@ -161,6 +169,67 @@ function Test4() { { server: { ALPN: false }, client: { ALPN: false } }); }); + + TestALPNCallback(); +} + +function TestALPNCallback() { + // Server always selects the client's 2nd preference: + const serverOptions = { + ALPNCallback: common.mustCall(({ protocols }) => { + return protocols[1]; + }, 2) + }; + + const clientsOptions = [{ + ALPNProtocols: ['a', 'b', 'c'], + }, { + ALPNProtocols: ['a'], + }]; + + runTest(clientsOptions, serverOptions, function(results) { + // Callback picks 2nd preference => picks 'b' + checkResults(results[0], + { server: { ALPN: 'b' }, + client: { ALPN: 'b' } }); + + // Callback picks 2nd preference => undefined => ALPN rejected: + assert.strictEqual(results[1].server, undefined); + assert.strictEqual(results[1].client.error.code, 'ECONNRESET'); + + TestBadALPNCallback(); + }); +} + +function TestBadALPNCallback() { + // Server always returns a fixed invalid value: + const serverOptions = { + ALPNCallback: common.mustCall(() => 'http/5') + }; + + const clientsOptions = [{ + ALPNProtocols: ['http/1', 'h2'], + }]; + + process.once('uncaughtException', common.mustCall((error) => { + assert.strictEqual(error.code, 'ERR_TLS_ALPN_CALLBACK_INVALID_RESULT'); + })); + + runTest(clientsOptions, serverOptions, function(results) { + // Callback returns 'http/5' => doesn't match client ALPN => error & reset + assert.strictEqual(results[0].server, undefined); + assert.strictEqual(results[0].client.error.code, 'ECONNRESET'); + + TestALPNOptionsCallback(); + }); +} + +function TestALPNOptionsCallback() { + // Server sets two incompatible ALPN options: + assert.throws(() => tls.createServer({ + ALPNCallback: () => 'a', + ALPNProtocols: ['b', 'c'] + }), (error) => error.code === 'ERR_TLS_ALPN_CALLBACK_WITH_PROTOCOLS'); } Test1(); diff --git a/test/parallel/test-tls-getprotocol.js b/test/parallel/test-tls-getprotocol.js index d45287d671d8af..7da2f60676d00e 100644 --- a/test/parallel/test-tls-getprotocol.js +++ b/test/parallel/test-tls-getprotocol.js @@ -11,9 +11,18 @@ const tls = require('tls'); const fixtures = require('../common/fixtures'); const clientConfigs = [ - { secureProtocol: 'TLSv1_method', version: 'TLSv1' }, - { secureProtocol: 'TLSv1_1_method', version: 'TLSv1.1' }, - { secureProtocol: 'TLSv1_2_method', version: 'TLSv1.2' }, + { + secureProtocol: 'TLSv1_method', + version: 'TLSv1', + ciphers: (common.hasOpenSSL31 ? 'DEFAULT:@SECLEVEL=0' : 'DEFAULT') + }, { + secureProtocol: 'TLSv1_1_method', + version: 'TLSv1.1', + ciphers: (common.hasOpenSSL31 ? 'DEFAULT:@SECLEVEL=0' : 'DEFAULT') + }, { + secureProtocol: 'TLSv1_2_method', + version: 'TLSv1.2' + }, ]; const serverConfig = { @@ -30,6 +39,7 @@ const server = tls.createServer(serverConfig, common.mustCall(clientConfigs.leng tls.connect({ host: common.localhostIPv4, port: server.address().port, + ciphers: v.ciphers, rejectUnauthorized: false, secureProtocol: v.secureProtocol }, common.mustCall(function() { diff --git a/test/parallel/test-tls-min-max-version.js b/test/parallel/test-tls-min-max-version.js index 5cea41ca7e0bd6..ab351558a4c8b3 100644 --- a/test/parallel/test-tls-min-max-version.js +++ b/test/parallel/test-tls-min-max-version.js @@ -22,6 +22,9 @@ function test(cmin, cmax, cprot, smin, smax, sprot, proto, cerr, serr) { if (serr !== 'ERR_SSL_UNSUPPORTED_PROTOCOL') ciphers = 'ALL@SECLEVEL=0'; } + if (common.hasOpenSSL31 && cerr === 'ERR_SSL_TLSV1_ALERT_PROTOCOL_VERSION') { + ciphers = 'DEFAULT@SECLEVEL=0'; + } // Report where test was called from. Strip leading garbage from // at Object. (file:line) // from the stack location, we only want the file:line part. diff --git a/test/parallel/test-tls-session-cache.js b/test/parallel/test-tls-session-cache.js index c4bebff2e32085..e4ecb53282fbae 100644 --- a/test/parallel/test-tls-session-cache.js +++ b/test/parallel/test-tls-session-cache.js @@ -100,6 +100,7 @@ function doTest(testOptions, callback) { const args = [ 's_client', '-tls1', + '-cipher', (common.hasOpenSSL31 ? 'DEFAULT:@SECLEVEL=0' : 'DEFAULT'), '-connect', `localhost:${this.address().port}`, '-servername', 'ohgod', '-key', fixtures.path('keys/rsa_private.pem'), diff --git a/test/parallel/test-trace-events-worker-metadata-with-name.js b/test/parallel/test-trace-events-worker-metadata-with-name.js index 6c3a44f9566d9c..bf6e1005aa458f 100644 --- a/test/parallel/test-trace-events-worker-metadata-with-name.js +++ b/test/parallel/test-trace-events-worker-metadata-with-name.js @@ -7,7 +7,7 @@ const { isMainThread } = require('worker_threads'); if (isMainThread) { const CODE = 'const { Worker } = require(\'worker_threads\'); ' + - `new Worker('${__filename.replace(/\\/g, '/')}', { name: 'foo' })`; + `new Worker(${JSON.stringify(__filename)}, { name: 'foo' })`; const FILE_NAME = 'node_trace.1.log'; const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); diff --git a/test/parallel/test-trace-events-worker-metadata.js b/test/parallel/test-trace-events-worker-metadata.js index 8b4d0be9c60713..6a8702ccadbc7b 100644 --- a/test/parallel/test-trace-events-worker-metadata.js +++ b/test/parallel/test-trace-events-worker-metadata.js @@ -7,7 +7,7 @@ const { isMainThread } = require('worker_threads'); if (isMainThread) { const CODE = 'const { Worker } = require(\'worker_threads\'); ' + - `new Worker('${__filename.replace(/\\/g, '/')}')`; + `new Worker(${JSON.stringify(__filename)})`; const FILE_NAME = 'node_trace.1.log'; const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); diff --git a/test/parallel/test-url-canParse-whatwg.js b/test/parallel/test-url-canParse-whatwg.js new file mode 100644 index 00000000000000..7f7d5d40aa7a28 --- /dev/null +++ b/test/parallel/test-url-canParse-whatwg.js @@ -0,0 +1,12 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); + +// One argument is required +assert.throws(() => { + URL.canParse(); +}, { + code: 'ERR_MISSING_ARGS', + name: 'TypeError', +}); diff --git a/test/parallel/test-url-format-whatwg.js b/test/parallel/test-url-format-whatwg.js index d1f0e0bcbddec2..bf9f8eaac63246 100644 --- a/test/parallel/test-url-format-whatwg.js +++ b/test/parallel/test-url-format-whatwg.js @@ -140,3 +140,8 @@ assert.strictEqual( url.format(new URL('http://user:pass@xn--0zwm56d.com:8080/path'), { unicode: true }), 'http://user:pass@测试.com:8080/path' ); + +assert.strictEqual( + url.format(new URL('tel:123')), + url.format(new URL('tel:123'), { unicode: true }) +); diff --git a/test/parallel/test-url-is-url.js b/test/parallel/test-url-is-url.js new file mode 100644 index 00000000000000..6bb8a1595df2a0 --- /dev/null +++ b/test/parallel/test-url-is-url.js @@ -0,0 +1,16 @@ +// Flags: --expose-internals +'use strict'; + +require('../common'); + +const { URL, parse } = require('url'); +const assert = require('assert'); +const { isURL } = require('internal/url'); + +assert.strictEqual(isURL(new URL('https://www.nodejs.org')), true); +assert.strictEqual(isURL(parse('https://www.nodejs.org')), false); +assert.strictEqual(isURL({ + href: 'https://www.nodejs.org', + protocol: 'https:', + path: '/', +}), false); diff --git a/test/parallel/test-url-pathtofileurl.js b/test/parallel/test-url-pathtofileurl.js index 068a04e6613b28..d18b5a41fdfc2f 100644 --- a/test/parallel/test-url-pathtofileurl.js +++ b/test/parallel/test-url-pathtofileurl.js @@ -29,13 +29,30 @@ const url = require('url'); // Missing server: assert.throws(() => url.pathToFileURL('\\\\\\no-server'), { - code: 'ERR_INVALID_ARG_VALUE' + code: 'ERR_INVALID_ARG_VALUE', }); // Missing share or resource: assert.throws(() => url.pathToFileURL('\\\\host'), { - code: 'ERR_INVALID_ARG_VALUE' + code: 'ERR_INVALID_ARG_VALUE', }); + + // Regression test for direct String.prototype.startsWith call + assert.throws(() => url.pathToFileURL([ + '\\\\', + { [Symbol.toPrimitive]: () => 'blep\\blop' }, + ]), { + code: 'ERR_INVALID_ARG_TYPE', + }); + assert.throws(() => url.pathToFileURL(['\\\\', 'blep\\blop']), { + code: 'ERR_INVALID_ARG_TYPE', + }); + assert.throws(() => url.pathToFileURL({ + [Symbol.toPrimitive]: () => '\\\\blep\\blop', + }), { + code: 'ERR_INVALID_ARG_TYPE', + }); + } else { // UNC paths on posix are considered a single path that has backslashes: const fileURL = url.pathToFileURL('\\\\nas\\share\\path.txt').href; @@ -144,3 +161,19 @@ const url = require('url'); assert.strictEqual(actual, expected); } } + +// Test for non-string parameter +{ + for (const badPath of [ + undefined, null, true, 42, 42n, Symbol('42'), NaN, {}, [], () => {}, + Promise.resolve('foo'), + new Date(), + new String('notPrimitive'), + { toString() { return 'amObject'; } }, + { [Symbol.toPrimitive]: (hint) => 'amObject' }, + ]) { + assert.throws(() => url.pathToFileURL(badPath), { + code: 'ERR_INVALID_ARG_TYPE', + }); + } +} diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index 9b57fd4a99b10e..b64d6531abd02c 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -2829,7 +2829,7 @@ assert.strictEqual( ' at Function.Module._load (node:internal/modules/cjs/loader:621:3)', // This file is not an actual Node.js core file. ' at Module.require [as weird/name] (node:internal/aaaaa/loader:735:19)', - ' at require (node:internal/modules/cjs/helpers:14:16)', + ' at require (node:internal/modules/helpers:14:16)', ' at Array.forEach ()', ` at ${process.cwd()}/test/parallel/test-util-inspect.js:2760:12`, ` at Object. (${process.cwd()}/node_modules/hyper_module/folder/file.js:2753:10)`, diff --git a/test/parallel/test-v8-serialize-leak.js b/test/parallel/test-v8-serialize-leak.js index 696dbfea65ba95..89b36c4a248dd4 100644 --- a/test/parallel/test-v8-serialize-leak.js +++ b/test/parallel/test-v8-serialize-leak.js @@ -8,7 +8,6 @@ if (common.isIBMi) common.skip('On IBMi, the rss memory always returns zero'); const v8 = require('v8'); -const assert = require('assert'); const before = process.memoryUsage.rss(); @@ -16,14 +15,19 @@ for (let i = 0; i < 1000000; i++) { v8.serialize(''); } -global.gc(); - -const after = process.memoryUsage.rss(); - -if (process.config.variables.asan) { - assert(after < before * 10, `asan: before=${before} after=${after}`); -} else if (process.config.variables.node_builtin_modules_path) { - assert(after < before * 4, `node_builtin_modules_path: before=${before} after=${after}`); -} else { - assert(after < before * 2, `before=${before} after=${after}`); +async function main() { + await common.gcUntil('RSS should go down', () => { + const after = process.memoryUsage.rss(); + if (process.config.variables.asan) { + console.log(`asan: before=${before} after=${after}`); + return after < before * 10; + } else if (process.config.variables.node_builtin_modules_path) { + console.log(`node_builtin_modules_path: before=${before} after=${after}`); + return after < before * 10; + } + console.log(`before=${before} after=${after}`); + return after < before * 10; + }); } + +main(); diff --git a/test/parallel/test-vm-module-dynamic-import.js b/test/parallel/test-vm-module-dynamic-import.js index cd318511401412..5bca08b8c9c3bb 100644 --- a/test/parallel/test-vm-module-dynamic-import.js +++ b/test/parallel/test-vm-module-dynamic-import.js @@ -59,10 +59,10 @@ async function test() { { const s = new Script('import("foo", { assert: { key: "value" } })', { - importModuleDynamically: common.mustCall((specifier, wrap, assertion) => { + importModuleDynamically: common.mustCall((specifier, wrap, attributes) => { assert.strictEqual(specifier, 'foo'); assert.strictEqual(wrap, s); - assert.deepStrictEqual(assertion, { __proto__: null, key: 'value' }); + assert.deepStrictEqual(attributes, { __proto__: null, key: 'value' }); return foo; }), }); diff --git a/test/parallel/test-vm-module-link.js b/test/parallel/test-vm-module-link.js index 16694d5d846075..1edd6a0ba01bb5 100644 --- a/test/parallel/test-vm-module-link.js +++ b/test/parallel/test-vm-module-link.js @@ -131,7 +131,9 @@ async function asserts() { await m.link((s, r, p) => { assert.strictEqual(s, 'foo'); assert.strictEqual(r.identifier, 'm'); + assert.strictEqual(p.attributes.n1, 'v1'); assert.strictEqual(p.assert.n1, 'v1'); + assert.strictEqual(p.attributes.n2, 'v2'); assert.strictEqual(p.assert.n2, 'v2'); return new SourceTextModule(''); }); diff --git a/test/parallel/test-watch-mode-files_watcher.mjs b/test/parallel/test-watch-mode-files_watcher.mjs index 19f71a04e40df8..a059eb30dc63d9 100644 --- a/test/parallel/test-watch-mode-files_watcher.mjs +++ b/test/parallel/test-watch-mode-files_watcher.mjs @@ -26,7 +26,7 @@ describe('watch mode file watcher', () => { beforeEach(() => { changesCount = 0; - watcher = new FilesWatcher({ throttle: 100 }); + watcher = new FilesWatcher({ debounce: 100 }); watcher.on('changed', () => changesCount++); }); @@ -51,7 +51,7 @@ describe('watch mode file watcher', () => { assert.strictEqual(changesCount, 1); }); - it('should throttle changes', async () => { + it('should debounce changes', async () => { const file = path.join(tmpdir.path, 'file2'); writeFileSync(file, 'written'); watcher.filterFile(file); @@ -61,7 +61,7 @@ describe('watch mode file watcher', () => { writeFileSync(file, '2'); writeFileSync(file, '3'); writeFileSync(file, '4'); - await setTimeout(200); // throttle * 2 + await setTimeout(200); // debounce * 2 writeFileSync(file, '5'); const changed = once(watcher, 'changed'); writeFileSync(file, 'after'); @@ -86,8 +86,8 @@ describe('watch mode file watcher', () => { await writeAndWaitForChanges(watcher, file); writeFileSync(file, '1'); + assert.strictEqual(changesCount, 1); - await setTimeout(200); // avoid throttling watcher.clearFileFilters(); writeFileSync(file, '2'); // Wait for this long to make sure changes are triggered only once @@ -97,7 +97,7 @@ describe('watch mode file watcher', () => { it('should watch all files in watched path when in "all" mode', { skip: !supportsRecursiveWatching }, async () => { - watcher = new FilesWatcher({ throttle: 100, mode: 'all' }); + watcher = new FilesWatcher({ debounce: 100, mode: 'all' }); watcher.on('changed', () => changesCount++); const file = path.join(tmpdir.path, 'file5'); diff --git a/test/parallel/test-webcrypto-export-import-ec.js b/test/parallel/test-webcrypto-export-import-ec.js index e18514800f5059..1e9edb9d6a8a6d 100644 --- a/test/parallel/test-webcrypto-export-import-ec.js +++ b/test/parallel/test-webcrypto-export-import-ec.js @@ -400,15 +400,81 @@ async function testImportRaw({ name, publicUsages }, namedCurve) { ['ECDSA', ['verify'], ['sign']], ['ECDH', [], ['deriveBits', 'deriveBits']], ]) { - assert.rejects(subtle.importKey( - 'spki', - rsaPublic.export({ format: 'der', type: 'spki' }), - { name, hash: 'SHA-256', namedCurve: 'P-256' }, - true, publicUsages), { message: /Invalid key type/ }); - assert.rejects(subtle.importKey( - 'pkcs8', - rsaPrivate.export({ format: 'der', type: 'pkcs8' }), - { name, hash: 'SHA-256', namedCurve: 'P-256' }, - true, privateUsages), { message: /Invalid key type/ }); + assert.rejects( + subtle.importKey( + 'spki', + rsaPublic.export({ format: 'der', type: 'spki' }), + { name, hash: 'SHA-256', namedCurve: 'P-256' }, + true, publicUsages), { message: /Invalid key type/ }, + ).then(common.mustCall()); + assert.rejects( + subtle.importKey( + 'pkcs8', + rsaPrivate.export({ format: 'der', type: 'pkcs8' }), + { name, hash: 'SHA-256', namedCurve: 'P-256' }, + true, privateUsages), { message: /Invalid key type/ }, + ).then(common.mustCall()); + } +} + +// Bad private keys +{ + for (const { namedCurve, key: pkcs8 } of [ + // The private key is exactly equal to the order, and the public key is + // private key * order. + { + namedCurve: 'P-256', + key: Buffer.from( + '3066020100301306072a8648ce3d020106082a8648ce3d030107044c304a0201' + + '010420ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc' + + '632551a12303210000ffffff00000000ffffffffffffffffbce6faada7179e84' + + 'f3b9cac2fc632551', 'hex'), + }, + // The private key is exactly equal to the order, and the public key is + // omitted. + { + namedCurve: 'P-256', + key: Buffer.from( + '3041020100301306072a8648ce3d020106082a8648ce3d030107042730250201' + + '010420ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc' + + '632551', 'hex'), + }, + // The private key is exactly equal to the order + 11, and the public key is + // private key * order. + { + namedCurve: 'P-521', + key: Buffer.from( + '3081ee020100301006072a8648ce3d020106052b810400230481d63081d30201' + + '01044201ffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + + 'fffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb7' + + '1e91386414a181890381860004008a75841259fdedff546f1a39573b4315cfed' + + '5dc7ed7c17849543ef2c54f2991652f3dbc5332663da1bd19b1aebe319108501' + + '5c024fa4c9a902ecc0e02dda0cdb9a0096fb303fcbba2129849d0ca877054fb2' + + '293add566210bd0493ed2e95d4e0b9b82b1bc8a90e8b42a4ab3892331914a953' + + '36dcac80e3f4819b5d58874f92ce48c808', 'hex'), + }, + // The private key is exactly equal to the order + 11, and the public key is + // omitted. + { + namedCurve: 'P-521', + key: Buffer.from( + '3060020100301006072a8648ce3d020106052b81040023044930470201010442' + + '01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + + 'fffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e9138' + + '6414', 'hex'), + }, + ]) { + for (const [name, privateUsages] of [ + ['ECDSA', ['sign']], + ['ECDH', ['deriveBits', 'deriveBits']], + ]) { + assert.rejects( + subtle.importKey( + 'pkcs8', + pkcs8, + { name, hash: 'SHA-256', namedCurve }, + true, privateUsages), { name: 'DataError', message: /Invalid keyData/ }, + ).then(common.mustCall()); + } } } diff --git a/test/parallel/test-whatwg-readablebytestreambyob.js b/test/parallel/test-whatwg-readablebytestreambyob.js new file mode 100644 index 00000000000000..5dbe4813dbc4f6 --- /dev/null +++ b/test/parallel/test-whatwg-readablebytestreambyob.js @@ -0,0 +1,62 @@ +'use strict'; + +const common = require('../common'); + +const { + open, +} = require('fs/promises'); + +const { + Buffer, +} = require('buffer'); + +class Source { + async start(controller) { + this.file = await open(__filename); + this.controller = controller; + } + + async pull(controller) { + const byobRequest = controller.byobRequest; + const view = byobRequest.view; + + const { + bytesRead, + } = await this.file.read({ + buffer: view, + offset: view.byteOffset, + length: view.byteLength + }); + + if (bytesRead === 0) { + await this.file.close(); + this.controller.close(); + } + + byobRequest.respond(bytesRead); + } + + get type() { return 'bytes'; } + + get autoAllocateChunkSize() { return 1024; } +} + +(async () => { + const source = new Source(); + const stream = new ReadableStream(source); + + const { emitWarning } = process; + + process.emitWarning = common.mustNotCall(); + + try { + const reader = stream.getReader({ mode: 'byob' }); + + let result; + do { + result = await reader.read(Buffer.alloc(100)); + } while (!result.done); + } finally { + process.emitWarning = emitWarning; + } +})().then(common.mustCall()); diff --git a/test/parallel/test-whatwg-url-custom-parsing.js b/test/parallel/test-whatwg-url-custom-parsing.js index a3532374ca684e..905028fee3812c 100644 --- a/test/parallel/test-whatwg-url-custom-parsing.js +++ b/test/parallel/test-whatwg-url-custom-parsing.js @@ -78,3 +78,10 @@ for (const test of additional_tests) { if (test.search) assert.strictEqual(url.search, test.search); if (test.hash) assert.strictEqual(url.hash, test.hash); } + +assert.throws(() => { + new URL(); +}, { + name: 'TypeError', + code: 'ERR_MISSING_ARGS', +}); diff --git a/test/parallel/test-worker-message-channel.js b/test/parallel/test-worker-message-channel.js index 8f66ef87e6e3d4..1d7550753932e7 100644 --- a/test/parallel/test-worker-message-channel.js +++ b/test/parallel/test-worker-message-channel.js @@ -3,6 +3,9 @@ const common = require('../common'); const assert = require('assert'); const { MessageChannel, MessagePort, Worker } = require('worker_threads'); +// Asserts that freezing the EventTarget prototype does not make the internal throw. +Object.freeze(EventTarget.prototype); + { const channel = new MessageChannel(); diff --git a/test/pummel/pummel.status b/test/pummel/pummel.status index 143450986e46c4..589647bcb741fa 100644 --- a/test/pummel/pummel.status +++ b/test/pummel/pummel.status @@ -9,6 +9,8 @@ prefix pummel [$system==win32] # https://github.com/nodejs/node/issues/40728 test-fs-watch-non-recursive: PASS,FLAKY +# https://github.com/nodejs/node/issues/50260 +test-structuredclone-jstransferable: PASS,FLAKY [$system==linux] # https://github.com/nodejs/node/issues/38226 @@ -29,3 +31,7 @@ test-heapsnapshot-near-heap-limit: PASS,FLAKY [$system==ibmi] # https://github.com/nodejs/node/issues/39683 test-regress-GH-892: PASS, FLAKY + +[$arch==s390x] +# https://github.com/nodejs/node/issues/38226 +test-crypto-timing-safe-equal-benchmarks: PASS,FLAKY diff --git a/test/pummel/test-heapdump-fs-promise.js b/test/pummel/test-heapdump-fs-promise.js index 62defa2df7820b..10ee087ae7fc23 100644 --- a/test/pummel/test-heapdump-fs-promise.js +++ b/test/pummel/test-heapdump-fs-promise.js @@ -10,7 +10,7 @@ validateSnapshotNodes('Node / FSReqPromise', [ { children: [ { node_name: 'FSReqPromise', edge_name: 'native_to_javascript' }, - { node_name: 'Float64Array', edge_name: 'stats_field_array' }, + { node_name: 'Node / AliasedFloat64Array', edge_name: 'stats_field_array' }, ], }, ]); diff --git a/test/sequential/sequential.status b/test/sequential/sequential.status index 0688f5b05e789c..0cfd67fc86c190 100644 --- a/test/sequential/sequential.status +++ b/test/sequential/sequential.status @@ -15,10 +15,6 @@ test-watch-mode-inspect: PASS, FLAKY # https://github.com/nodejs/node/issues/47116 test-http-max-sockets: PASS, FLAKY -[$system==win32 || $system==freebsd] -# https://github.com/nodejs/node/issues/49564 -test-http-regr-gh-2928: PASS, FLAKY - [$system==linux] [$system==macos] @@ -41,6 +37,8 @@ test-tls-psk-client: PASS, FLAKY test-tls-securepair-client: PASS, FLAKY [$arch==arm] +# https://github.com/nodejs/node/issues/49933 +test-watch-mode-inspect: PASS, FLAKY [$arch==s390x] # https://github.com/nodejs/node/issues/41286 diff --git a/test/sequential/test-fs-readdir-recursive.js b/test/sequential/test-fs-readdir-recursive.js index 3ced1434f303b7..1bb69f203ea526 100644 --- a/test/sequential/test-fs-readdir-recursive.js +++ b/test/sequential/test-fs-readdir-recursive.js @@ -131,9 +131,11 @@ function getDirentPath(dirent) { } function assertDirents(dirents) { + assert.strictEqual(dirents.length, expected.length); dirents.sort((a, b) => (getDirentPath(a) < getDirentPath(b) ? -1 : 1)); for (const [i, dirent] of dirents.entries()) { assert(dirent instanceof fs.Dirent); + assert.notStrictEqual(dirent.name, undefined); assert.strictEqual(getDirentPath(dirent), expected[i]); } } diff --git a/test/sequential/test-perf-hooks.js b/test/sequential/test-perf-hooks.js index d0ee0f5aad04c8..5ed9ff22ce2d38 100644 --- a/test/sequential/test-perf-hooks.js +++ b/test/sequential/test-perf-hooks.js @@ -1,84 +1,165 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); const { performance } = require('perf_hooks'); +// Get the start time as soon as possible. +const testStartTime = performance.now(); +const assert = require('assert'); +const { writeSync } = require('fs'); -if (!common.isMainThread) - common.skip('bootstrapping workers works differently'); +// Use writeSync to stdout to avoid disturbing the loop. +function log(str) { + writeSync(1, str + '\n'); +} assert(performance); assert(performance.nodeTiming); assert.strictEqual(typeof performance.timeOrigin, 'number'); + +assert(testStartTime > 0, `${testStartTime} <= 0`); // Use a fairly large epsilon value, since we can only guarantee that the node // process started up in 15 seconds. -assert(Math.abs(performance.timeOrigin - Date.now()) < 15000); +assert(testStartTime < 15000, `${testStartTime} >= 15000`); -const inited = performance.now(); -assert(inited < 15000); +// Use different ways to calculate process uptime to check that +// performance.timeOrigin and performance.now() are in reasonable range. +const epsilon = 50; +{ + const uptime1 = Date.now() - performance.timeOrigin; + const uptime2 = performance.now(); + const uptime3 = process.uptime() * 1000; + assert(Math.abs(uptime1 - uptime2) < epsilon, + `Date.now() - performance.timeOrigin (${uptime1}) - ` + + `performance.now() (${uptime2}) = ` + + `${uptime1 - uptime2} >= +- ${epsilon}`); + assert(Math.abs(uptime1 - uptime3) < epsilon, + `Date.now() - performance.timeOrigin (${uptime1}) - ` + + `process.uptime() * 1000 (${uptime3}) = ` + + `${uptime1 - uptime3} >= +- ${epsilon}`); +} assert.strictEqual(performance.nodeTiming.name, 'node'); assert.strictEqual(performance.nodeTiming.entryType, 'node'); -const delay = 250; -function checkNodeTiming(props) { - console.log(props); - - for (const prop of Object.keys(props)) { - if (props[prop].around !== undefined) { - assert.strictEqual(typeof performance.nodeTiming[prop], 'number'); - const delta = performance.nodeTiming[prop] - props[prop].around; - assert( - Math.abs(delta) < (props[prop].delay || delay), - `${prop}: ${Math.abs(delta)} >= ${props[prop].delay || delay}` - ); - } else { - assert.strictEqual(performance.nodeTiming[prop], props[prop], - `mismatch for performance property ${prop}: ` + - `${performance.nodeTiming[prop]} vs ${props[prop]}`); - } - } +// Copy all the values from the getters. +const initialTiming = { ...performance.nodeTiming }; + +{ + const { + startTime, + nodeStart, + v8Start, + environment, + bootstrapComplete, + } = initialTiming; + + assert.strictEqual(startTime, 0); + assert.strictEqual(typeof nodeStart, 'number'); + assert(nodeStart > 0, `nodeStart ${nodeStart} <= 0`); + // The whole process starts before this test starts. + assert(nodeStart < testStartTime, + `nodeStart ${nodeStart} >= ${testStartTime}`); + + assert.strictEqual(typeof v8Start, 'number'); + assert(v8Start > 0, `v8Start ${v8Start} <= 0`); + // V8 starts after the process starts. + assert(v8Start > nodeStart, `v8Start ${v8Start} <= ${nodeStart}`); + // V8 starts before this test starts. + assert(v8Start < testStartTime, + `v8Start ${v8Start} >= ${testStartTime}`); + + assert.strictEqual(typeof environment, 'number'); + assert(environment > 0, `environment ${environment} <= 0`); + // Environment starts after V8 starts. + assert(environment > v8Start, + `environment ${environment} <= ${v8Start}`); + // Environment starts before this test starts. + assert(environment < testStartTime, + `environment ${environment} >= ${testStartTime}`); + + assert.strictEqual(typeof bootstrapComplete, 'number'); + assert(bootstrapComplete > 0, `bootstrapComplete ${bootstrapComplete} <= 0`); + // Bootstrap completes after environment starts. + assert(bootstrapComplete > environment, + `bootstrapComplete ${bootstrapComplete} <= ${environment}`); + // Bootstrap completes before this test starts. + assert(bootstrapComplete < testStartTime, + `bootstrapComplete ${bootstrapComplete} >= ${testStartTime}`); } -checkNodeTiming({ - name: 'node', - entryType: 'node', - startTime: 0, - duration: { around: performance.now() }, - nodeStart: { around: 0 }, - v8Start: { around: 0 }, - bootstrapComplete: { around: inited, delay: 2500 }, - environment: { around: 0 }, - loopStart: -1, - loopExit: -1 -}); +function checkNodeTiming(timing) { + // Calculate the difference between now() and duration as soon as possible. + const now = performance.now(); + const delta = Math.abs(now - timing.duration); + + log(JSON.stringify(timing, null, 2)); + // Check that the properties are still reasonable. + assert.strictEqual(timing.name, 'node'); + assert.strictEqual(timing.entryType, 'node'); + + // Check that duration is positive and practically the same as + // performance.now() i.e. measures Node.js instance up time. + assert.strictEqual(typeof timing.duration, 'number'); + assert(timing.duration > 0, `timing.duration ${timing.duration} <= 0`); + assert(delta < 10, + `now (${now}) - timing.duration (${timing.duration}) = ${delta} >= 10`); + + // Check that the following fields do not change. + assert.strictEqual(timing.startTime, initialTiming.startTime); + assert.strictEqual(timing.nodeStart, initialTiming.nodeStart); + assert.strictEqual(timing.v8Start, initialTiming.v8Start); + assert.strictEqual(timing.environment, initialTiming.environment); + assert.strictEqual(timing.bootstrapComplete, initialTiming.bootstrapComplete); + + assert.strictEqual(typeof timing.loopStart, 'number'); + assert.strictEqual(typeof timing.loopExit, 'number'); +} + +log('check initial nodeTiming'); +checkNodeTiming(initialTiming); +assert.strictEqual(initialTiming.loopExit, -1); -setTimeout(() => { - checkNodeTiming({ - name: 'node', - entryType: 'node', - startTime: 0, - duration: { around: performance.now() }, - nodeStart: { around: 0 }, - v8Start: { around: 0 }, - bootstrapComplete: { around: inited, delay: 2500 }, - environment: { around: 0 }, - loopStart: { around: inited, delay: 2500 }, - loopExit: -1 - }); -}, 1000); +function checkValue(timing, name, min, max) { + const value = timing[name]; + assert(value > 0, `${name} ${value} <= 0`); + // Loop starts after bootstrap completes. + assert(value > min, + `${name} ${value} <= ${min}`); + assert(value < max, `${name} ${value} >= ${max}`); +} + +let loopStart = initialTiming.loopStart; +if (common.isMainThread) { + // In the main thread, the loop does not start until we start an operation + // that requires it, e.g. setTimeout(). + assert.strictEqual(initialTiming.loopStart, -1); + log('Start timer'); + setTimeout(() => { + log('Check nodeTiming in timer'); + const timing = { ...performance.nodeTiming }; + checkNodeTiming(timing); + // Loop should start after we fire the timeout, and before we call + // performance.now() here. + loopStart = timing.loopStart; + checkValue(timing, 'loopStart', initialTiming.duration, performance.now()); + }, 1000); +} else { + // In the worker, the loop always starts before the user code is evaluated, + // and after bootstrap completes. + checkValue(initialTiming, + 'loopStart', + initialTiming.bootstrapComplete, + testStartTime); +} process.on('exit', () => { - checkNodeTiming({ - name: 'node', - entryType: 'node', - startTime: 0, - duration: { around: performance.now() }, - nodeStart: { around: 0 }, - v8Start: { around: 0 }, - bootstrapComplete: { around: inited, delay: 2500 }, - environment: { around: 0 }, - loopStart: { around: inited, delay: 2500 }, - loopExit: { around: performance.now() } - }); + log('Check nodeTiming in process exit event'); + const timing = { ...performance.nodeTiming }; + checkNodeTiming(timing); + // Check that loopStart does not change. + assert.strictEqual(timing.loopStart, loopStart); + checkValue(timing, + 'loopExit', + loopStart, + performance.now()); }); diff --git a/test/sequential/test-watch-mode.mjs b/test/sequential/test-watch-mode.mjs index 610391863e6de0..383e15e73dd3e1 100644 --- a/test/sequential/test-watch-mode.mjs +++ b/test/sequential/test-watch-mode.mjs @@ -7,6 +7,7 @@ import { describe, it } from 'node:test'; import { spawn } from 'node:child_process'; import { writeFileSync, readFileSync, mkdirSync } from 'node:fs'; import { inspect } from 'node:util'; +import { pathToFileURL } from 'node:url'; import { createInterface } from 'node:readline'; if (common.isIBMi) @@ -188,7 +189,7 @@ console.log("don't show me");`); it('should watch changes to dependencies - cjs', async () => { const dependency = createTmpFile('module.exports = {};'); const file = createTmpFile(` -const dependency = require('${dependency.replace(/\\/g, '/')}'); +const dependency = require(${JSON.stringify(dependency)}); console.log(dependency); `); const { stderr, stdout } = await runWriteSucceed({ file, watchedFile: dependency }); @@ -206,7 +207,7 @@ console.log(dependency); it('should watch changes to dependencies - esm', async () => { const dependency = createTmpFile('module.exports = {};'); const file = createTmpFile(` -import dependency from 'file://${dependency.replace(/\\/g, '/')}'; +import dependency from ${JSON.stringify(pathToFileURL(dependency))}; console.log(dependency); `, '.mjs'); const { stderr, stdout } = await runWriteSucceed({ file, watchedFile: dependency }); @@ -278,7 +279,7 @@ console.log(values.random); skip: 'enable once --import is backported', }, async () => { const file = createTmpFile(); - const imported = `file://${createTmpFile('setImmediate(() => process.exit(0));')}`; + const imported = pathToFileURL(createTmpFile('setImmediate(() => process.exit(0));')); const args = ['--import', imported, file]; const { stderr, stdout } = await runWriteSucceed({ file, watchedFile: file, args }); @@ -320,9 +321,9 @@ console.log(values.random); it('should watch changes to previously missing ESM dependency', { skip: !supportsRecursive }, async () => { - const dependency = path.join(tmpdir.path, `${tmpFiles++}.mjs`); - const relativeDependencyPath = `./${path.basename(dependency)}`; - const dependant = createTmpFile(`import '${relativeDependencyPath}'`, '.mjs'); + const relativeDependencyPath = `./${tmpFiles++}.mjs`; + const dependency = path.join(tmpdir.path, relativeDependencyPath); + const dependant = createTmpFile(`import ${JSON.stringify(relativeDependencyPath)}`, '.mjs'); await failWriteSucceed({ file: dependant, watchedFile: dependency }); }); diff --git a/test/wasi/c/sock.c b/test/wasi/c/sock.c index de4a3ccc5f95a6..d11e86c805784d 100644 --- a/test/wasi/c/sock.c +++ b/test/wasi/c/sock.c @@ -9,9 +9,9 @@ int main(void) { int fd = 0 ; socklen_t addrlen = 0; int flags = 0; - int ret = accept(0, NULL, &addrlen); + int ret = accept(10, NULL, &addrlen); assert(ret == -1); - assert(errno == ENOTSUP); + assert(errno == EBADF); return 0; } diff --git a/test/wasi/wasm/sock.wasm b/test/wasi/wasm/sock.wasm index 78e7b8e430f911..9fdba111a23ca2 100755 Binary files a/test/wasi/wasm/sock.wasm and b/test/wasi/wasm/sock.wasm differ diff --git a/test/wpt/test-domexception.js b/test/wpt/test-domexception.js index ea68c8562aea57..7900d1ca9a79c6 100644 --- a/test/wpt/test-domexception.js +++ b/test/wpt/test-domexception.js @@ -4,15 +4,6 @@ const { WPTRunner } = require('../common/wpt'); const runner = new WPTRunner('webidl/ecmascript-binding/es-exceptions'); -runner.setFlags(['--expose-internals']); -runner.setInitScript(` - const { internalBinding } = require('internal/test/binding'); - const { DOMException } = internalBinding('messaging'); - Object.defineProperty(global, 'DOMException', { - writable: true, - configurable: true, - value: DOMException, - }); -`); +runner.loadLazyGlobals(); runner.runJsTests(); diff --git a/test/wpt/test-streams.js b/test/wpt/test-streams.js index 6aa435303ab6b3..faf906efb2ef74 100644 --- a/test/wpt/test-streams.js +++ b/test/wpt/test-streams.js @@ -5,6 +5,7 @@ const { WPTRunner } = require('../common/wpt'); const runner = new WPTRunner('streams'); // Set a script that will be executed in the worker before running the tests. +runner.pretendGlobalThisAs('Window'); runner.setInitScript(` // Simulate global postMessage for enqueue-with-detached-buffer.window.js function postMessage(value, origin, transferList) { diff --git a/tools/dep_updaters/update-base64.sh b/tools/dep_updaters/update-base64.sh index 41435fc06eedc3..07bb774797ab86 100755 --- a/tools/dep_updaters/update-base64.sh +++ b/tools/dep_updaters/update-base64.sh @@ -71,6 +71,16 @@ echo "$ git add -A deps/base64/base64 src/base64_version.h" echo "$ git commit -m \"deps: update base64 to $NEW_VERSION\"" echo "" +# update the base64_version.h +cat > "$BASE_DIR/src/base64_version.h" << EOL +// This is an auto generated file, please do not edit. +// Refer to tools/dep_updaters/update-base64.sh +#ifndef SRC_BASE64_VERSION_H_ +#define SRC_BASE64_VERSION_H_ +#define BASE64_VERSION "$NEW_VERSION" +#endif // SRC_BASE64_VERSION_H_ +EOL + # The last line of the script should always print the new version, # as we need to add it to $GITHUB_ENV variable. echo "NEW_VERSION=$NEW_VERSION" diff --git a/tools/dep_updaters/update-cjs-module-lexer.sh b/tools/dep_updaters/update-cjs-module-lexer.sh index c9f5b037431822..74c66b0fecb8d9 100755 --- a/tools/dep_updaters/update-cjs-module-lexer.sh +++ b/tools/dep_updaters/update-cjs-module-lexer.sh @@ -58,6 +58,16 @@ echo "$ git add -A deps/cjs-module-lexer src/cjs_module_lexer_version.h" echo "$ git commit -m \"deps: update cjs-module-lexer to $NEW_VERSION\"" echo "" +# update cjs_module_lexer_version.h +cat > "$BASE_DIR/src/cjs_module_lexer_version.h" << EOL +// This is an auto generated file, please do not edit. +// Refer to tools/dep_updaters/update-cjs-module-lexer.sh +#ifndef SRC_CJS_MODULE_LEXER_VERSION_H_ +#define SRC_CJS_MODULE_LEXER_VERSION_H_ +#define CJS_MODULE_LEXER_VERSION "$NEW_VERSION" +#endif // SRC_CJS_MODULE_LEXER_VERSION_H_ +EOL + # The last line of the script should always print the new version, # as we need to add it to $GITHUB_ENV variable. echo "NEW_VERSION=$NEW_VERSION" diff --git a/tools/dep_updaters/update-eslint.sh b/tools/dep_updaters/update-eslint.sh index 3142d4f2d7f0d4..75fa36ce9fcef7 100755 --- a/tools/dep_updaters/update-eslint.sh +++ b/tools/dep_updaters/update-eslint.sh @@ -48,7 +48,7 @@ rm -rf ../node_modules/eslint eslint-plugin-markdown \ @babel/core \ @babel/eslint-parser \ - @babel/plugin-syntax-import-assertions + @babel/plugin-syntax-import-attributes ) ( cd node_modules/eslint @@ -63,7 +63,7 @@ rm -rf ../node_modules/eslint eslint-plugin-markdown \ @babel/core \ @babel/eslint-parser \ - @babel/plugin-syntax-import-assertions + @babel/plugin-syntax-import-attributes ) # Use dmn to remove some unneeded files. "$NODE" "$NPM" exec --package=dmn@2.2.2 --yes -- dmn -f clean diff --git a/tools/doc/type-parser.mjs b/tools/doc/type-parser.mjs index 9aa9d67c7e958e..db31f6ed729b69 100644 --- a/tools/doc/type-parser.mjs +++ b/tools/doc/type-parser.mjs @@ -57,6 +57,8 @@ const customTypesMap = { 'Module Namespace Object': 'https://tc39.github.io/ecma262/#sec-module-namespace-exotic-objects', + 'AsyncLocalStorage': 'async_context.html#class-asynclocalstorage', + 'AsyncHook': 'async_hooks.html#async_hookscreatehookcallbacks', 'AsyncResource': 'async_hooks.html#class-asyncresource', @@ -108,6 +110,7 @@ const customTypesMap = { 'dgram.Socket': 'dgram.html#class-dgramsocket', 'Channel': 'diagnostics_channel.html#class-channel', + 'TracingChannel': 'diagnostics_channel.html#class-tracingchannel', 'Domain': 'domain.html#class-domain', diff --git a/tools/eslint-rules/set-proto-to-null-in-object.js b/tools/eslint-rules/set-proto-to-null-in-object.js new file mode 100644 index 00000000000000..e1a6af38c032dc --- /dev/null +++ b/tools/eslint-rules/set-proto-to-null-in-object.js @@ -0,0 +1,140 @@ +'use strict'; + +module.exports = { + meta: { + messages: { + error: 'Add `__proto__: null` to object', + }, + fixable: 'code', + }, + create: function(context) { + return { + ObjectExpression(node) { + // Not adding __proto__ to module.exports as it will break a lot of libraries + if (isModuleExportsObject(node) || isModifiedExports(node)) { + return; + } + + const properties = node.properties; + let hasProto = false; + + for (const property of properties) { + + if (!property.key) { + continue; + } + + if (property.key.type === 'Identifier' && property.key.name === '__proto__') { + hasProto = true; + break; + } + + if (property.key.type === 'Literal' && property.key.value === '__proto__') { + hasProto = true; + break; + } + } + + if (hasProto) { + return; + } + + if (properties.length > 0) { + // If the object has properties but no __proto__ property + context.report({ + node, + message: 'Every object must have __proto__: null', + fix: function(fixer) { + // Generate the fix suggestion to add __proto__: null + const sourceCode = context.getSourceCode(); + const firstProperty = properties[0]; + const firstPropertyToken = sourceCode.getFirstToken(firstProperty); + + + const isMultiLine = properties.length === 1 ? + // If the object has only one property, + // it's multiline if the property is not on the same line as the object parenthesis + properties[0].loc.start.line !== node.loc.start.line : + // If the object has more than one property, + // it's multiline if the first and second properties are not on the same line + properties[0].loc.start.line !== properties[1].loc.start.line; + + const fixText = `__proto__: null,${isMultiLine ? '\n' : ' '}`; + + // Insert the fix suggestion before the first property + return fixer.insertTextBefore(firstPropertyToken, fixText); + }, + }); + } + + if (properties.length === 0) { + // If the object is empty and missing __proto__ + context.report({ + node, + message: 'Every empty object must have __proto__: null', + fix: function(fixer) { + // Generate the fix suggestion to create the object with __proto__: null + const fixText = '{ __proto__: null }'; + + // Replace the empty object with the fix suggestion + return fixer.replaceText(node, fixText); + }, + }); + } + }, + }; + }, +}; + +// Helper function to check if the object is `module.exports` +function isModuleExportsObject(node) { + return ( + node.parent && + node.parent.type === 'AssignmentExpression' && + node.parent.left && + node.parent.left.type === 'MemberExpression' && + node.parent.left.object && + node.parent.left.object.name === 'module' && + node.parent.left.property && + node.parent.left.property.name === 'exports' + ); +} + +function isModifiedExports(node) { + return ( + node.parent && + (isObjectAssignCall(node.parent) || isObjectDefinePropertiesCall(node.parent)) + ); +} + +// Helper function to check if the node represents an ObjectAssign call +function isObjectAssignCall(node) { + return ( + node.type === 'CallExpression' && + node.callee && + node.callee.type === 'Identifier' && + node.callee.name === 'ObjectAssign' && + node.arguments.length > 1 && + node.arguments.some((arg) => + arg.type === 'MemberExpression' && + arg.object.name === 'module' && + arg.property.name === 'exports', + ) + ); +} + +// Helper function to check if the node represents an ObjectDefineProperties call +function isObjectDefinePropertiesCall(node) { + return ( + node.type === 'CallExpression' && + node.callee && + node.callee.type === 'Identifier' && + node.callee.name === 'ObjectDefineProperties' && + node.arguments.length > 1 && + node.arguments.some((arg) => + arg.type === 'MemberExpression' && + arg.object.name === 'module' && + arg.property.name === 'exports', + ) + ); +} diff --git a/tools/js2c.py b/tools/js2c.py index 54c7dfce363100..50f34c070ac099 100755 --- a/tools/js2c.py +++ b/tools/js2c.py @@ -57,8 +57,14 @@ def ReadFile(filename): {0} +namespace {{ +const ThreadsafeCopyOnWrite global_source_map {{ + BuiltinSourceMap{{ {1} }} +}}; +}} + void BuiltinLoader::LoadJavaScriptSource() {{ - {1} + source_ = global_source_map; }} UnionBytes BuiltinLoader::GetConfig() {{ @@ -82,7 +88,7 @@ def ReadFile(filename): }}; """ -INITIALIZER = 'source_.emplace("{0}", UnionBytes{{{1}, {2}}});' +INITIALIZER = '{{"{0}", UnionBytes{{{1}, {2}}} }},' CONFIG_GYPI_ID = 'config_raw' diff --git a/tools/lint-md/lint-md.mjs b/tools/lint-md/lint-md.mjs index 3306e24daebaf0..bdea9c710cfea5 100644 --- a/tools/lint-md/lint-md.mjs +++ b/tools/lint-md/lint-md.mjs @@ -1,11 +1,10 @@ import fs from 'fs'; -import path$1 from 'path'; -import { fileURLToPath, pathToFileURL } from 'url'; -import proc from 'process'; -import fs$1 from 'node:fs'; -import path$2 from 'node:path'; +import path$2 from 'path'; +import { pathToFileURL } from 'url'; +import path$1 from 'node:path'; import process$1 from 'node:process'; -import { fileURLToPath as fileURLToPath$1 } from 'node:url'; +import { fileURLToPath } from 'node:url'; +import fs$1 from 'node:fs'; import os from 'node:os'; import tty from 'node:tty'; @@ -21,18 +20,6 @@ function getDefaultExportFromCjs (x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } -/*! - * Determine if an object is a Buffer - * - * @author Feross Aboukhadijeh - * @license MIT - */ -var isBuffer = function isBuffer (obj) { - return obj != null && obj.constructor != null && - typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) -}; -var isBuffer$1 = getDefaultExportFromCjs(isBuffer); - var hasOwn = Object.prototype.hasOwnProperty; var toStr = Object.prototype.toString; var defineProperty = Object.defineProperty; @@ -118,6 +105,8 @@ var extend$1 = function extend() { }; var extend$2 = getDefaultExportFromCjs(extend$1); +function ok$B() {} + function isPlainObject(value) { if (typeof value !== 'object' || value === null) { return false; @@ -206,83 +195,111 @@ function wrap(middleware, callback) { } } -function stringifyPosition$1(value) { +function stringifyPosition$2(value) { if (!value || typeof value !== 'object') { return '' } if ('position' in value || 'type' in value) { - return position$1(value.position) + return position$2(value.position) } if ('start' in value || 'end' in value) { - return position$1(value) + return position$2(value) } if ('line' in value || 'column' in value) { - return point$3(value) + return point$4(value) } return '' } -function point$3(point) { - return index$1(point && point.line) + ':' + index$1(point && point.column) +function point$4(point) { + return index$2(point && point.line) + ':' + index$2(point && point.column) } -function position$1(pos) { - return point$3(pos && pos.start) + '-' + point$3(pos && pos.end) +function position$2(pos) { + return point$4(pos && pos.start) + '-' + point$4(pos && pos.end) } -function index$1(value) { +function index$2(value) { return value && typeof value === 'number' ? value : 1 } let VFileMessage$1 = class VFileMessage extends Error { - constructor(reason, place, origin) { - const parts = [null, null]; - let position = { - start: {line: null, column: null}, - end: {line: null, column: null} - }; + constructor(causeOrReason, optionsOrParentOrPlace, origin) { super(); - if (typeof place === 'string') { - origin = place; - place = undefined; + if (typeof optionsOrParentOrPlace === 'string') { + origin = optionsOrParentOrPlace; + optionsOrParentOrPlace = undefined; + } + let reason = ''; + let options = {}; + let legacyCause = false; + if (optionsOrParentOrPlace) { + if ( + 'line' in optionsOrParentOrPlace && + 'column' in optionsOrParentOrPlace + ) { + options = {place: optionsOrParentOrPlace}; + } + else if ( + 'start' in optionsOrParentOrPlace && + 'end' in optionsOrParentOrPlace + ) { + options = {place: optionsOrParentOrPlace}; + } + else if ('type' in optionsOrParentOrPlace) { + options = { + ancestors: [optionsOrParentOrPlace], + place: optionsOrParentOrPlace.position + }; + } + else { + options = {...optionsOrParentOrPlace}; + } + } + if (typeof causeOrReason === 'string') { + reason = causeOrReason; + } + else if (!options.cause && causeOrReason) { + legacyCause = true; + reason = causeOrReason.message; + options.cause = causeOrReason; } - if (typeof origin === 'string') { + if (!options.ruleId && !options.source && typeof origin === 'string') { const index = origin.indexOf(':'); if (index === -1) { - parts[1] = origin; + options.ruleId = origin; } else { - parts[0] = origin.slice(0, index); - parts[1] = origin.slice(index + 1); + options.source = origin.slice(0, index); + options.ruleId = origin.slice(index + 1); } } - if (place) { - if ('type' in place || 'position' in place) { - if (place.position) { - position = place.position; - } - } - else if ('start' in place || 'end' in place) { - position = place; - } - else if ('line' in place || 'column' in place) { - position.start = place; + if (!options.place && options.ancestors && options.ancestors) { + const parent = options.ancestors[options.ancestors.length - 1]; + if (parent) { + options.place = parent.position; } } - this.name = stringifyPosition$1(place) || '1:1'; - this.message = typeof reason === 'object' ? reason.message : reason; - this.stack = ''; - if (typeof reason === 'object' && reason.stack) { - this.stack = reason.stack; - } - this.reason = this.message; - this.fatal; - this.line = position.start.line; - this.column = position.start.column; - this.position = position; - this.source = parts[0]; - this.ruleId = parts[1]; + const start = + options.place && 'start' in options.place + ? options.place.start + : options.place; + this.ancestors = options.ancestors || undefined; + this.cause = options.cause || undefined; + this.column = start ? start.column : undefined; + this.fatal = undefined; this.file; + this.message = reason; + this.line = start ? start.line : undefined; + this.name = stringifyPosition$2(options.place) || '1:1'; + this.place = options.place || undefined; + this.reason = this.message; + this.ruleId = options.ruleId || undefined; + this.source = options.source || undefined; + this.stack = + legacyCause && options.cause && typeof options.cause.stack === 'string' + ? options.cause.stack + : ''; this.actual; this.expected; - this.url; this.note; + this.url; } }; VFileMessage$1.prototype.file = ''; @@ -290,43 +307,55 @@ VFileMessage$1.prototype.name = ''; VFileMessage$1.prototype.reason = ''; VFileMessage$1.prototype.message = ''; VFileMessage$1.prototype.stack = ''; -VFileMessage$1.prototype.fatal = null; -VFileMessage$1.prototype.column = null; -VFileMessage$1.prototype.line = null; -VFileMessage$1.prototype.source = null; -VFileMessage$1.prototype.ruleId = null; -VFileMessage$1.prototype.position = null; +VFileMessage$1.prototype.column = undefined; +VFileMessage$1.prototype.line = undefined; +VFileMessage$1.prototype.ancestors = undefined; +VFileMessage$1.prototype.cause = undefined; +VFileMessage$1.prototype.fatal = undefined; +VFileMessage$1.prototype.place = undefined; +VFileMessage$1.prototype.ruleId = undefined; +VFileMessage$1.prototype.source = undefined; function isUrl$1(fileUrlOrPath) { - return ( + return Boolean( fileUrlOrPath !== null && - typeof fileUrlOrPath === 'object' && - fileUrlOrPath.href && - fileUrlOrPath.origin + typeof fileUrlOrPath === 'object' && + 'href' in fileUrlOrPath && + fileUrlOrPath.href && + 'protocol' in fileUrlOrPath && + fileUrlOrPath.protocol && + fileUrlOrPath.auth === undefined ) } -const order$1 = ['history', 'path', 'basename', 'stem', 'extname', 'dirname']; +const order$1 = ([ + 'history', + 'path', + 'basename', + 'stem', + 'extname', + 'dirname' +]); let VFile$1 = class VFile { constructor(value) { let options; if (!value) { options = {}; - } else if (typeof value === 'string' || buffer(value)) { - options = {value}; } else if (isUrl$1(value)) { options = {path: value}; + } else if (typeof value === 'string' || isUint8Array$3(value)) { + options = {value}; } else { options = value; } + this.cwd = process$1.cwd(); this.data = {}; - this.messages = []; this.history = []; - this.cwd = proc.cwd(); + this.messages = []; this.value; - this.stored; - this.result; this.map; + this.result; + this.stored; let index = -1; while (++index < order$1.length) { const prop = order$1[index]; @@ -345,17 +374,13 @@ let VFile$1 = class VFile { } } } - get path() { - return this.history[this.history.length - 1] + get basename() { + return typeof this.path === 'string' ? path$1.basename(this.path) : undefined } - set path(path) { - if (isUrl$1(path)) { - path = fileURLToPath(path); - } - assertNonEmpty$1(path, 'path'); - if (this.path !== path) { - this.history.push(path); - } + set basename(basename) { + assertNonEmpty$1(basename, 'basename'); + assertPart$1(basename, 'basename'); + this.path = path$1.join(this.dirname || '', basename); } get dirname() { return typeof this.path === 'string' ? path$1.dirname(this.path) : undefined @@ -364,14 +389,6 @@ let VFile$1 = class VFile { assertPath$1(this.basename, 'dirname'); this.path = path$1.join(dirname || '', this.basename); } - get basename() { - return typeof this.path === 'string' ? path$1.basename(this.path) : undefined - } - set basename(basename) { - assertNonEmpty$1(basename, 'basename'); - assertPart$1(basename, 'basename'); - this.path = path$1.join(this.dirname || '', basename); - } get extname() { return typeof this.path === 'string' ? path$1.extname(this.path) : undefined } @@ -379,7 +396,7 @@ let VFile$1 = class VFile { assertPart$1(extname, 'extname'); assertPath$1(this.dirname, 'extname'); if (extname) { - if (extname.charCodeAt(0) !== 46 ) { + if (extname.codePointAt(0) !== 46 ) { throw new Error('`extname` must start with `.`') } if (extname.includes('.', 1)) { @@ -388,6 +405,18 @@ let VFile$1 = class VFile { } this.path = path$1.join(this.dirname, this.stem + (extname || '')); } + get path() { + return this.history[this.history.length - 1] + } + set path(path) { + if (isUrl$1(path)) { + path = fileURLToPath(path); + } + assertNonEmpty$1(path, 'path'); + if (this.path !== path) { + this.history.push(path); + } + } get stem() { return typeof this.path === 'string' ? path$1.basename(this.path, this.extname) @@ -398,11 +427,22 @@ let VFile$1 = class VFile { assertPart$1(stem, 'stem'); this.path = path$1.join(this.dirname || '', stem + (this.extname || '')); } - toString(encoding) { - return (this.value || '').toString(encoding || undefined) + fail(causeOrReason, optionsOrParentOrPlace, origin) { + const message = this.message(causeOrReason, optionsOrParentOrPlace, origin); + message.fatal = true; + throw message + } + info(causeOrReason, optionsOrParentOrPlace, origin) { + const message = this.message(causeOrReason, optionsOrParentOrPlace, origin); + message.fatal = undefined; + return message } - message(reason, place, origin) { - const message = new VFileMessage$1(reason, place, origin); + message(causeOrReason, optionsOrParentOrPlace, origin) { + const message = new VFileMessage$1( + causeOrReason, + optionsOrParentOrPlace, + origin + ); if (this.path) { message.name = this.path + ':' + message.name; message.file = this.path; @@ -411,15 +451,15 @@ let VFile$1 = class VFile { this.messages.push(message); return message } - info(reason, place, origin) { - const message = this.message(reason, place, origin); - message.fatal = null; - return message - } - fail(reason, place, origin) { - const message = this.message(reason, place, origin); - message.fatal = true; - throw message + toString(encoding) { + if (this.value === undefined) { + return '' + } + if (typeof this.value === 'string') { + return this.value + } + const decoder = new TextDecoder(encoding || undefined); + return decoder.decode(this.value) } }; function assertPart$1(part, name) { @@ -439,82 +479,218 @@ function assertPath$1(path, name) { throw new Error('Setting `' + name + '` requires `path` to be set too') } } -function buffer(value) { - return isBuffer$1(value) +function isUint8Array$3(value) { + return Boolean( + value && + typeof value === 'object' && + 'byteLength' in value && + 'byteOffset' in value + ) } -const unified = base().freeze(); +const CallableInstance = + ( + ( + function (property) { + const self = this; + const constr = self.constructor; + const proto = ( + constr.prototype + ); + const func = proto[property]; + const apply = function () { + return func.apply(apply, arguments) + }; + Object.setPrototypeOf(apply, proto); + const names = Object.getOwnPropertyNames(func); + for (const p of names) { + const descriptor = Object.getOwnPropertyDescriptor(func, p); + if (descriptor) Object.defineProperty(apply, p, descriptor); + } + return apply + } + ) + ); + const own$6 = {}.hasOwnProperty; -function base() { - const transformers = trough(); - const attachers = []; - let namespace = {}; - let frozen; - let freezeIndex = -1; - processor.data = data; - processor.Parser = undefined; - processor.Compiler = undefined; - processor.freeze = freeze; - processor.attachers = attachers; - processor.use = use; - processor.parse = parse; - processor.stringify = stringify; - processor.run = run; - processor.runSync = runSync; - processor.process = process; - processor.processSync = processSync; - return processor - function processor() { - const destination = base(); +class Processor extends CallableInstance { + constructor() { + super('copy'); + this.Compiler = undefined; + this.Parser = undefined; + this.attachers = []; + this.compiler = undefined; + this.freezeIndex = -1; + this.frozen = undefined; + this.namespace = {}; + this.parser = undefined; + this.transformers = trough(); + } + copy() { + const destination = + ( + new Processor() + ); let index = -1; - while (++index < attachers.length) { - destination.use(...attachers[index]); + while (++index < this.attachers.length) { + const attacher = this.attachers[index]; + destination.use(...attacher); } - destination.data(extend$2(true, {}, namespace)); + destination.data(extend$2(true, {}, this.namespace)); return destination } - function data(key, value) { + data(key, value) { if (typeof key === 'string') { if (arguments.length === 2) { - assertUnfrozen('data', frozen); - namespace[key] = value; - return processor + assertUnfrozen('data', this.frozen); + this.namespace[key] = value; + return this } - return (own$6.call(namespace, key) && namespace[key]) || null + return (own$6.call(this.namespace, key) && this.namespace[key]) || undefined } if (key) { - assertUnfrozen('data', frozen); - namespace = key; - return processor + assertUnfrozen('data', this.frozen); + this.namespace = key; + return this } - return namespace + return this.namespace } - function freeze() { - if (frozen) { - return processor + freeze() { + if (this.frozen) { + return this } - while (++freezeIndex < attachers.length) { - const [attacher, ...options] = attachers[freezeIndex]; + const self = ( (this)); + while (++this.freezeIndex < this.attachers.length) { + const [attacher, ...options] = this.attachers[this.freezeIndex]; if (options[0] === false) { continue } if (options[0] === true) { options[0] = undefined; } - const transformer = attacher.call(processor, ...options); + const transformer = attacher.call(self, ...options); if (typeof transformer === 'function') { - transformers.use(transformer); + this.transformers.use(transformer); + } + } + this.frozen = true; + this.freezeIndex = Number.POSITIVE_INFINITY; + return this + } + parse(file) { + this.freeze(); + const realFile = vfile(file); + const parser = this.parser || this.Parser; + assertParser('parse', parser); + return parser(String(realFile), realFile) + } + process(file, done) { + const self = this; + this.freeze(); + assertParser('process', this.parser || this.Parser); + assertCompiler('process', this.compiler || this.Compiler); + return done ? executor(undefined, done) : new Promise(executor) + function executor(resolve, reject) { + const realFile = vfile(file); + const parseTree = + ( + (self.parse(realFile)) + ); + self.run(parseTree, realFile, function (error, tree, file) { + if (error || !tree || !file) { + return realDone(error) + } + const compileTree = + ( + (tree) + ); + const compileResult = self.stringify(compileTree, file); + if (looksLikeAValue(compileResult)) { + file.value = compileResult; + } else { + file.result = compileResult; + } + realDone(error, (file)); + }); + function realDone(error, file) { + if (error || !file) { + reject(error); + } else if (resolve) { + resolve(file); + } else { + done(undefined, file); + } + } + } + } + processSync(file) { + let complete = false; + let result; + this.freeze(); + assertParser('processSync', this.parser || this.Parser); + assertCompiler('processSync', this.compiler || this.Compiler); + this.process(file, realDone); + assertDone('processSync', 'process', complete); + return result + function realDone(error, file) { + complete = true; + bail(error); + result = file; + } + } + run(tree, file, done) { + assertNode(tree); + this.freeze(); + const transformers = this.transformers; + if (!done && typeof file === 'function') { + done = file; + file = undefined; + } + return done ? executor(undefined, done) : new Promise(executor) + function executor(resolve, reject) { + const realFile = vfile(file); + transformers.run(tree, realFile, realDone); + function realDone(error, outputTree, file) { + const resultingTree = + ( + outputTree || tree + ); + if (error) { + reject(error); + } else if (resolve) { + resolve(resultingTree); + } else { + done(undefined, resultingTree, file); + } } } - frozen = true; - freezeIndex = Number.POSITIVE_INFINITY; - return processor } - function use(value, ...options) { - let settings; - assertUnfrozen('use', frozen); + runSync(tree, file) { + let complete = false; + let result; + this.run(tree, file, realDone); + assertDone('runSync', 'run', complete); + return result + function realDone(error, tree) { + bail(error); + result = tree; + complete = true; + } + } + stringify(tree, file) { + this.freeze(); + const realFile = vfile(file); + const compiler = this.compiler || this.Compiler; + assertCompiler('stringify', compiler); + assertNode(tree); + return compiler(tree, realFile) + } + use(value, ...parameters) { + const attachers = this.attachers; + const namespace = this.namespace; + assertUnfrozen('use', this.frozen); if (value === null || value === undefined) ; else if (typeof value === 'function') { - addPlugin(value, ...options); + addPlugin(value, parameters); } else if (typeof value === 'object') { if (Array.isArray(value)) { addList(value); @@ -524,17 +700,15 @@ function base() { } else { throw new TypeError('Expected usable value, not `' + value + '`') } - if (settings) { - namespace.settings = Object.assign(namespace.settings || {}, settings); - } - return processor + return this function add(value) { if (typeof value === 'function') { - addPlugin(value); + addPlugin(value, []); } else if (typeof value === 'object') { if (Array.isArray(value)) { - const [plugin, ...options] = value; - addPlugin(plugin, ...options); + const [plugin, ...parameters] = + (value); + addPlugin(plugin, parameters); } else { addPreset(value); } @@ -543,9 +717,14 @@ function base() { } } function addPreset(result) { + if (!('plugins' in result) && !('settings' in result)) { + throw new Error( + 'Expected usable value but received an empty preset, which is probably a mistake: presets typically come with `plugins` and sometimes with `settings`, but this has neither' + ) + } addList(result.plugins); if (result.settings) { - settings = Object.assign(settings || {}, result.settings); + namespace.settings = extend$2(true, namespace.settings, result.settings); } } function addList(plugins) { @@ -559,156 +738,38 @@ function base() { throw new TypeError('Expected a list of plugins, not `' + plugins + '`') } } - function addPlugin(plugin, value) { + function addPlugin(plugin, parameters) { let index = -1; - let entry; + let entryIndex = -1; while (++index < attachers.length) { if (attachers[index][0] === plugin) { - entry = attachers[index]; + entryIndex = index; break } } - if (entry) { - if (isPlainObject(entry[1]) && isPlainObject(value)) { - value = extend$2(true, entry[1], value); + if (entryIndex === -1) { + attachers.push([plugin, ...parameters]); + } + else if (parameters.length > 0) { + let [primary, ...rest] = parameters; + const currentPrimary = attachers[entryIndex][1]; + if (isPlainObject(currentPrimary) && isPlainObject(primary)) { + primary = extend$2(true, currentPrimary, primary); } - entry[1] = value; - } else { - attachers.push([...arguments]); + attachers[entryIndex] = [plugin, primary, ...rest]; } } } - function parse(doc) { - processor.freeze(); - const file = vfile(doc); - const Parser = processor.Parser; - assertParser('parse', Parser); - if (newable(Parser, 'parse')) { - return new Parser(String(file), file).parse() - } - return Parser(String(file), file) +} +const unified = new Processor().freeze(); +function assertParser(name, value) { + if (typeof value !== 'function') { + throw new TypeError('Cannot `' + name + '` without `parser`') } - function stringify(node, doc) { - processor.freeze(); - const file = vfile(doc); - const Compiler = processor.Compiler; - assertCompiler('stringify', Compiler); - assertNode(node); - if (newable(Compiler, 'compile')) { - return new Compiler(node, file).compile() - } - return Compiler(node, file) - } - function run(node, doc, callback) { - assertNode(node); - processor.freeze(); - if (!callback && typeof doc === 'function') { - callback = doc; - doc = undefined; - } - if (!callback) { - return new Promise(executor) - } - executor(null, callback); - function executor(resolve, reject) { - transformers.run(node, vfile(doc), done); - function done(error, tree, file) { - tree = tree || node; - if (error) { - reject(error); - } else if (resolve) { - resolve(tree); - } else { - callback(null, tree, file); - } - } - } - } - function runSync(node, file) { - let result; - let complete; - processor.run(node, file, done); - assertDone('runSync', 'run', complete); - return result - function done(error, tree) { - bail(error); - result = tree; - complete = true; - } - } - function process(doc, callback) { - processor.freeze(); - assertParser('process', processor.Parser); - assertCompiler('process', processor.Compiler); - if (!callback) { - return new Promise(executor) - } - executor(null, callback); - function executor(resolve, reject) { - const file = vfile(doc); - processor.run(processor.parse(file), file, (error, tree, file) => { - if (error || !tree || !file) { - done(error); - } else { - const result = processor.stringify(tree, file); - if (result === undefined || result === null) ; else if (looksLikeAVFileValue(result)) { - file.value = result; - } else { - file.result = result; - } - done(error, file); - } - }); - function done(error, file) { - if (error || !file) { - reject(error); - } else if (resolve) { - resolve(file); - } else { - callback(null, file); - } - } - } - } - function processSync(doc) { - let complete; - processor.freeze(); - assertParser('processSync', processor.Parser); - assertCompiler('processSync', processor.Compiler); - const file = vfile(doc); - processor.process(file, done); - assertDone('processSync', 'process', complete); - return file - function done(error) { - complete = true; - bail(error); - } - } -} -function newable(value, name) { - return ( - typeof value === 'function' && - value.prototype && - (keys(value.prototype) || name in value.prototype) - ) -} -function keys(value) { - let key; - for (key in value) { - if (own$6.call(value, key)) { - return true - } - } - return false -} -function assertParser(name, value) { - if (typeof value !== 'function') { - throw new TypeError('Cannot `' + name + '` without `Parser`') - } -} -function assertCompiler(name, value) { - if (typeof value !== 'function') { - throw new TypeError('Cannot `' + name + '` without `Compiler`') +} +function assertCompiler(name, value) { + if (typeof value !== 'function') { + throw new TypeError('Cannot `' + name + '` without `compiler`') } } function assertUnfrozen(name, frozen) { @@ -743,23 +804,31 @@ function looksLikeAVFile$1(value) { 'messages' in value ) } -function looksLikeAVFileValue(value) { - return typeof value === 'string' || isBuffer$1(value) +function looksLikeAValue(value) { + return typeof value === 'string' || isUint8Array$2(value) +} +function isUint8Array$2(value) { + return Boolean( + value && + typeof value === 'object' && + 'byteLength' in value && + 'byteOffset' in value + ) } -const emptyOptions = {}; -function toString(value, options) { - const settings = options || emptyOptions; +const emptyOptions$3 = {}; +function toString$2(value, options) { + const settings = options || emptyOptions$3; const includeImageAlt = typeof settings.includeImageAlt === 'boolean' ? settings.includeImageAlt : true; const includeHtml = typeof settings.includeHtml === 'boolean' ? settings.includeHtml : true; - return one(value, includeImageAlt, includeHtml) + return one$2(value, includeImageAlt, includeHtml) } -function one(value, includeImageAlt, includeHtml) { - if (node(value)) { +function one$2(value, includeImageAlt, includeHtml) { + if (node$2(value)) { if ('value' in value) { return value.type === 'html' && !includeHtml ? '' : value.value } @@ -767,802 +836,26 @@ function one(value, includeImageAlt, includeHtml) { return value.alt } if ('children' in value) { - return all(value.children, includeImageAlt, includeHtml) + return all$2(value.children, includeImageAlt, includeHtml) } } if (Array.isArray(value)) { - return all(value, includeImageAlt, includeHtml) + return all$2(value, includeImageAlt, includeHtml) } return '' } -function all(values, includeImageAlt, includeHtml) { +function all$2(values, includeImageAlt, includeHtml) { const result = []; let index = -1; while (++index < values.length) { - result[index] = one(values[index], includeImageAlt, includeHtml); + result[index] = one$2(values[index], includeImageAlt, includeHtml); } return result.join('') } -function node(value) { +function node$2(value) { return Boolean(value && typeof value === 'object') } -function splice(list, start, remove, items) { - const end = list.length; - let chunkStart = 0; - let parameters; - if (start < 0) { - start = -start > end ? 0 : end + start; - } else { - start = start > end ? end : start; - } - remove = remove > 0 ? remove : 0; - if (items.length < 10000) { - parameters = Array.from(items); - parameters.unshift(start, remove); - list.splice(...parameters); - } else { - if (remove) list.splice(start, remove); - while (chunkStart < items.length) { - parameters = items.slice(chunkStart, chunkStart + 10000); - parameters.unshift(start, 0); - list.splice(...parameters); - chunkStart += 10000; - start += 10000; - } - } -} -function push(list, items) { - if (list.length > 0) { - splice(list, list.length, 0, items); - return list - } - return items -} - -const hasOwnProperty = {}.hasOwnProperty; -function combineExtensions(extensions) { - const all = {}; - let index = -1; - while (++index < extensions.length) { - syntaxExtension(all, extensions[index]); - } - return all -} -function syntaxExtension(all, extension) { - let hook; - for (hook in extension) { - const maybe = hasOwnProperty.call(all, hook) ? all[hook] : undefined; - const left = maybe || (all[hook] = {}); - const right = extension[hook]; - let code; - if (right) { - for (code in right) { - if (!hasOwnProperty.call(left, code)) left[code] = []; - const value = right[code]; - constructs( - left[code], - Array.isArray(value) ? value : value ? [value] : [] - ); - } - } - } -} -function constructs(existing, list) { - let index = -1; - const before = []; - while (++index < list.length) { -(list[index].add === 'after' ? existing : before).push(list[index]); - } - splice(existing, 0, 0, before); -} - -const unicodePunctuationRegex = - /[!-\/:-@\[-`\{-~\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061D-\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u09FD\u0A76\u0AF0\u0C77\u0C84\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1B7D\u1B7E\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E4F\u2E52-\u2E5D\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]/; - -const asciiAlpha = regexCheck(/[A-Za-z]/); -const asciiAlphanumeric = regexCheck(/[\dA-Za-z]/); -const asciiAtext = regexCheck(/[#-'*+\--9=?A-Z^-~]/); -function asciiControl(code) { - return ( - code !== null && (code < 32 || code === 127) - ) -} -const asciiDigit = regexCheck(/\d/); -const asciiHexDigit = regexCheck(/[\dA-Fa-f]/); -const asciiPunctuation = regexCheck(/[!-/:-@[-`{-~]/); -function markdownLineEnding(code) { - return code !== null && code < -2 -} -function markdownLineEndingOrSpace(code) { - return code !== null && (code < 0 || code === 32) -} -function markdownSpace(code) { - return code === -2 || code === -1 || code === 32 -} -const unicodePunctuation = regexCheck(unicodePunctuationRegex); -const unicodeWhitespace = regexCheck(/\s/); -function regexCheck(regex) { - return check - function check(code) { - return code !== null && regex.test(String.fromCharCode(code)) - } -} - -function factorySpace(effects, ok, type, max) { - const limit = max ? max - 1 : Number.POSITIVE_INFINITY; - let size = 0; - return start - function start(code) { - if (markdownSpace(code)) { - effects.enter(type); - return prefix(code) - } - return ok(code) - } - function prefix(code) { - if (markdownSpace(code) && size++ < limit) { - effects.consume(code); - return prefix - } - effects.exit(type); - return ok(code) - } -} - -const content$1 = { - tokenize: initializeContent -}; -function initializeContent(effects) { - const contentStart = effects.attempt( - this.parser.constructs.contentInitial, - afterContentStartConstruct, - paragraphInitial - ); - let previous; - return contentStart - function afterContentStartConstruct(code) { - if (code === null) { - effects.consume(code); - return - } - effects.enter('lineEnding'); - effects.consume(code); - effects.exit('lineEnding'); - return factorySpace(effects, contentStart, 'linePrefix') - } - function paragraphInitial(code) { - effects.enter('paragraph'); - return lineStart(code) - } - function lineStart(code) { - const token = effects.enter('chunkText', { - contentType: 'text', - previous - }); - if (previous) { - previous.next = token; - } - previous = token; - return data(code) - } - function data(code) { - if (code === null) { - effects.exit('chunkText'); - effects.exit('paragraph'); - effects.consume(code); - return - } - if (markdownLineEnding(code)) { - effects.consume(code); - effects.exit('chunkText'); - return lineStart - } - effects.consume(code); - return data - } -} - -const document$1 = { - tokenize: initializeDocument -}; -const containerConstruct = { - tokenize: tokenizeContainer -}; -function initializeDocument(effects) { - const self = this; - const stack = []; - let continued = 0; - let childFlow; - let childToken; - let lineStartOffset; - return start - function start(code) { - if (continued < stack.length) { - const item = stack[continued]; - self.containerState = item[1]; - return effects.attempt( - item[0].continuation, - documentContinue, - checkNewContainers - )(code) - } - return checkNewContainers(code) - } - function documentContinue(code) { - continued++; - if (self.containerState._closeFlow) { - self.containerState._closeFlow = undefined; - if (childFlow) { - closeFlow(); - } - const indexBeforeExits = self.events.length; - let indexBeforeFlow = indexBeforeExits; - let point; - while (indexBeforeFlow--) { - if ( - self.events[indexBeforeFlow][0] === 'exit' && - self.events[indexBeforeFlow][1].type === 'chunkFlow' - ) { - point = self.events[indexBeforeFlow][1].end; - break - } - } - exitContainers(continued); - let index = indexBeforeExits; - while (index < self.events.length) { - self.events[index][1].end = Object.assign({}, point); - index++; - } - splice( - self.events, - indexBeforeFlow + 1, - 0, - self.events.slice(indexBeforeExits) - ); - self.events.length = index; - return checkNewContainers(code) - } - return start(code) - } - function checkNewContainers(code) { - if (continued === stack.length) { - if (!childFlow) { - return documentContinued(code) - } - if (childFlow.currentConstruct && childFlow.currentConstruct.concrete) { - return flowStart(code) - } - self.interrupt = Boolean( - childFlow.currentConstruct && !childFlow._gfmTableDynamicInterruptHack - ); - } - self.containerState = {}; - return effects.check( - containerConstruct, - thereIsANewContainer, - thereIsNoNewContainer - )(code) - } - function thereIsANewContainer(code) { - if (childFlow) closeFlow(); - exitContainers(continued); - return documentContinued(code) - } - function thereIsNoNewContainer(code) { - self.parser.lazy[self.now().line] = continued !== stack.length; - lineStartOffset = self.now().offset; - return flowStart(code) - } - function documentContinued(code) { - self.containerState = {}; - return effects.attempt( - containerConstruct, - containerContinue, - flowStart - )(code) - } - function containerContinue(code) { - continued++; - stack.push([self.currentConstruct, self.containerState]); - return documentContinued(code) - } - function flowStart(code) { - if (code === null) { - if (childFlow) closeFlow(); - exitContainers(0); - effects.consume(code); - return - } - childFlow = childFlow || self.parser.flow(self.now()); - effects.enter('chunkFlow', { - contentType: 'flow', - previous: childToken, - _tokenizer: childFlow - }); - return flowContinue(code) - } - function flowContinue(code) { - if (code === null) { - writeToChild(effects.exit('chunkFlow'), true); - exitContainers(0); - effects.consume(code); - return - } - if (markdownLineEnding(code)) { - effects.consume(code); - writeToChild(effects.exit('chunkFlow')); - continued = 0; - self.interrupt = undefined; - return start - } - effects.consume(code); - return flowContinue - } - function writeToChild(token, eof) { - const stream = self.sliceStream(token); - if (eof) stream.push(null); - token.previous = childToken; - if (childToken) childToken.next = token; - childToken = token; - childFlow.defineSkip(token.start); - childFlow.write(stream); - if (self.parser.lazy[token.start.line]) { - let index = childFlow.events.length; - while (index--) { - if ( - childFlow.events[index][1].start.offset < lineStartOffset && - (!childFlow.events[index][1].end || - childFlow.events[index][1].end.offset > lineStartOffset) - ) { - return - } - } - const indexBeforeExits = self.events.length; - let indexBeforeFlow = indexBeforeExits; - let seen; - let point; - while (indexBeforeFlow--) { - if ( - self.events[indexBeforeFlow][0] === 'exit' && - self.events[indexBeforeFlow][1].type === 'chunkFlow' - ) { - if (seen) { - point = self.events[indexBeforeFlow][1].end; - break - } - seen = true; - } - } - exitContainers(continued); - index = indexBeforeExits; - while (index < self.events.length) { - self.events[index][1].end = Object.assign({}, point); - index++; - } - splice( - self.events, - indexBeforeFlow + 1, - 0, - self.events.slice(indexBeforeExits) - ); - self.events.length = index; - } - } - function exitContainers(size) { - let index = stack.length; - while (index-- > size) { - const entry = stack[index]; - self.containerState = entry[1]; - entry[0].exit.call(self, effects); - } - stack.length = size; - } - function closeFlow() { - childFlow.write([null]); - childToken = undefined; - childFlow = undefined; - self.containerState._closeFlow = undefined; - } -} -function tokenizeContainer(effects, ok, nok) { - return factorySpace( - effects, - effects.attempt(this.parser.constructs.document, ok, nok), - 'linePrefix', - this.parser.constructs.disable.null.includes('codeIndented') ? undefined : 4 - ) -} - -function classifyCharacter(code) { - if ( - code === null || - markdownLineEndingOrSpace(code) || - unicodeWhitespace(code) - ) { - return 1 - } - if (unicodePunctuation(code)) { - return 2 - } -} - -function resolveAll(constructs, events, context) { - const called = []; - let index = -1; - while (++index < constructs.length) { - const resolve = constructs[index].resolveAll; - if (resolve && !called.includes(resolve)) { - events = resolve(events, context); - called.push(resolve); - } - } - return events -} - -const attention = { - name: 'attention', - tokenize: tokenizeAttention, - resolveAll: resolveAllAttention -}; -function resolveAllAttention(events, context) { - let index = -1; - let open; - let group; - let text; - let openingSequence; - let closingSequence; - let use; - let nextEvents; - let offset; - while (++index < events.length) { - if ( - events[index][0] === 'enter' && - events[index][1].type === 'attentionSequence' && - events[index][1]._close - ) { - open = index; - while (open--) { - if ( - events[open][0] === 'exit' && - events[open][1].type === 'attentionSequence' && - events[open][1]._open && - context.sliceSerialize(events[open][1]).charCodeAt(0) === - context.sliceSerialize(events[index][1]).charCodeAt(0) - ) { - if ( - (events[open][1]._close || events[index][1]._open) && - (events[index][1].end.offset - events[index][1].start.offset) % 3 && - !( - (events[open][1].end.offset - - events[open][1].start.offset + - events[index][1].end.offset - - events[index][1].start.offset) % - 3 - ) - ) { - continue - } - use = - events[open][1].end.offset - events[open][1].start.offset > 1 && - events[index][1].end.offset - events[index][1].start.offset > 1 - ? 2 - : 1; - const start = Object.assign({}, events[open][1].end); - const end = Object.assign({}, events[index][1].start); - movePoint(start, -use); - movePoint(end, use); - openingSequence = { - type: use > 1 ? 'strongSequence' : 'emphasisSequence', - start, - end: Object.assign({}, events[open][1].end) - }; - closingSequence = { - type: use > 1 ? 'strongSequence' : 'emphasisSequence', - start: Object.assign({}, events[index][1].start), - end - }; - text = { - type: use > 1 ? 'strongText' : 'emphasisText', - start: Object.assign({}, events[open][1].end), - end: Object.assign({}, events[index][1].start) - }; - group = { - type: use > 1 ? 'strong' : 'emphasis', - start: Object.assign({}, openingSequence.start), - end: Object.assign({}, closingSequence.end) - }; - events[open][1].end = Object.assign({}, openingSequence.start); - events[index][1].start = Object.assign({}, closingSequence.end); - nextEvents = []; - if (events[open][1].end.offset - events[open][1].start.offset) { - nextEvents = push(nextEvents, [ - ['enter', events[open][1], context], - ['exit', events[open][1], context] - ]); - } - nextEvents = push(nextEvents, [ - ['enter', group, context], - ['enter', openingSequence, context], - ['exit', openingSequence, context], - ['enter', text, context] - ]); - nextEvents = push( - nextEvents, - resolveAll( - context.parser.constructs.insideSpan.null, - events.slice(open + 1, index), - context - ) - ); - nextEvents = push(nextEvents, [ - ['exit', text, context], - ['enter', closingSequence, context], - ['exit', closingSequence, context], - ['exit', group, context] - ]); - if (events[index][1].end.offset - events[index][1].start.offset) { - offset = 2; - nextEvents = push(nextEvents, [ - ['enter', events[index][1], context], - ['exit', events[index][1], context] - ]); - } else { - offset = 0; - } - splice(events, open - 1, index - open + 3, nextEvents); - index = open + nextEvents.length - offset - 2; - break - } - } - } - } - index = -1; - while (++index < events.length) { - if (events[index][1].type === 'attentionSequence') { - events[index][1].type = 'data'; - } - } - return events -} -function tokenizeAttention(effects, ok) { - const attentionMarkers = this.parser.constructs.attentionMarkers.null; - const previous = this.previous; - const before = classifyCharacter(previous); - let marker; - return start - function start(code) { - marker = code; - effects.enter('attentionSequence'); - return inside(code) - } - function inside(code) { - if (code === marker) { - effects.consume(code); - return inside - } - const token = effects.exit('attentionSequence'); - const after = classifyCharacter(code); - const open = - !after || (after === 2 && before) || attentionMarkers.includes(code); - const close = - !before || (before === 2 && after) || attentionMarkers.includes(previous); - token._open = Boolean(marker === 42 ? open : open && (before || !close)); - token._close = Boolean(marker === 42 ? close : close && (after || !open)); - return ok(code) - } -} -function movePoint(point, offset) { - point.column += offset; - point.offset += offset; - point._bufferIndex += offset; -} - -const autolink = { - name: 'autolink', - tokenize: tokenizeAutolink -}; -function tokenizeAutolink(effects, ok, nok) { - let size = 0; - return start - function start(code) { - effects.enter('autolink'); - effects.enter('autolinkMarker'); - effects.consume(code); - effects.exit('autolinkMarker'); - effects.enter('autolinkProtocol'); - return open - } - function open(code) { - if (asciiAlpha(code)) { - effects.consume(code); - return schemeOrEmailAtext - } - return emailAtext(code) - } - function schemeOrEmailAtext(code) { - if (code === 43 || code === 45 || code === 46 || asciiAlphanumeric(code)) { - size = 1; - return schemeInsideOrEmailAtext(code) - } - return emailAtext(code) - } - function schemeInsideOrEmailAtext(code) { - if (code === 58) { - effects.consume(code); - size = 0; - return urlInside - } - if ( - (code === 43 || code === 45 || code === 46 || asciiAlphanumeric(code)) && - size++ < 32 - ) { - effects.consume(code); - return schemeInsideOrEmailAtext - } - size = 0; - return emailAtext(code) - } - function urlInside(code) { - if (code === 62) { - effects.exit('autolinkProtocol'); - effects.enter('autolinkMarker'); - effects.consume(code); - effects.exit('autolinkMarker'); - effects.exit('autolink'); - return ok - } - if (code === null || code === 32 || code === 60 || asciiControl(code)) { - return nok(code) - } - effects.consume(code); - return urlInside - } - function emailAtext(code) { - if (code === 64) { - effects.consume(code); - return emailAtSignOrDot - } - if (asciiAtext(code)) { - effects.consume(code); - return emailAtext - } - return nok(code) - } - function emailAtSignOrDot(code) { - return asciiAlphanumeric(code) ? emailLabel(code) : nok(code) - } - function emailLabel(code) { - if (code === 46) { - effects.consume(code); - size = 0; - return emailAtSignOrDot - } - if (code === 62) { - effects.exit('autolinkProtocol').type = 'autolinkEmail'; - effects.enter('autolinkMarker'); - effects.consume(code); - effects.exit('autolinkMarker'); - effects.exit('autolink'); - return ok - } - return emailValue(code) - } - function emailValue(code) { - if ((code === 45 || asciiAlphanumeric(code)) && size++ < 63) { - const next = code === 45 ? emailValue : emailLabel; - effects.consume(code); - return next - } - return nok(code) - } -} - -const blankLine = { - tokenize: tokenizeBlankLine, - partial: true -}; -function tokenizeBlankLine(effects, ok, nok) { - return start - function start(code) { - return markdownSpace(code) - ? factorySpace(effects, after, 'linePrefix')(code) - : after(code) - } - function after(code) { - return code === null || markdownLineEnding(code) ? ok(code) : nok(code) - } -} - -const blockQuote = { - name: 'blockQuote', - tokenize: tokenizeBlockQuoteStart, - continuation: { - tokenize: tokenizeBlockQuoteContinuation - }, - exit: exit$1 -}; -function tokenizeBlockQuoteStart(effects, ok, nok) { - const self = this; - return start - function start(code) { - if (code === 62) { - const state = self.containerState; - if (!state.open) { - effects.enter('blockQuote', { - _container: true - }); - state.open = true; - } - effects.enter('blockQuotePrefix'); - effects.enter('blockQuoteMarker'); - effects.consume(code); - effects.exit('blockQuoteMarker'); - return after - } - return nok(code) - } - function after(code) { - if (markdownSpace(code)) { - effects.enter('blockQuotePrefixWhitespace'); - effects.consume(code); - effects.exit('blockQuotePrefixWhitespace'); - effects.exit('blockQuotePrefix'); - return ok - } - effects.exit('blockQuotePrefix'); - return ok(code) - } -} -function tokenizeBlockQuoteContinuation(effects, ok, nok) { - const self = this; - return contStart - function contStart(code) { - if (markdownSpace(code)) { - return factorySpace( - effects, - contBefore, - 'linePrefix', - self.parser.constructs.disable.null.includes('codeIndented') - ? undefined - : 4 - )(code) - } - return contBefore(code) - } - function contBefore(code) { - return effects.attempt(blockQuote, ok, nok)(code) - } -} -function exit$1(effects) { - effects.exit('blockQuote'); -} - -const characterEscape = { - name: 'characterEscape', - tokenize: tokenizeCharacterEscape -}; -function tokenizeCharacterEscape(effects, ok, nok) { - return start - function start(code) { - effects.enter('characterEscape'); - effects.enter('escapeMarker'); - effects.consume(code); - effects.exit('escapeMarker'); - return inside - } - function inside(code) { - if (asciiPunctuation(code)) { - effects.enter('characterEscapeValue'); - effects.consume(code); - effects.exit('characterEscapeValue'); - effects.exit('characterEscape'); - return ok - } - return nok(code) - } -} - const characterEntities = { AElig: 'Æ', AMP: '&', @@ -3691,9 +2984,813 @@ const characterEntities = { zwnj: '‌' }; -const own$5 = {}.hasOwnProperty; -function decodeNamedCharacterReference(value) { - return own$5.call(characterEntities, value) ? characterEntities[value] : false +const own$5 = {}.hasOwnProperty; +function decodeNamedCharacterReference(value) { + return own$5.call(characterEntities, value) ? characterEntities[value] : false +} + +function splice(list, start, remove, items) { + const end = list.length; + let chunkStart = 0; + let parameters; + if (start < 0) { + start = -start > end ? 0 : end + start; + } else { + start = start > end ? end : start; + } + remove = remove > 0 ? remove : 0; + if (items.length < 10000) { + parameters = Array.from(items); + parameters.unshift(start, remove); + list.splice(...parameters); + } else { + if (remove) list.splice(start, remove); + while (chunkStart < items.length) { + parameters = items.slice(chunkStart, chunkStart + 10000); + parameters.unshift(start, 0); + list.splice(...parameters); + chunkStart += 10000; + start += 10000; + } + } +} +function push(list, items) { + if (list.length > 0) { + splice(list, list.length, 0, items); + return list + } + return items +} + +const hasOwnProperty = {}.hasOwnProperty; +function combineExtensions(extensions) { + const all = {}; + let index = -1; + while (++index < extensions.length) { + syntaxExtension(all, extensions[index]); + } + return all +} +function syntaxExtension(all, extension) { + let hook; + for (hook in extension) { + const maybe = hasOwnProperty.call(all, hook) ? all[hook] : undefined; + const left = maybe || (all[hook] = {}); + const right = extension[hook]; + let code; + if (right) { + for (code in right) { + if (!hasOwnProperty.call(left, code)) left[code] = []; + const value = right[code]; + constructs( + left[code], + Array.isArray(value) ? value : value ? [value] : [] + ); + } + } + } +} +function constructs(existing, list) { + let index = -1; + const before = []; + while (++index < list.length) { +(list[index].add === 'after' ? existing : before).push(list[index]); + } + splice(existing, 0, 0, before); +} + +function decodeNumericCharacterReference(value, base) { + const code = Number.parseInt(value, base); + if ( + code < 9 || + code === 11 || + (code > 13 && code < 32) || + (code > 126 && code < 160) || + (code > 55_295 && code < 57_344) || + (code > 64_975 && code < 65_008) || + (code & 65_535) === 65_535 || + (code & 65_535) === 65_534 || + code > 1_114_111 + ) { + return '\uFFFD' + } + return String.fromCharCode(code) +} + +function normalizeIdentifier$1(value) { + return ( + value + .replace(/[\t\n\r ]+/g, ' ') + .replace(/^ | $/g, '') + .toLowerCase() + .toUpperCase() + ) +} + +const unicodePunctuationInternal = regexCheck(/\p{P}/u); +const asciiAlpha = regexCheck(/[A-Za-z]/); +const asciiAlphanumeric = regexCheck(/[\dA-Za-z]/); +const asciiAtext = regexCheck(/[#-'*+\--9=?A-Z^-~]/); +function asciiControl(code) { + return ( + code !== null && (code < 32 || code === 127) + ) +} +const asciiDigit = regexCheck(/\d/); +const asciiHexDigit = regexCheck(/[\dA-Fa-f]/); +const asciiPunctuation = regexCheck(/[!-/:-@[-`{-~]/); +function markdownLineEnding(code) { + return code !== null && code < -2 +} +function markdownLineEndingOrSpace(code) { + return code !== null && (code < 0 || code === 32) +} +function markdownSpace(code) { + return code === -2 || code === -1 || code === 32 +} +function unicodePunctuation(code) { + return asciiPunctuation(code) || unicodePunctuationInternal(code) +} +const unicodeWhitespace = regexCheck(/\s/); +function regexCheck(regex) { + return check + function check(code) { + return code !== null && code > -1 && regex.test(String.fromCharCode(code)) + } +} + +function factorySpace(effects, ok, type, max) { + const limit = max ? max - 1 : Number.POSITIVE_INFINITY; + let size = 0; + return start + function start(code) { + if (markdownSpace(code)) { + effects.enter(type); + return prefix(code) + } + return ok(code) + } + function prefix(code) { + if (markdownSpace(code) && size++ < limit) { + effects.consume(code); + return prefix + } + effects.exit(type); + return ok(code) + } +} + +const content$1 = { + tokenize: initializeContent +}; +function initializeContent(effects) { + const contentStart = effects.attempt( + this.parser.constructs.contentInitial, + afterContentStartConstruct, + paragraphInitial + ); + let previous; + return contentStart + function afterContentStartConstruct(code) { + if (code === null) { + effects.consume(code); + return + } + effects.enter('lineEnding'); + effects.consume(code); + effects.exit('lineEnding'); + return factorySpace(effects, contentStart, 'linePrefix') + } + function paragraphInitial(code) { + effects.enter('paragraph'); + return lineStart(code) + } + function lineStart(code) { + const token = effects.enter('chunkText', { + contentType: 'text', + previous + }); + if (previous) { + previous.next = token; + } + previous = token; + return data(code) + } + function data(code) { + if (code === null) { + effects.exit('chunkText'); + effects.exit('paragraph'); + effects.consume(code); + return + } + if (markdownLineEnding(code)) { + effects.consume(code); + effects.exit('chunkText'); + return lineStart + } + effects.consume(code); + return data + } +} + +const document$1 = { + tokenize: initializeDocument +}; +const containerConstruct = { + tokenize: tokenizeContainer +}; +function initializeDocument(effects) { + const self = this; + const stack = []; + let continued = 0; + let childFlow; + let childToken; + let lineStartOffset; + return start + function start(code) { + if (continued < stack.length) { + const item = stack[continued]; + self.containerState = item[1]; + return effects.attempt( + item[0].continuation, + documentContinue, + checkNewContainers + )(code) + } + return checkNewContainers(code) + } + function documentContinue(code) { + continued++; + if (self.containerState._closeFlow) { + self.containerState._closeFlow = undefined; + if (childFlow) { + closeFlow(); + } + const indexBeforeExits = self.events.length; + let indexBeforeFlow = indexBeforeExits; + let point; + while (indexBeforeFlow--) { + if ( + self.events[indexBeforeFlow][0] === 'exit' && + self.events[indexBeforeFlow][1].type === 'chunkFlow' + ) { + point = self.events[indexBeforeFlow][1].end; + break + } + } + exitContainers(continued); + let index = indexBeforeExits; + while (index < self.events.length) { + self.events[index][1].end = Object.assign({}, point); + index++; + } + splice( + self.events, + indexBeforeFlow + 1, + 0, + self.events.slice(indexBeforeExits) + ); + self.events.length = index; + return checkNewContainers(code) + } + return start(code) + } + function checkNewContainers(code) { + if (continued === stack.length) { + if (!childFlow) { + return documentContinued(code) + } + if (childFlow.currentConstruct && childFlow.currentConstruct.concrete) { + return flowStart(code) + } + self.interrupt = Boolean( + childFlow.currentConstruct && !childFlow._gfmTableDynamicInterruptHack + ); + } + self.containerState = {}; + return effects.check( + containerConstruct, + thereIsANewContainer, + thereIsNoNewContainer + )(code) + } + function thereIsANewContainer(code) { + if (childFlow) closeFlow(); + exitContainers(continued); + return documentContinued(code) + } + function thereIsNoNewContainer(code) { + self.parser.lazy[self.now().line] = continued !== stack.length; + lineStartOffset = self.now().offset; + return flowStart(code) + } + function documentContinued(code) { + self.containerState = {}; + return effects.attempt( + containerConstruct, + containerContinue, + flowStart + )(code) + } + function containerContinue(code) { + continued++; + stack.push([self.currentConstruct, self.containerState]); + return documentContinued(code) + } + function flowStart(code) { + if (code === null) { + if (childFlow) closeFlow(); + exitContainers(0); + effects.consume(code); + return + } + childFlow = childFlow || self.parser.flow(self.now()); + effects.enter('chunkFlow', { + contentType: 'flow', + previous: childToken, + _tokenizer: childFlow + }); + return flowContinue(code) + } + function flowContinue(code) { + if (code === null) { + writeToChild(effects.exit('chunkFlow'), true); + exitContainers(0); + effects.consume(code); + return + } + if (markdownLineEnding(code)) { + effects.consume(code); + writeToChild(effects.exit('chunkFlow')); + continued = 0; + self.interrupt = undefined; + return start + } + effects.consume(code); + return flowContinue + } + function writeToChild(token, eof) { + const stream = self.sliceStream(token); + if (eof) stream.push(null); + token.previous = childToken; + if (childToken) childToken.next = token; + childToken = token; + childFlow.defineSkip(token.start); + childFlow.write(stream); + if (self.parser.lazy[token.start.line]) { + let index = childFlow.events.length; + while (index--) { + if ( + childFlow.events[index][1].start.offset < lineStartOffset && + (!childFlow.events[index][1].end || + childFlow.events[index][1].end.offset > lineStartOffset) + ) { + return + } + } + const indexBeforeExits = self.events.length; + let indexBeforeFlow = indexBeforeExits; + let seen; + let point; + while (indexBeforeFlow--) { + if ( + self.events[indexBeforeFlow][0] === 'exit' && + self.events[indexBeforeFlow][1].type === 'chunkFlow' + ) { + if (seen) { + point = self.events[indexBeforeFlow][1].end; + break + } + seen = true; + } + } + exitContainers(continued); + index = indexBeforeExits; + while (index < self.events.length) { + self.events[index][1].end = Object.assign({}, point); + index++; + } + splice( + self.events, + indexBeforeFlow + 1, + 0, + self.events.slice(indexBeforeExits) + ); + self.events.length = index; + } + } + function exitContainers(size) { + let index = stack.length; + while (index-- > size) { + const entry = stack[index]; + self.containerState = entry[1]; + entry[0].exit.call(self, effects); + } + stack.length = size; + } + function closeFlow() { + childFlow.write([null]); + childToken = undefined; + childFlow = undefined; + self.containerState._closeFlow = undefined; + } +} +function tokenizeContainer(effects, ok, nok) { + return factorySpace( + effects, + effects.attempt(this.parser.constructs.document, ok, nok), + 'linePrefix', + this.parser.constructs.disable.null.includes('codeIndented') ? undefined : 4 + ) +} + +function classifyCharacter(code) { + if ( + code === null || + markdownLineEndingOrSpace(code) || + unicodeWhitespace(code) + ) { + return 1 + } + if (unicodePunctuation(code)) { + return 2 + } +} + +function resolveAll(constructs, events, context) { + const called = []; + let index = -1; + while (++index < constructs.length) { + const resolve = constructs[index].resolveAll; + if (resolve && !called.includes(resolve)) { + events = resolve(events, context); + called.push(resolve); + } + } + return events +} + +const attention = { + name: 'attention', + tokenize: tokenizeAttention, + resolveAll: resolveAllAttention +}; +function resolveAllAttention(events, context) { + let index = -1; + let open; + let group; + let text; + let openingSequence; + let closingSequence; + let use; + let nextEvents; + let offset; + while (++index < events.length) { + if ( + events[index][0] === 'enter' && + events[index][1].type === 'attentionSequence' && + events[index][1]._close + ) { + open = index; + while (open--) { + if ( + events[open][0] === 'exit' && + events[open][1].type === 'attentionSequence' && + events[open][1]._open && + context.sliceSerialize(events[open][1]).charCodeAt(0) === + context.sliceSerialize(events[index][1]).charCodeAt(0) + ) { + if ( + (events[open][1]._close || events[index][1]._open) && + (events[index][1].end.offset - events[index][1].start.offset) % 3 && + !( + (events[open][1].end.offset - + events[open][1].start.offset + + events[index][1].end.offset - + events[index][1].start.offset) % + 3 + ) + ) { + continue + } + use = + events[open][1].end.offset - events[open][1].start.offset > 1 && + events[index][1].end.offset - events[index][1].start.offset > 1 + ? 2 + : 1; + const start = Object.assign({}, events[open][1].end); + const end = Object.assign({}, events[index][1].start); + movePoint(start, -use); + movePoint(end, use); + openingSequence = { + type: use > 1 ? 'strongSequence' : 'emphasisSequence', + start, + end: Object.assign({}, events[open][1].end) + }; + closingSequence = { + type: use > 1 ? 'strongSequence' : 'emphasisSequence', + start: Object.assign({}, events[index][1].start), + end + }; + text = { + type: use > 1 ? 'strongText' : 'emphasisText', + start: Object.assign({}, events[open][1].end), + end: Object.assign({}, events[index][1].start) + }; + group = { + type: use > 1 ? 'strong' : 'emphasis', + start: Object.assign({}, openingSequence.start), + end: Object.assign({}, closingSequence.end) + }; + events[open][1].end = Object.assign({}, openingSequence.start); + events[index][1].start = Object.assign({}, closingSequence.end); + nextEvents = []; + if (events[open][1].end.offset - events[open][1].start.offset) { + nextEvents = push(nextEvents, [ + ['enter', events[open][1], context], + ['exit', events[open][1], context] + ]); + } + nextEvents = push(nextEvents, [ + ['enter', group, context], + ['enter', openingSequence, context], + ['exit', openingSequence, context], + ['enter', text, context] + ]); + nextEvents = push( + nextEvents, + resolveAll( + context.parser.constructs.insideSpan.null, + events.slice(open + 1, index), + context + ) + ); + nextEvents = push(nextEvents, [ + ['exit', text, context], + ['enter', closingSequence, context], + ['exit', closingSequence, context], + ['exit', group, context] + ]); + if (events[index][1].end.offset - events[index][1].start.offset) { + offset = 2; + nextEvents = push(nextEvents, [ + ['enter', events[index][1], context], + ['exit', events[index][1], context] + ]); + } else { + offset = 0; + } + splice(events, open - 1, index - open + 3, nextEvents); + index = open + nextEvents.length - offset - 2; + break + } + } + } + } + index = -1; + while (++index < events.length) { + if (events[index][1].type === 'attentionSequence') { + events[index][1].type = 'data'; + } + } + return events +} +function tokenizeAttention(effects, ok) { + const attentionMarkers = this.parser.constructs.attentionMarkers.null; + const previous = this.previous; + const before = classifyCharacter(previous); + let marker; + return start + function start(code) { + marker = code; + effects.enter('attentionSequence'); + return inside(code) + } + function inside(code) { + if (code === marker) { + effects.consume(code); + return inside + } + const token = effects.exit('attentionSequence'); + const after = classifyCharacter(code); + const open = + !after || (after === 2 && before) || attentionMarkers.includes(code); + const close = + !before || (before === 2 && after) || attentionMarkers.includes(previous); + token._open = Boolean(marker === 42 ? open : open && (before || !close)); + token._close = Boolean(marker === 42 ? close : close && (after || !open)); + return ok(code) + } +} +function movePoint(point, offset) { + point.column += offset; + point.offset += offset; + point._bufferIndex += offset; +} + +const autolink = { + name: 'autolink', + tokenize: tokenizeAutolink +}; +function tokenizeAutolink(effects, ok, nok) { + let size = 0; + return start + function start(code) { + effects.enter('autolink'); + effects.enter('autolinkMarker'); + effects.consume(code); + effects.exit('autolinkMarker'); + effects.enter('autolinkProtocol'); + return open + } + function open(code) { + if (asciiAlpha(code)) { + effects.consume(code); + return schemeOrEmailAtext + } + return emailAtext(code) + } + function schemeOrEmailAtext(code) { + if (code === 43 || code === 45 || code === 46 || asciiAlphanumeric(code)) { + size = 1; + return schemeInsideOrEmailAtext(code) + } + return emailAtext(code) + } + function schemeInsideOrEmailAtext(code) { + if (code === 58) { + effects.consume(code); + size = 0; + return urlInside + } + if ( + (code === 43 || code === 45 || code === 46 || asciiAlphanumeric(code)) && + size++ < 32 + ) { + effects.consume(code); + return schemeInsideOrEmailAtext + } + size = 0; + return emailAtext(code) + } + function urlInside(code) { + if (code === 62) { + effects.exit('autolinkProtocol'); + effects.enter('autolinkMarker'); + effects.consume(code); + effects.exit('autolinkMarker'); + effects.exit('autolink'); + return ok + } + if (code === null || code === 32 || code === 60 || asciiControl(code)) { + return nok(code) + } + effects.consume(code); + return urlInside + } + function emailAtext(code) { + if (code === 64) { + effects.consume(code); + return emailAtSignOrDot + } + if (asciiAtext(code)) { + effects.consume(code); + return emailAtext + } + return nok(code) + } + function emailAtSignOrDot(code) { + return asciiAlphanumeric(code) ? emailLabel(code) : nok(code) + } + function emailLabel(code) { + if (code === 46) { + effects.consume(code); + size = 0; + return emailAtSignOrDot + } + if (code === 62) { + effects.exit('autolinkProtocol').type = 'autolinkEmail'; + effects.enter('autolinkMarker'); + effects.consume(code); + effects.exit('autolinkMarker'); + effects.exit('autolink'); + return ok + } + return emailValue(code) + } + function emailValue(code) { + if ((code === 45 || asciiAlphanumeric(code)) && size++ < 63) { + const next = code === 45 ? emailValue : emailLabel; + effects.consume(code); + return next + } + return nok(code) + } +} + +const blankLine = { + tokenize: tokenizeBlankLine, + partial: true +}; +function tokenizeBlankLine(effects, ok, nok) { + return start + function start(code) { + return markdownSpace(code) + ? factorySpace(effects, after, 'linePrefix')(code) + : after(code) + } + function after(code) { + return code === null || markdownLineEnding(code) ? ok(code) : nok(code) + } +} + +const blockQuote = { + name: 'blockQuote', + tokenize: tokenizeBlockQuoteStart, + continuation: { + tokenize: tokenizeBlockQuoteContinuation + }, + exit: exit$1 +}; +function tokenizeBlockQuoteStart(effects, ok, nok) { + const self = this; + return start + function start(code) { + if (code === 62) { + const state = self.containerState; + if (!state.open) { + effects.enter('blockQuote', { + _container: true + }); + state.open = true; + } + effects.enter('blockQuotePrefix'); + effects.enter('blockQuoteMarker'); + effects.consume(code); + effects.exit('blockQuoteMarker'); + return after + } + return nok(code) + } + function after(code) { + if (markdownSpace(code)) { + effects.enter('blockQuotePrefixWhitespace'); + effects.consume(code); + effects.exit('blockQuotePrefixWhitespace'); + effects.exit('blockQuotePrefix'); + return ok + } + effects.exit('blockQuotePrefix'); + return ok(code) + } +} +function tokenizeBlockQuoteContinuation(effects, ok, nok) { + const self = this; + return contStart + function contStart(code) { + if (markdownSpace(code)) { + return factorySpace( + effects, + contBefore, + 'linePrefix', + self.parser.constructs.disable.null.includes('codeIndented') + ? undefined + : 4 + )(code) + } + return contBefore(code) + } + function contBefore(code) { + return effects.attempt(blockQuote, ok, nok)(code) + } +} +function exit$1(effects) { + effects.exit('blockQuote'); +} + +const characterEscape = { + name: 'characterEscape', + tokenize: tokenizeCharacterEscape +}; +function tokenizeCharacterEscape(effects, ok, nok) { + return start + function start(code) { + effects.enter('characterEscape'); + effects.enter('escapeMarker'); + effects.consume(code); + effects.exit('escapeMarker'); + return inside + } + function inside(code) { + if (asciiPunctuation(code)) { + effects.enter('characterEscapeValue'); + effects.consume(code); + effects.exit('characterEscapeValue'); + effects.exit('characterEscape'); + return ok + } + return nok(code) + } } const characterReference = { @@ -4664,16 +4761,6 @@ function factoryWhitespace(effects, ok) { } } -function normalizeIdentifier(value) { - return ( - value - .replace(/[\t\n\r ]+/g, ' ') - .replace(/^ | $/g, '') - .toLowerCase() - .toUpperCase() - ) -} - const definition$1 = { name: 'definition', tokenize: tokenizeDefinition @@ -4702,7 +4789,7 @@ function tokenizeDefinition(effects, ok, nok) { )(code) } function labelAfter(code) { - identifier = normalizeIdentifier( + identifier = normalizeIdentifier$1( self.sliceSerialize(self.events[self.events.length - 1][1]).slice(1, -1) ); if (code === 58) { @@ -5847,7 +5934,7 @@ function tokenizeLabelEnd(effects, ok, nok) { return labelEndNok(code) } defined = self.parser.defined.includes( - normalizeIdentifier( + normalizeIdentifier$1( self.sliceSerialize({ start: labelStart.end, end: self.now() @@ -5976,7 +6063,7 @@ function tokenizeReferenceFull(effects, ok, nok) { } function referenceFullAfter(code) { return self.parser.defined.includes( - normalizeIdentifier( + normalizeIdentifier$1( self.sliceSerialize(self.events[self.events.length - 1][1]).slice(1, -1) ) ) @@ -6117,7 +6204,7 @@ function tokenizeThematicBreak(effects, ok, nok) { } } -const list$1 = { +const list$2 = { name: 'list', tokenize: tokenizeListStart, continuation: { @@ -6255,7 +6342,7 @@ function tokenizeListContinuation(effects, ok, nok) { self.interrupt = undefined; return factorySpace( effects, - effects.attempt(list$1, ok, nok), + effects.attempt(list$2, ok, nok), 'linePrefix', self.parser.constructs.disable.null.includes('codeIndented') ? undefined @@ -6905,19 +6992,19 @@ function serializeChunks(chunks, expandTabs) { } const document = { - [42]: list$1, - [43]: list$1, - [45]: list$1, - [48]: list$1, - [49]: list$1, - [50]: list$1, - [51]: list$1, - [52]: list$1, - [53]: list$1, - [54]: list$1, - [55]: list$1, - [56]: list$1, - [57]: list$1, + [42]: list$2, + [43]: list$2, + [45]: list$2, + [48]: list$2, + [49]: list$2, + [50]: list$2, + [51]: list$2, + [52]: list$2, + [53]: list$2, + [54]: list$2, + [55]: list$2, + [56]: list$2, + [57]: list$2, [62]: blockQuote }; const contentInitial = { @@ -7002,6 +7089,12 @@ function parse$1(options) { } } +function postprocess(events) { + while (!subtokenize(events)) { + } + return events +} + const search = /[\0\t\n\r]/g; function preprocess() { let column = 1; @@ -7016,7 +7109,11 @@ function preprocess() { let startPosition; let endPosition; let code; - value = buffer + value.toString(encoding); + value = + buffer + + (typeof value === 'string' + ? value.toString() + : new TextDecoder(encoding || undefined).decode(value)); startPosition = 0; buffer = ''; if (start) { @@ -7081,30 +7178,6 @@ function preprocess() { } } -function postprocess(events) { - while (!subtokenize(events)) { - } - return events -} - -function decodeNumericCharacterReference(value, base) { - const code = Number.parseInt(value, base); - if ( - code < 9 || - code === 11 || - (code > 13 && code < 32) || - (code > 126 && code < 160) || - (code > 55295 && code < 57344) || - (code > 64975 && code < 65008) || - (code & 65535) === 65535 || - (code & 65535) === 65534 || - code > 1114111 - ) { - return '\uFFFD' - } - return String.fromCharCode(code) -} - const characterEscapeOrReference = /\\([!-/:-@[-`{-~])|&(#(?:\d{1,7}|x[\da-f]{1,6})|[\da-z]{1,31});/gi; function decodeString(value) { @@ -7124,18 +7197,17 @@ function decode($0, $1, $2) { } const own$4 = {}.hasOwnProperty; -const fromMarkdown = - function (value, encoding, options) { - if (typeof encoding !== 'string') { - options = encoding; - encoding = undefined; - } - return compiler(options)( - postprocess( - parse$1(options).document().write(preprocess()(value, encoding, true)) - ) +function fromMarkdown(value, encoding, options) { + if (typeof encoding !== 'string') { + options = encoding; + encoding = undefined; + } + return compiler(options)( + postprocess( + parse$1(options).document().write(preprocess()(value, encoding, true)) ) - }; + ) +} function compiler(options) { const config = { transforms: [], @@ -7250,8 +7322,7 @@ function compiler(options) { exit, buffer, resume, - setData, - getData + data }; const listStack = []; let index = -1; @@ -7289,7 +7360,7 @@ function compiler(options) { handler.call(context, undefined, tail[0]); } tree.position = { - start: point$2( + start: point$3( events.length > 0 ? events[0][1].start : { @@ -7298,7 +7369,7 @@ function compiler(options) { offset: 0 } ), - end: point$2( + end: point$3( events.length > 0 ? events[events.length - 2][1].end : { @@ -7324,37 +7395,42 @@ function compiler(options) { let atMarker; while (++index <= length) { const event = events[index]; - if ( - event[1].type === 'listUnordered' || - event[1].type === 'listOrdered' || - event[1].type === 'blockQuote' - ) { - if (event[0] === 'enter') { - containerBalance++; - } else { - containerBalance--; + switch (event[1].type) { + case 'listUnordered': + case 'listOrdered': + case 'blockQuote': { + if (event[0] === 'enter') { + containerBalance++; + } else { + containerBalance--; + } + atMarker = undefined; + break } - atMarker = undefined; - } else if (event[1].type === 'lineEndingBlank') { - if (event[0] === 'enter') { - if ( - listItem && - !atMarker && - !containerBalance && - !firstBlankLineIndex - ) { - firstBlankLineIndex = index; + case 'lineEndingBlank': { + if (event[0] === 'enter') { + if ( + listItem && + !atMarker && + !containerBalance && + !firstBlankLineIndex + ) { + firstBlankLineIndex = index; + } + atMarker = undefined; } + break + } + case 'linePrefix': + case 'listItemValue': + case 'listItemMarker': + case 'listItemPrefix': + case 'listItemPrefixWhitespace': { + break + } + default: { atMarker = undefined; } - } else if ( - event[1].type === 'linePrefix' || - event[1].type === 'listItemValue' || - event[1].type === 'listItemMarker' || - event[1].type === 'listItemPrefix' || - event[1].type === 'listItemPrefixWhitespace' - ) ; else { - atMarker = undefined; } if ( (!containerBalance && @@ -7406,13 +7482,14 @@ function compiler(options) { length++; } if (event[1].type === 'listItemPrefix') { - listItem = { + const item = { type: 'listItem', _spread: false, start: Object.assign({}, event[1].start), end: undefined }; - events.splice(index, 0, ['enter', listItem, event[2]]); + listItem = item; + events.splice(index, 0, ['enter', item, event[2]]); index++; length++; firstBlankLineIndex = undefined; @@ -7423,12 +7500,6 @@ function compiler(options) { events[start][1]._spread = listSpread; return length } - function setData(key, value) { - data[key] = value; - } - function getData(key) { - return data[key] - } function opener(create, and) { return open function open(token) { @@ -7444,13 +7515,14 @@ function compiler(options) { } function enter(node, token, errorHandler) { const parent = this.stack[this.stack.length - 1]; - parent.children.push(node); + const siblings = parent.children; + siblings.push(node); this.stack.push(node); this.tokenStack.push([token, errorHandler]); node.position = { - start: point$2(token.start) + start: point$3(token.start), + end: undefined }; - return node } function closer(and) { return close @@ -7467,7 +7539,7 @@ function compiler(options) { 'Cannot close `' + token.type + '` (' + - stringifyPosition$1({ + stringifyPosition$2({ start: token.start, end: token.end }) + @@ -7481,20 +7553,19 @@ function compiler(options) { handler.call(this, token, open[0]); } } - node.position.end = point$2(token.end); - return node + node.position.end = point$3(token.end); } function resume() { - return toString(this.stack.pop()) + return toString$2(this.stack.pop()) } function onenterlistordered() { - setData('expectingFirstListItemValue', true); + this.data.expectingFirstListItemValue = true; } function onenterlistitemvalue(token) { - if (getData('expectingFirstListItemValue')) { + if (this.data.expectingFirstListItemValue) { const ancestor = this.stack[this.stack.length - 2]; ancestor.start = Number.parseInt(this.sliceSerialize(token), 10); - setData('expectingFirstListItemValue'); + this.data.expectingFirstListItemValue = undefined; } } function onexitcodefencedfenceinfo() { @@ -7508,15 +7579,15 @@ function compiler(options) { node.meta = data; } function onexitcodefencedfence() { - if (getData('flowCodeInside')) return + if (this.data.flowCodeInside) return this.buffer(); - setData('flowCodeInside', true); + this.data.flowCodeInside = true; } function onexitcodefenced() { const data = this.resume(); const node = this.stack[this.stack.length - 1]; node.value = data.replace(/^(\r?\n|\r)|(\r?\n|\r)$/g, ''); - setData('flowCodeInside'); + this.data.flowCodeInside = undefined; } function onexitcodeindented() { const data = this.resume(); @@ -7527,7 +7598,7 @@ function compiler(options) { const label = this.resume(); const node = this.stack[this.stack.length - 1]; node.label = label; - node.identifier = normalizeIdentifier( + node.identifier = normalizeIdentifier$1( this.sliceSerialize(token) ).toLowerCase(); } @@ -7549,42 +7620,44 @@ function compiler(options) { } } function onexitsetextheadingtext() { - setData('setextHeadingSlurpLineEnding', true); + this.data.setextHeadingSlurpLineEnding = true; } function onexitsetextheadinglinesequence(token) { const node = this.stack[this.stack.length - 1]; - node.depth = this.sliceSerialize(token).charCodeAt(0) === 61 ? 1 : 2; + node.depth = this.sliceSerialize(token).codePointAt(0) === 61 ? 1 : 2; } function onexitsetextheading() { - setData('setextHeadingSlurpLineEnding'); + this.data.setextHeadingSlurpLineEnding = undefined; } function onenterdata(token) { const node = this.stack[this.stack.length - 1]; - let tail = node.children[node.children.length - 1]; + const siblings = node.children; + let tail = siblings[siblings.length - 1]; if (!tail || tail.type !== 'text') { tail = text(); tail.position = { - start: point$2(token.start) + start: point$3(token.start), + end: undefined }; - node.children.push(tail); + siblings.push(tail); } this.stack.push(tail); } function onexitdata(token) { const tail = this.stack.pop(); tail.value += this.sliceSerialize(token); - tail.position.end = point$2(token.end); + tail.position.end = point$3(token.end); } function onexitlineending(token) { const context = this.stack[this.stack.length - 1]; - if (getData('atHardBreak')) { + if (this.data.atHardBreak) { const tail = context.children[context.children.length - 1]; - tail.position.end = point$2(token.end); - setData('atHardBreak'); + tail.position.end = point$3(token.end); + this.data.atHardBreak = undefined; return } if ( - !getData('setextHeadingSlurpLineEnding') && + !this.data.setextHeadingSlurpLineEnding && config.canContainEols.includes(context.type) ) { onenterdata.call(this, token); @@ -7592,7 +7665,7 @@ function compiler(options) { } } function onexithardbreak() { - setData('atHardBreak', true); + this.data.atHardBreak = true; } function onexithtmlflow() { const data = this.resume(); @@ -7611,8 +7684,8 @@ function compiler(options) { } function onexitlink() { const node = this.stack[this.stack.length - 1]; - if (getData('inReference')) { - const referenceType = getData('referenceType') || 'shortcut'; + if (this.data.inReference) { + const referenceType = this.data.referenceType || 'shortcut'; node.type += 'Reference'; node.referenceType = referenceType; delete node.url; @@ -7621,12 +7694,12 @@ function compiler(options) { delete node.identifier; delete node.label; } - setData('referenceType'); + this.data.referenceType = undefined; } function onexitimage() { const node = this.stack[this.stack.length - 1]; - if (getData('inReference')) { - const referenceType = getData('referenceType') || 'shortcut'; + if (this.data.inReference) { + const referenceType = this.data.referenceType || 'shortcut'; node.type += 'Reference'; node.referenceType = referenceType; delete node.url; @@ -7635,19 +7708,19 @@ function compiler(options) { delete node.identifier; delete node.label; } - setData('referenceType'); + this.data.referenceType = undefined; } function onexitlabeltext(token) { const string = this.sliceSerialize(token); const ancestor = this.stack[this.stack.length - 2]; ancestor.label = decodeString(string); - ancestor.identifier = normalizeIdentifier(string).toLowerCase(); + ancestor.identifier = normalizeIdentifier$1(string).toLowerCase(); } function onexitlabel() { const fragment = this.stack[this.stack.length - 1]; const value = this.resume(); const node = this.stack[this.stack.length - 1]; - setData('inReference', true); + this.data.inReference = true; if (node.type === 'link') { const children = fragment.children; node.children = children; @@ -7666,40 +7739,40 @@ function compiler(options) { node.title = data; } function onexitresource() { - setData('inReference'); + this.data.inReference = undefined; } function onenterreference() { - setData('referenceType', 'collapsed'); + this.data.referenceType = 'collapsed'; } function onexitreferencestring(token) { const label = this.resume(); const node = this.stack[this.stack.length - 1]; node.label = label; - node.identifier = normalizeIdentifier( + node.identifier = normalizeIdentifier$1( this.sliceSerialize(token) ).toLowerCase(); - setData('referenceType', 'full'); + this.data.referenceType = 'full'; } function onexitcharacterreferencemarker(token) { - setData('characterReferenceType', token.type); + this.data.characterReferenceType = token.type; } function onexitcharacterreferencevalue(token) { const data = this.sliceSerialize(token); - const type = getData('characterReferenceType'); + const type = this.data.characterReferenceType; let value; if (type) { value = decodeNumericCharacterReference( data, type === 'characterReferenceMarkerNumeric' ? 10 : 16 ); - setData('characterReferenceType'); + this.data.characterReferenceType = undefined; } else { const result = decodeNamedCharacterReference(data); value = result; } const tail = this.stack.pop(); tail.value += value; - tail.position.end = point$2(token.end); + tail.position.end = point$3(token.end); } function onexitautolinkprotocol(token) { onexitdata.call(this, token); @@ -7749,7 +7822,7 @@ function compiler(options) { function heading() { return { type: 'heading', - depth: undefined, + depth: 0, children: [] } } @@ -7821,7 +7894,7 @@ function compiler(options) { } } } -function point$2(d) { +function point$3(d) { return { line: d.line, column: d.column, @@ -7843,20 +7916,28 @@ function extension(combined, extension) { let key; for (key in extension) { if (own$4.call(extension, key)) { - if (key === 'canContainEols') { - const right = extension[key]; - if (right) { - combined[key].push(...right); + switch (key) { + case 'canContainEols': { + const right = extension[key]; + if (right) { + combined[key].push(...right); + } + break } - } else if (key === 'transforms') { - const right = extension[key]; - if (right) { - combined[key].push(...right); + case 'transforms': { + const right = extension[key]; + if (right) { + combined[key].push(...right); + } + break } - } else if (key === 'enter' || key === 'exit') { - const right = extension[key]; - if (right) { - Object.assign(combined[key], right); + case 'enter': + case 'exit': { + const right = extension[key]; + if (right) { + Object.assign(combined[key], right); + } + break } } } @@ -7868,14 +7949,14 @@ function defaultOnError(left, right) { 'Cannot close `' + left.type + '` (' + - stringifyPosition$1({ + stringifyPosition$2({ start: left.start, end: left.end }) + '): a different token (`' + right.type + '`, ' + - stringifyPosition$1({ + stringifyPosition$2({ start: right.start, end: right.end }) + @@ -7886,7 +7967,7 @@ function defaultOnError(left, right) { 'Cannot close document, a token (`' + right.type + '`, ' + - stringifyPosition$1({ + stringifyPosition$2({ start: right.start, end: right.end }) + @@ -7896,17 +7977,16 @@ function defaultOnError(left, right) { } function remarkParse(options) { - const parser = (doc) => { - const settings = (this.data('settings')); - return fromMarkdown( - doc, - Object.assign({}, settings, options, { - extensions: this.data('micromarkExtensions') || [], - mdastExtensions: this.data('fromMarkdownExtensions') || [] - }) - ) - }; - Object.assign(this, {Parser: parser}); + const self = this; + self.parser = parser; + function parser(doc) { + return fromMarkdown(doc, { + ...self.data('settings'), + ...options, + extensions: self.data('micromarkExtensions') || [], + mdastExtensions: self.data('fromMarkdownExtensions') || [] + }) + } } const own$3 = {}.hasOwnProperty; @@ -7929,6 +8009,7 @@ function zwitch(key, options) { return one } +const own$2 = {}.hasOwnProperty; function configure(base, extension) { let index = -1; let key; @@ -7938,16 +8019,41 @@ function configure(base, extension) { } } for (key in extension) { - if (key === 'extensions') ; else if (key === 'unsafe' || key === 'join') { - base[key] = [...(base[key] || []), ...(extension[key] || [])]; - } else if (key === 'handlers') { - base[key] = Object.assign(base[key], extension[key] || {}); - } else { - base.options[key] = extension[key]; + if (own$2.call(extension, key)) { + switch (key) { + case 'extensions': { + break + } + case 'unsafe': { + list$1(base[key], extension[key]); + break + } + case 'join': { + list$1(base[key], extension[key]); + break + } + case 'handlers': { + map$4(base[key], extension[key]); + break + } + default: { + base.options[key] = extension[key]; + } + } } } return base } +function list$1(left, right) { + if (right) { + left.push(...right); + } +} +function map$4(left, right) { + if (right) { + Object.assign(left, right); + } +} function blockquote(node, _, state, info) { const exit = state.enter('blockquote'); @@ -8025,7 +8131,7 @@ function longestStreak(value, substring) { function formatCodeAsIndented(node, state) { return Boolean( - !state.options.fences && + state.options.fences === false && node.value && !node.lang && /[^ \r\n]/.test(node.value) && @@ -8195,176 +8301,196 @@ function emphasisPeek(_, _1, state) { return state.options.emphasis || '*' } -const convert = +const convert$A = ( function (test) { - if (test === undefined || test === null) { - return ok + if (test === null || test === undefined) { + return ok$A } - if (typeof test === 'string') { - return typeFactory(test) + if (typeof test === 'function') { + return castFactory$A(test) } if (typeof test === 'object') { - return Array.isArray(test) ? anyFactory(test) : propsFactory(test) + return Array.isArray(test) ? anyFactory$A(test) : propsFactory$A(test) } - if (typeof test === 'function') { - return castFactory(test) + if (typeof test === 'string') { + return typeFactory$A(test) } throw new Error('Expected function, string, or object as test') } ); -function anyFactory(tests) { +function anyFactory$A(tests) { const checks = []; let index = -1; while (++index < tests.length) { - checks[index] = convert(tests[index]); + checks[index] = convert$A(tests[index]); } - return castFactory(any) + return castFactory$A(any) function any(...parameters) { let index = -1; while (++index < checks.length) { - if (checks[index].call(this, ...parameters)) return true + if (checks[index].apply(this, parameters)) return true } return false } } -function propsFactory(check) { - return castFactory(all) +function propsFactory$A(check) { + const checkAsRecord = (check); + return castFactory$A(all) function all(node) { + const nodeAsRecord = ( + (node) + ); let key; for (key in check) { - if (node[key] !== check[key]) return false + if (nodeAsRecord[key] !== checkAsRecord[key]) return false } return true } } -function typeFactory(check) { - return castFactory(type) +function typeFactory$A(check) { + return castFactory$A(type) function type(node) { return node && node.type === check } } -function castFactory(check) { - return assertion - function assertion(node, ...parameters) { +function castFactory$A(testFunction) { + return check + function check(value, index, parent) { return Boolean( - node && - typeof node === 'object' && - 'type' in node && - Boolean(check.call(this, node, ...parameters)) + looksLikeANode(value) && + testFunction.call( + this, + value, + typeof index === 'number' ? index : undefined, + parent || undefined + ) ) } } -function ok() { +function ok$A() { return true } +function looksLikeANode(value) { + return value !== null && typeof value === 'object' && 'type' in value +} -function color$2(d) { +function color$B(d) { return '\u001B[33m' + d + '\u001B[39m' } -const CONTINUE$1 = true; -const EXIT$1 = false; -const SKIP$1 = 'skip'; -const visitParents$1 = - ( - function (tree, test, visitor, reverse) { - if (typeof test === 'function' && typeof visitor !== 'function') { - reverse = visitor; - visitor = test; - test = null; - } - const is = convert(test); - const step = reverse ? -1 : 1; - factory(tree, undefined, [])(); - function factory(node, index, parents) { - const value = node && typeof node === 'object' ? node : {}; - if (typeof value.type === 'string') { - const name = - typeof value.tagName === 'string' - ? value.tagName - : - typeof value.name === 'string' - ? value.name - : undefined; - Object.defineProperty(visit, 'name', { - value: - 'node (' + color$2(node.type + (name ? '<' + name + '>' : '')) + ')' - }); +const empty = []; +const CONTINUE$A = true; +const EXIT$A = false; +const SKIP$A = 'skip'; +function visitParents$A(tree, test, visitor, reverse) { + let check; + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + } else { + check = test; + } + const is = convert$A(check); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = ( + node && typeof node === 'object' ? node : {} + ); + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$B(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = empty; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || undefined)) { + result = toResult$A(visitor(node, parents)); + if (result[0] === EXIT$A) { + return result } - return visit - function visit() { - let result = []; - let subresult; - let offset; - let grandparents; - if (!test || is(node, index, parents[parents.length - 1] || null)) { - result = toResult$1(visitor(node, parents)); - if (result[0] === EXIT$1) { - return result - } - } - if (node.children && result[0] !== SKIP$1) { - offset = (reverse ? node.children.length : -1) + step; - grandparents = parents.concat(node); - while (offset > -1 && offset < node.children.length) { - subresult = factory(node.children[offset], offset, grandparents)(); - if (subresult[0] === EXIT$1) { - return subresult - } - offset = - typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + if ('children' in node && node.children) { + const nodeAsParent = (node); + if (nodeAsParent.children && result[0] !== SKIP$A) { + offset = (reverse ? nodeAsParent.children.length : -1) + step; + grandparents = parents.concat(nodeAsParent); + while (offset > -1 && offset < nodeAsParent.children.length) { + const child = nodeAsParent.children[offset]; + subresult = factory(child, offset, grandparents)(); + if (subresult[0] === EXIT$A) { + return subresult } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; } - return result } } + return result } - ); -function toResult$1(value) { + } +} +function toResult$A(value) { if (Array.isArray(value)) { return value } if (typeof value === 'number') { - return [CONTINUE$1, value] + return [CONTINUE$A, value] } - return [value] + return value === null || value === undefined ? empty : [value] } -const visit$1 = - ( - function (tree, test, visitor, reverse) { - if (typeof test === 'function' && typeof visitor !== 'function') { - reverse = visitor; - visitor = test; - test = null; - } - visitParents$1(tree, test, overload, reverse); - function overload(node, parents) { - const parent = parents[parents.length - 1]; - return visitor( - node, - parent ? parent.children.indexOf(node) : null, - parent - ) - } - } - ); +function visit$A(tree, testOrVisitor, visitorOrReverse, maybeReverse) { + let reverse; + let test; + let visitor; + if ( + typeof testOrVisitor === 'function' && + typeof visitorOrReverse !== 'function' + ) { + test = undefined; + visitor = testOrVisitor; + reverse = visitorOrReverse; + } else { + test = testOrVisitor; + visitor = visitorOrReverse; + reverse = maybeReverse; + } + visitParents$A(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + const index = parent ? parent.children.indexOf(node) : undefined; + return visitor(node, index, parent) + } +} function formatHeadingAsSetext(node, state) { let literalWithBreak = false; - visit$1(node, (node) => { + visit$A(node, function (node) { if ( ('value' in node && /\r?\n|\r/.test(node.value)) || node.type === 'break' ) { literalWithBreak = true; - return EXIT$1 + return EXIT$A } }); return Boolean( (!node.depth || node.depth < 3) && - toString(node) && + toString$2(node) && (state.options.setext || literalWithBreak) ) } @@ -8502,35 +8628,19 @@ function imageReference(node, _, state, info) { ...tracker.current() }); subexit(); - state.stack = stack; - exit(); - if (type === 'full' || !alt || alt !== reference) { - value += tracker.move(reference + ']'); - } else if (type === 'shortcut') { - value = value.slice(0, -1); - } else { - value += tracker.move(']'); - } - return value -} -function imageReferencePeek() { - return '!' -} - -function patternCompile(pattern) { - if (!pattern._compiled) { - const before = - (pattern.atBreak ? '[\\r\\n][\\t ]*' : '') + - (pattern.before ? '(?:' + pattern.before + ')' : ''); - pattern._compiled = new RegExp( - (before ? '(' + before + ')' : '') + - (/[|\\{}()[\]^$+*?.-]/.test(pattern.character) ? '\\' : '') + - pattern.character + - (pattern.after ? '(?:' + pattern.after + ')' : ''), - 'g' - ); + state.stack = stack; + exit(); + if (type === 'full' || !alt || alt !== reference) { + value += tracker.move(reference + ']'); + } else if (type === 'shortcut') { + value = value.slice(0, -1); + } else { + value += tracker.move(']'); } - return pattern._compiled + return value +} +function imageReferencePeek() { + return '!' } inlineCode.peek = inlineCodePeek; @@ -8549,7 +8659,7 @@ function inlineCode(node, _, state) { } while (++index < state.unsafe.length) { const pattern = state.unsafe[index]; - const expression = patternCompile(pattern); + const expression = state.compilePattern(pattern); let match; if (!pattern.atBreak) continue while ((match = expression.exec(value))) { @@ -8570,7 +8680,7 @@ function inlineCodePeek() { } function formatLinkAsAutolink(node, state) { - const raw = toString(node); + const raw = toString$2(node); return Boolean( !state.options.resourceLink && node.url && @@ -8749,31 +8859,6 @@ function checkBulletOrdered(state) { return marker } -function checkBulletOrderedOther(state) { - const bulletOrdered = checkBulletOrdered(state); - const bulletOrderedOther = state.options.bulletOrderedOther; - if (!bulletOrderedOther) { - return bulletOrdered === '.' ? ')' : '.' - } - if (bulletOrderedOther !== '.' && bulletOrderedOther !== ')') { - throw new Error( - 'Cannot serialize items with `' + - bulletOrderedOther + - '` for `options.bulletOrderedOther`, expected `*`, `+`, or `-`' - ) - } - if (bulletOrderedOther === bulletOrdered) { - throw new Error( - 'Expected `bulletOrdered` (`' + - bulletOrdered + - '`) and `bulletOrderedOther` (`' + - bulletOrderedOther + - '`) to be different' - ) - } - return bulletOrderedOther -} - function checkRule(state) { const marker = state.options.rule || '*'; if (marker !== '*' && marker !== '-' && marker !== '_') { @@ -8791,20 +8876,12 @@ function list(node, parent, state, info) { const bulletCurrent = state.bulletCurrent; let bullet = node.ordered ? checkBulletOrdered(state) : checkBullet(state); const bulletOther = node.ordered - ? checkBulletOrderedOther(state) + ? bullet === '.' + ? ')' + : '.' : checkBulletOther(state); - const bulletLastUsed = state.bulletLastUsed; - let useDifferentMarker = false; - if ( - parent && - (node.ordered - ? state.options.bulletOrderedOther - : state.options.bulletOther) && - bulletLastUsed && - bullet === bulletLastUsed - ) { - useDifferentMarker = true; - } + let useDifferentMarker = + parent && state.bulletLastUsed ? bullet === state.bulletLastUsed : false; if (!node.ordered) { const firstListItem = node.children ? node.children[0] : undefined; if ( @@ -8850,10 +8927,7 @@ function list(node, parent, state, info) { } function checkListItemIndent(state) { - const style = state.options.listItemIndent || 'tab'; - if (style === 1 || style === '1') { - return 'one' - } + const style = state.options.listItemIndent || 'one'; if (style !== 'tab' && style !== 'one' && style !== 'mixed') { throw new Error( 'Cannot serialize items with `' + @@ -8912,25 +8986,28 @@ function paragraph(node, _, state, info) { return value } -const phrasing = ( - convert([ - 'break', - 'delete', - 'emphasis', - 'footnote', - 'footnoteReference', - 'image', - 'imageReference', - 'inlineCode', - 'link', - 'linkReference', - 'strong', - 'text' - ]) -); +const phrasing = + ( + convert$A([ + 'break', + 'delete', + 'emphasis', + 'footnote', + 'footnoteReference', + 'image', + 'imageReference', + 'inlineCode', + 'link', + 'linkReference', + 'strong', + 'text' + ]) + ); function root(node, _, state, info) { - const hasPhrasing = node.children.some((d) => phrasing(d)); + const hasPhrasing = node.children.some(function (d) { + return phrasing(d) + }); const fn = hasPhrasing ? state.containerPhrasing : state.containerFlow; return fn.call(state, node, info) } @@ -9024,16 +9101,6 @@ function joinDefaults(left, right, parent, state) { ) { return false } - if ( - left.type === 'list' && - left.type === right.type && - Boolean(left.ordered) === Boolean(right.ordered) && - !(left.ordered - ? state.options.bulletOrderedOther - : state.options.bulletOther) - ) { - return false - } if ('spread' in parent && typeof parent.spread === 'boolean') { if ( left.type === 'paragraph' && @@ -9149,6 +9216,22 @@ function association(node) { return decodeString(node.identifier) } +function compilePattern(pattern) { + if (!pattern._compiled) { + const before = + (pattern.atBreak ? '[\\r\\n][\\t ]*' : '') + + (pattern.before ? '(?:' + pattern.before + ')' : ''); + pattern._compiled = new RegExp( + (before ? '(' + before + ')' : '') + + (/[|\\{}()[\]^$+*?.-]/.test(pattern.character) ? '\\' : '') + + pattern.character + + (pattern.after ? '(?:' + pattern.after + ')' : ''), + 'g' + ); + } + return pattern._compiled +} + function containerPhrasing(parent, state, info) { const indexStack = state.indexStack; const children = parent.children || []; @@ -9280,7 +9363,7 @@ function safe(state, input, config) { if (!patternInScope(state.stack, pattern)) { continue } - const expression = patternCompile(pattern); + const expression = state.compilePattern(pattern); let match; while ((match = expression.exec(value))) { const before = 'before' in pattern || Boolean(pattern.atBreak); @@ -9397,19 +9480,19 @@ function toMarkdown(tree, options = {}) { containerPhrasing: containerPhrasingBound, containerFlow: containerFlowBound, createTracker: track, + compilePattern, safe: safeBound, stack: [], - unsafe: [], - join: [], - handlers: {}, + unsafe: [...unsafe], + join: [...join], + handlers: {...handle}, options: {}, indexStack: [], handle: undefined }; - configure(state, {unsafe, join, handlers: handle}); configure(state, options); if (state.options.tightDefinitions) { - configure(state, {join: [joinDefinition]}); + state.join.push(joinDefinition); } state.handle = zwitch('type', { invalid, @@ -9441,7 +9524,8 @@ function toMarkdown(tree, options = {}) { function invalid(value) { throw new Error('Cannot handle value `' + value + '`, expected node') } -function unknown(node) { +function unknown(value) { + const node = (value); throw new Error('Cannot handle unknown node `' + node.type + '`') } function joinDefinition(left, right) { @@ -9453,2326 +9537,2332 @@ function containerPhrasingBound(parent, info) { return containerPhrasing(parent, this, info) } function containerFlowBound(parent, info) { - return containerFlow(parent, this, info) -} -function safeBound(value, config) { - return safe(this, value, config) -} - -function remarkStringify(options) { - const compiler = (tree) => { - const settings = (this.data('settings')); - return toMarkdown( - tree, - Object.assign({}, settings, options, { - extensions: - ( - this.data('toMarkdownExtensions') - ) || [] - }) - ) - }; - Object.assign(this, {Compiler: compiler}); -} - -const wwwPrefix = { - tokenize: tokenizeWwwPrefix, - partial: true -}; -const domain = { - tokenize: tokenizeDomain, - partial: true -}; -const path = { - tokenize: tokenizePath, - partial: true -}; -const trail = { - tokenize: tokenizeTrail, - partial: true -}; -const emailDomainDotTrail = { - tokenize: tokenizeEmailDomainDotTrail, - partial: true -}; -const wwwAutolink = { - tokenize: tokenizeWwwAutolink, - previous: previousWww -}; -const protocolAutolink = { - tokenize: tokenizeProtocolAutolink, - previous: previousProtocol -}; -const emailAutolink = { - tokenize: tokenizeEmailAutolink, - previous: previousEmail -}; -const text = {}; -const gfmAutolinkLiteral = { - text -}; -let code = 48; -while (code < 123) { - text[code] = emailAutolink; - code++; - if (code === 58) code = 65; - else if (code === 91) code = 97; -} -text[43] = emailAutolink; -text[45] = emailAutolink; -text[46] = emailAutolink; -text[95] = emailAutolink; -text[72] = [emailAutolink, protocolAutolink]; -text[104] = [emailAutolink, protocolAutolink]; -text[87] = [emailAutolink, wwwAutolink]; -text[119] = [emailAutolink, wwwAutolink]; -function tokenizeEmailAutolink(effects, ok, nok) { - const self = this; - let dot; - let data; - return start - function start(code) { - if ( - !gfmAtext(code) || - !previousEmail.call(self, self.previous) || - previousUnbalanced(self.events) - ) { - return nok(code) - } - effects.enter('literalAutolink'); - effects.enter('literalAutolinkEmail'); - return atext(code) - } - function atext(code) { - if (gfmAtext(code)) { - effects.consume(code); - return atext - } - if (code === 64) { - effects.consume(code); - return emailDomain - } - return nok(code) - } - function emailDomain(code) { - if (code === 46) { - return effects.check( - emailDomainDotTrail, - emailDomainAfter, - emailDomainDot - )(code) - } - if (code === 45 || code === 95 || asciiAlphanumeric(code)) { - data = true; - effects.consume(code); - return emailDomain - } - return emailDomainAfter(code) - } - function emailDomainDot(code) { - effects.consume(code); - dot = true; - return emailDomain - } - function emailDomainAfter(code) { - if (data && dot && asciiAlpha(self.previous)) { - effects.exit('literalAutolinkEmail'); - effects.exit('literalAutolink'); - return ok(code) - } - return nok(code) - } -} -function tokenizeWwwAutolink(effects, ok, nok) { - const self = this; - return wwwStart - function wwwStart(code) { - if ( - (code !== 87 && code !== 119) || - !previousWww.call(self, self.previous) || - previousUnbalanced(self.events) - ) { - return nok(code) - } - effects.enter('literalAutolink'); - effects.enter('literalAutolinkWww'); - return effects.check( - wwwPrefix, - effects.attempt(domain, effects.attempt(path, wwwAfter), nok), - nok - )(code) - } - function wwwAfter(code) { - effects.exit('literalAutolinkWww'); - effects.exit('literalAutolink'); - return ok(code) - } -} -function tokenizeProtocolAutolink(effects, ok, nok) { - const self = this; - let buffer = ''; - let seen = false; - return protocolStart - function protocolStart(code) { - if ( - (code === 72 || code === 104) && - previousProtocol.call(self, self.previous) && - !previousUnbalanced(self.events) - ) { - effects.enter('literalAutolink'); - effects.enter('literalAutolinkHttp'); - buffer += String.fromCodePoint(code); - effects.consume(code); - return protocolPrefixInside - } - return nok(code) - } - function protocolPrefixInside(code) { - if (asciiAlpha(code) && buffer.length < 5) { - buffer += String.fromCodePoint(code); - effects.consume(code); - return protocolPrefixInside - } - if (code === 58) { - const protocol = buffer.toLowerCase(); - if (protocol === 'http' || protocol === 'https') { - effects.consume(code); - return protocolSlashesInside - } - } - return nok(code) - } - function protocolSlashesInside(code) { - if (code === 47) { - effects.consume(code); - if (seen) { - return afterProtocol - } - seen = true; - return protocolSlashesInside - } - return nok(code) - } - function afterProtocol(code) { - return code === null || - asciiControl(code) || - markdownLineEndingOrSpace(code) || - unicodeWhitespace(code) || - unicodePunctuation(code) - ? nok(code) - : effects.attempt(domain, effects.attempt(path, protocolAfter), nok)(code) - } - function protocolAfter(code) { - effects.exit('literalAutolinkHttp'); - effects.exit('literalAutolink'); - return ok(code) + return containerFlow(parent, this, info) +} +function safeBound(value, config) { + return safe(this, value, config) +} + +function remarkStringify(options) { + const self = this; + self.compiler = compiler; + function compiler(tree) { + return toMarkdown(tree, { + ...self.data('settings'), + ...options, + extensions: self.data('toMarkdownExtensions') || [] + }) } } -function tokenizeWwwPrefix(effects, ok, nok) { - let size = 0; - return wwwPrefixInside - function wwwPrefixInside(code) { - if ((code === 87 || code === 119) && size < 3) { - size++; - effects.consume(code); - return wwwPrefixInside - } - if (code === 46 && size === 3) { - effects.consume(code); - return wwwPrefixAfter - } - return nok(code) + +function ccount(value, character) { + const source = String(value); + if (typeof character !== 'string') { + throw new TypeError('Expected character') } - function wwwPrefixAfter(code) { - return code === null ? nok(code) : ok(code) + let count = 0; + let index = source.indexOf(character); + while (index !== -1) { + count++; + index = source.indexOf(character, index + character.length); } + return count } -function tokenizeDomain(effects, ok, nok) { - let underscoreInLastSegment; - let underscoreInLastLastSegment; - let seen; - return domainInside - function domainInside(code) { - if (code === 46 || code === 95) { - return effects.check(trail, domainAfter, domainAtPunctuation)(code) - } - if ( - code === null || - markdownLineEndingOrSpace(code) || - unicodeWhitespace(code) || - (code !== 45 && unicodePunctuation(code)) - ) { - return domainAfter(code) - } - seen = true; - effects.consume(code); - return domainInside + +function escapeStringRegexp(string) { + if (typeof string !== 'string') { + throw new TypeError('Expected a string'); + } + return string + .replace(/[|\\{}()[\]^$+*?.]/g, '\\$&') + .replace(/-/g, '\\x2d'); +} + +function findAndReplace(tree, list, options) { + const settings = options || {}; + const ignored = convert$A(settings.ignore || []); + const pairs = toPairs(list); + let pairIndex = -1; + while (++pairIndex < pairs.length) { + visitParents$A(tree, 'text', visitor); } - function domainAtPunctuation(code) { - if (code === 95) { - underscoreInLastSegment = true; - } - else { - underscoreInLastLastSegment = underscoreInLastSegment; - underscoreInLastSegment = undefined; + function visitor(node, parents) { + let index = -1; + let grandparent; + while (++index < parents.length) { + const parent = parents[index]; + const siblings = grandparent ? grandparent.children : undefined; + if ( + ignored( + parent, + siblings ? siblings.indexOf(parent) : undefined, + grandparent + ) + ) { + return + } + grandparent = parent; + } + if (grandparent) { + return handler(node, parents) + } + } + function handler(node, parents) { + const parent = parents[parents.length - 1]; + const find = pairs[pairIndex][0]; + const replace = pairs[pairIndex][1]; + let start = 0; + const siblings = parent.children; + const index = siblings.indexOf(node); + let change = false; + let nodes = []; + find.lastIndex = 0; + let match = find.exec(node.value); + while (match) { + const position = match.index; + const matchObject = { + index: match.index, + input: match.input, + stack: [...parents, node] + }; + let value = replace(...match, matchObject); + if (typeof value === 'string') { + value = value.length > 0 ? {type: 'text', value} : undefined; + } + if (value === false) { + find.lastIndex = position + 1; + } else { + if (start !== position) { + nodes.push({ + type: 'text', + value: node.value.slice(start, position) + }); + } + if (Array.isArray(value)) { + nodes.push(...value); + } else if (value) { + nodes.push(value); + } + start = position + match[0].length; + change = true; + } + if (!find.global) { + break + } + match = find.exec(node.value); } - effects.consume(code); - return domainInside - } - function domainAfter(code) { - if (underscoreInLastLastSegment || underscoreInLastSegment || !seen) { - return nok(code) + if (change) { + if (start < node.value.length) { + nodes.push({type: 'text', value: node.value.slice(start)}); + } + parent.children.splice(index, 1, ...nodes); + } else { + nodes = [node]; } - return ok(code) + return index + nodes.length } } -function tokenizePath(effects, ok) { - let sizeOpen = 0; - let sizeClose = 0; - return pathInside - function pathInside(code) { - if (code === 40) { - sizeOpen++; - effects.consume(code); - return pathInside - } - if (code === 41 && sizeClose < sizeOpen) { - return pathAtPunctuation(code) - } - if ( - code === 33 || - code === 34 || - code === 38 || - code === 39 || - code === 41 || - code === 42 || - code === 44 || - code === 46 || - code === 58 || - code === 59 || - code === 60 || - code === 63 || - code === 93 || - code === 95 || - code === 126 - ) { - return effects.check(trail, ok, pathAtPunctuation)(code) - } - if ( - code === null || - markdownLineEndingOrSpace(code) || - unicodeWhitespace(code) - ) { - return ok(code) - } - effects.consume(code); - return pathInside +function toPairs(tupleOrList) { + const result = []; + if (!Array.isArray(tupleOrList)) { + throw new TypeError('Expected find and replace tuple or list of tuples') } - function pathAtPunctuation(code) { - if (code === 41) { - sizeClose++; - } - effects.consume(code); - return pathInside + const list = + !tupleOrList[0] || Array.isArray(tupleOrList[0]) + ? tupleOrList + : [tupleOrList]; + let index = -1; + while (++index < list.length) { + const tuple = list[index]; + result.push([toExpression(tuple[0]), toFunction(tuple[1])]); } + return result } -function tokenizeTrail(effects, ok, nok) { - return trail - function trail(code) { - if ( - code === 33 || - code === 34 || - code === 39 || - code === 41 || - code === 42 || - code === 44 || - code === 46 || - code === 58 || - code === 59 || - code === 63 || - code === 95 || - code === 126 - ) { - effects.consume(code); - return trail - } - if (code === 38) { - effects.consume(code); - return trailCharRefStart - } - if (code === 93) { - effects.consume(code); - return trailBracketAfter - } - if ( - code === 60 || - code === null || - markdownLineEndingOrSpace(code) || - unicodeWhitespace(code) - ) { - return ok(code) +function toExpression(find) { + return typeof find === 'string' ? new RegExp(escapeStringRegexp(find), 'g') : find +} +function toFunction(replace) { + return typeof replace === 'function' + ? replace + : function () { + return replace + } +} + +const inConstruct = 'phrasing'; +const notInConstruct = ['autolink', 'link', 'image', 'label']; +function gfmAutolinkLiteralFromMarkdown() { + return { + transforms: [transformGfmAutolinkLiterals], + enter: { + literalAutolink: enterLiteralAutolink, + literalAutolinkEmail: enterLiteralAutolinkValue, + literalAutolinkHttp: enterLiteralAutolinkValue, + literalAutolinkWww: enterLiteralAutolinkValue + }, + exit: { + literalAutolink: exitLiteralAutolink, + literalAutolinkEmail: exitLiteralAutolinkEmail, + literalAutolinkHttp: exitLiteralAutolinkHttp, + literalAutolinkWww: exitLiteralAutolinkWww } - return nok(code) } - function trailBracketAfter(code) { - if ( - code === null || - code === 40 || - code === 91 || - markdownLineEndingOrSpace(code) || - unicodeWhitespace(code) - ) { - return ok(code) - } - return trail(code) +} +function gfmAutolinkLiteralToMarkdown() { + return { + unsafe: [ + { + character: '@', + before: '[+\\-.\\w]', + after: '[\\-.\\w]', + inConstruct, + notInConstruct + }, + { + character: '.', + before: '[Ww]', + after: '[\\-.\\w]', + inConstruct, + notInConstruct + }, + { + character: ':', + before: '[ps]', + after: '\\/', + inConstruct, + notInConstruct + } + ] + } +} +function enterLiteralAutolink(token) { + this.enter({type: 'link', title: null, url: '', children: []}, token); +} +function enterLiteralAutolinkValue(token) { + this.config.enter.autolinkProtocol.call(this, token); +} +function exitLiteralAutolinkHttp(token) { + this.config.exit.autolinkProtocol.call(this, token); +} +function exitLiteralAutolinkWww(token) { + this.config.exit.data.call(this, token); + const node = this.stack[this.stack.length - 1]; + ok$B(node.type === 'link'); + node.url = 'http://' + this.sliceSerialize(token); +} +function exitLiteralAutolinkEmail(token) { + this.config.exit.autolinkEmail.call(this, token); +} +function exitLiteralAutolink(token) { + this.exit(token); +} +function transformGfmAutolinkLiterals(tree) { + findAndReplace( + tree, + [ + [/(https?:\/\/|www(?=\.))([-.\w]+)([^ \t\r\n]*)/gi, findUrl], + [/([-.\w+]+)@([-\w]+(?:\.[-\w]+)+)/g, findEmail] + ], + {ignore: ['link', 'linkReference']} + ); +} +function findUrl(_, protocol, domain, path, match) { + let prefix = ''; + if (!previous(match)) { + return false } - function trailCharRefStart(code) { - return asciiAlpha(code) ? trailCharRefInside(code) : nok(code) + if (/^w/i.test(protocol)) { + domain = protocol + domain; + protocol = ''; + prefix = 'http://'; } - function trailCharRefInside(code) { - if (code === 59) { - effects.consume(code); - return trail - } - if (asciiAlpha(code)) { - effects.consume(code); - return trailCharRefInside - } - return nok(code) + if (!isCorrectDomain(domain)) { + return false + } + const parts = splitUrl(domain + path); + if (!parts[0]) return false + const result = { + type: 'link', + title: null, + url: prefix + protocol + parts[0], + children: [{type: 'text', value: protocol + parts[0]}] + }; + if (parts[1]) { + return [result, {type: 'text', value: parts[1]}] } + return result } -function tokenizeEmailDomainDotTrail(effects, ok, nok) { - return start - function start(code) { - effects.consume(code); - return after +function findEmail(_, atext, label, match) { + if ( + !previous(match, true) || + /[-\d_]$/.test(label) + ) { + return false } - function after(code) { - return asciiAlphanumeric(code) ? nok(code) : ok(code) + return { + type: 'link', + title: null, + url: 'mailto:' + atext + '@' + label, + children: [{type: 'text', value: atext + '@' + label}] } } -function previousWww(code) { - return ( - code === null || - code === 40 || - code === 42 || - code === 95 || - code === 91 || - code === 93 || - code === 126 || - markdownLineEndingOrSpace(code) - ) -} -function previousProtocol(code) { - return !asciiAlpha(code) +function isCorrectDomain(domain) { + const parts = domain.split('.'); + if ( + parts.length < 2 || + (parts[parts.length - 1] && + (/_/.test(parts[parts.length - 1]) || + !/[a-zA-Z\d]/.test(parts[parts.length - 1]))) || + (parts[parts.length - 2] && + (/_/.test(parts[parts.length - 2]) || + !/[a-zA-Z\d]/.test(parts[parts.length - 2]))) + ) { + return false + } + return true } -function previousEmail(code) { - return !(code === 47 || gfmAtext(code)) +function splitUrl(url) { + const trailExec = /[!"&'),.:;<>?\]}]+$/.exec(url); + if (!trailExec) { + return [url, undefined] + } + url = url.slice(0, trailExec.index); + let trail = trailExec[0]; + let closingParenIndex = trail.indexOf(')'); + const openingParens = ccount(url, '('); + let closingParens = ccount(url, ')'); + while (closingParenIndex !== -1 && openingParens > closingParens) { + url += trail.slice(0, closingParenIndex + 1); + trail = trail.slice(closingParenIndex + 1); + closingParenIndex = trail.indexOf(')'); + closingParens++; + } + return [url, trail] } -function gfmAtext(code) { +function previous(match, email) { + const code = match.input.charCodeAt(match.index - 1); return ( - code === 43 || - code === 45 || - code === 46 || - code === 95 || - asciiAlphanumeric(code) + (match.index === 0 || + unicodeWhitespace(code) || + unicodePunctuation(code)) && + (!email || code !== 47) ) } -function previousUnbalanced(events) { - let index = events.length; - let result = false; - while (index--) { - const token = events[index][1]; - if ( - (token.type === 'labelLink' || token.type === 'labelImage') && - !token._balanced - ) { - result = true; - break - } - if (token._gfmAutolinkLiteralWalkedInto) { - result = false; - break - } - } - if (events.length > 0 && !result) { - events[events.length - 1][1]._gfmAutolinkLiteralWalkedInto = true; - } - return result -} -const indent = { - tokenize: tokenizeIndent, - partial: true -}; -function gfmFootnote() { +footnoteReference.peek = footnoteReferencePeek; +function gfmFootnoteFromMarkdown() { return { - document: { - [91]: { - tokenize: tokenizeDefinitionStart, - continuation: { - tokenize: tokenizeDefinitionContinuation - }, - exit: gfmFootnoteDefinitionEnd - } + enter: { + gfmFootnoteDefinition: enterFootnoteDefinition, + gfmFootnoteDefinitionLabelString: enterFootnoteDefinitionLabelString, + gfmFootnoteCall: enterFootnoteCall, + gfmFootnoteCallString: enterFootnoteCallString }, - text: { - [91]: { - tokenize: tokenizeGfmFootnoteCall - }, - [93]: { - add: 'after', - tokenize: tokenizePotentialGfmFootnoteCall, - resolveTo: resolveToPotentialGfmFootnoteCall - } + exit: { + gfmFootnoteDefinition: exitFootnoteDefinition, + gfmFootnoteDefinitionLabelString: exitFootnoteDefinitionLabelString, + gfmFootnoteCall: exitFootnoteCall, + gfmFootnoteCallString: exitFootnoteCallString } } } -function tokenizePotentialGfmFootnoteCall(effects, ok, nok) { - const self = this; - let index = self.events.length; - const defined = self.parser.gfmFootnotes || (self.parser.gfmFootnotes = []); - let labelStart; - while (index--) { - const token = self.events[index][1]; - if (token.type === 'labelImage') { - labelStart = token; - break - } - if ( - token.type === 'gfmFootnoteCall' || - token.type === 'labelLink' || - token.type === 'label' || - token.type === 'image' || - token.type === 'link' - ) { - break - } - } - return start - function start(code) { - if (!labelStart || !labelStart._balanced) { - return nok(code) - } - const id = normalizeIdentifier( - self.sliceSerialize({ - start: labelStart.end, - end: self.now() - }) - ); - if (id.codePointAt(0) !== 94 || !defined.includes(id.slice(1))) { - return nok(code) - } - effects.enter('gfmFootnoteCallLabelMarker'); - effects.consume(code); - effects.exit('gfmFootnoteCallLabelMarker'); - return ok(code) +function gfmFootnoteToMarkdown() { + return { + unsafe: [{character: '[', inConstruct: ['phrasing', 'label', 'reference']}], + handlers: {footnoteDefinition, footnoteReference} } } -function resolveToPotentialGfmFootnoteCall(events, context) { - let index = events.length; - while (index--) { - if ( - events[index][1].type === 'labelImage' && - events[index][0] === 'enter' - ) { - events[index][1]; - break - } +function enterFootnoteDefinition(token) { + this.enter( + {type: 'footnoteDefinition', identifier: '', label: '', children: []}, + token + ); +} +function enterFootnoteDefinitionLabelString() { + this.buffer(); +} +function exitFootnoteDefinitionLabelString(token) { + const label = this.resume(); + const node = this.stack[this.stack.length - 1]; + ok$B(node.type === 'footnoteDefinition'); + node.label = label; + node.identifier = normalizeIdentifier$1( + this.sliceSerialize(token) + ).toLowerCase(); +} +function exitFootnoteDefinition(token) { + this.exit(token); +} +function enterFootnoteCall(token) { + this.enter({type: 'footnoteReference', identifier: '', label: ''}, token); +} +function enterFootnoteCallString() { + this.buffer(); +} +function exitFootnoteCallString(token) { + const label = this.resume(); + const node = this.stack[this.stack.length - 1]; + ok$B(node.type === 'footnoteReference'); + node.label = label; + node.identifier = normalizeIdentifier$1( + this.sliceSerialize(token) + ).toLowerCase(); +} +function exitFootnoteCall(token) { + this.exit(token); +} +function footnoteReference(node, _, state, info) { + const tracker = state.createTracker(info); + let value = tracker.move('[^'); + const exit = state.enter('footnoteReference'); + const subexit = state.enter('reference'); + value += tracker.move( + state.safe(state.associationId(node), { + ...tracker.current(), + before: value, + after: ']' + }) + ); + subexit(); + exit(); + value += tracker.move(']'); + return value +} +function footnoteReferencePeek() { + return '[' +} +function footnoteDefinition(node, _, state, info) { + const tracker = state.createTracker(info); + let value = tracker.move('[^'); + const exit = state.enter('footnoteDefinition'); + const subexit = state.enter('label'); + value += tracker.move( + state.safe(state.associationId(node), { + ...tracker.current(), + before: value, + after: ']' + }) + ); + subexit(); + value += tracker.move( + ']:' + (node.children && node.children.length > 0 ? ' ' : '') + ); + tracker.shift(4); + value += tracker.move( + state.indentLines(state.containerFlow(node, tracker.current()), map$1) + ); + exit(); + return value +} +function map$1(line, index, blank) { + if (index === 0) { + return line } - events[index + 1][1].type = 'data'; - events[index + 3][1].type = 'gfmFootnoteCallLabelMarker'; - const call = { - type: 'gfmFootnoteCall', - start: Object.assign({}, events[index + 3][1].start), - end: Object.assign({}, events[events.length - 1][1].end) - }; - const marker = { - type: 'gfmFootnoteCallMarker', - start: Object.assign({}, events[index + 3][1].end), - end: Object.assign({}, events[index + 3][1].end) - }; - marker.end.column++; - marker.end.offset++; - marker.end._bufferIndex++; - const string = { - type: 'gfmFootnoteCallString', - start: Object.assign({}, marker.end), - end: Object.assign({}, events[events.length - 1][1].start) - }; - const chunk = { - type: 'chunkString', - contentType: 'string', - start: Object.assign({}, string.start), - end: Object.assign({}, string.end) - }; - const replacement = [ - events[index + 1], - events[index + 2], - ['enter', call, context], - events[index + 3], - events[index + 4], - ['enter', marker, context], - ['exit', marker, context], - ['enter', string, context], - ['enter', chunk, context], - ['exit', chunk, context], - ['exit', string, context], - events[events.length - 2], - events[events.length - 1], - ['exit', call, context] - ]; - events.splice(index, events.length - index + 1, ...replacement); - return events + return (blank ? '' : ' ') + line } -function tokenizeGfmFootnoteCall(effects, ok, nok) { - const self = this; - const defined = self.parser.gfmFootnotes || (self.parser.gfmFootnotes = []); - let size = 0; - let data; - return start - function start(code) { - effects.enter('gfmFootnoteCall'); - effects.enter('gfmFootnoteCallLabelMarker'); - effects.consume(code); - effects.exit('gfmFootnoteCallLabelMarker'); - return callStart - } - function callStart(code) { - if (code !== 94) return nok(code) - effects.enter('gfmFootnoteCallMarker'); - effects.consume(code); - effects.exit('gfmFootnoteCallMarker'); - effects.enter('gfmFootnoteCallString'); - effects.enter('chunkString').contentType = 'string'; - return callData + +const constructsWithoutStrikethrough = [ + 'autolink', + 'destinationLiteral', + 'destinationRaw', + 'reference', + 'titleQuote', + 'titleApostrophe' +]; +handleDelete.peek = peekDelete; +function gfmStrikethroughFromMarkdown() { + return { + canContainEols: ['delete'], + enter: {strikethrough: enterStrikethrough}, + exit: {strikethrough: exitStrikethrough} } - function callData(code) { - if ( - size > 999 || - (code === 93 && !data) || - code === null || - code === 91 || - markdownLineEndingOrSpace(code) - ) { - return nok(code) - } - if (code === 93) { - effects.exit('chunkString'); - const token = effects.exit('gfmFootnoteCallString'); - if (!defined.includes(normalizeIdentifier(self.sliceSerialize(token)))) { - return nok(code) +} +function gfmStrikethroughToMarkdown() { + return { + unsafe: [ + { + character: '~', + inConstruct: 'phrasing', + notInConstruct: constructsWithoutStrikethrough } - effects.enter('gfmFootnoteCallLabelMarker'); - effects.consume(code); - effects.exit('gfmFootnoteCallLabelMarker'); - effects.exit('gfmFootnoteCall'); - return ok - } - if (!markdownLineEndingOrSpace(code)) { - data = true; - } - size++; - effects.consume(code); - return code === 92 ? callEscape : callData - } - function callEscape(code) { - if (code === 91 || code === 92 || code === 93) { - effects.consume(code); - size++; - return callData - } - return callData(code) + ], + handlers: {delete: handleDelete} } } -function tokenizeDefinitionStart(effects, ok, nok) { - const self = this; - const defined = self.parser.gfmFootnotes || (self.parser.gfmFootnotes = []); - let identifier; - let size = 0; - let data; - return start - function start(code) { - effects.enter('gfmFootnoteDefinition')._container = true; - effects.enter('gfmFootnoteDefinitionLabel'); - effects.enter('gfmFootnoteDefinitionLabelMarker'); - effects.consume(code); - effects.exit('gfmFootnoteDefinitionLabelMarker'); - return labelAtMarker - } - function labelAtMarker(code) { - if (code === 94) { - effects.enter('gfmFootnoteDefinitionMarker'); - effects.consume(code); - effects.exit('gfmFootnoteDefinitionMarker'); - effects.enter('gfmFootnoteDefinitionLabelString'); - effects.enter('chunkString').contentType = 'string'; - return labelInside - } - return nok(code) - } - function labelInside(code) { - if ( - size > 999 || - (code === 93 && !data) || - code === null || - code === 91 || - markdownLineEndingOrSpace(code) - ) { - return nok(code) - } - if (code === 93) { - effects.exit('chunkString'); - const token = effects.exit('gfmFootnoteDefinitionLabelString'); - identifier = normalizeIdentifier(self.sliceSerialize(token)); - effects.enter('gfmFootnoteDefinitionLabelMarker'); - effects.consume(code); - effects.exit('gfmFootnoteDefinitionLabelMarker'); - effects.exit('gfmFootnoteDefinitionLabel'); - return labelAfter +function enterStrikethrough(token) { + this.enter({type: 'delete', children: []}, token); +} +function exitStrikethrough(token) { + this.exit(token); +} +function handleDelete(node, _, state, info) { + const tracker = state.createTracker(info); + const exit = state.enter('strikethrough'); + let value = tracker.move('~~'); + value += state.containerPhrasing(node, { + ...tracker.current(), + before: value, + after: '~' + }); + value += tracker.move('~~'); + exit(); + return value +} +function peekDelete() { + return '~' +} + +function markdownTable(table, options = {}) { + const align = (options.align || []).concat(); + const stringLength = options.stringLength || defaultStringLength; + const alignments = []; + const cellMatrix = []; + const sizeMatrix = []; + const longestCellByColumn = []; + let mostCellsPerRow = 0; + let rowIndex = -1; + while (++rowIndex < table.length) { + const row = []; + const sizes = []; + let columnIndex = -1; + if (table[rowIndex].length > mostCellsPerRow) { + mostCellsPerRow = table[rowIndex].length; } - if (!markdownLineEndingOrSpace(code)) { - data = true; + while (++columnIndex < table[rowIndex].length) { + const cell = serialize(table[rowIndex][columnIndex]); + if (options.alignDelimiters !== false) { + const size = stringLength(cell); + sizes[columnIndex] = size; + if ( + longestCellByColumn[columnIndex] === undefined || + size > longestCellByColumn[columnIndex] + ) { + longestCellByColumn[columnIndex] = size; + } + } + row.push(cell); } - size++; - effects.consume(code); - return code === 92 ? labelEscape : labelInside + cellMatrix[rowIndex] = row; + sizeMatrix[rowIndex] = sizes; } - function labelEscape(code) { - if (code === 91 || code === 92 || code === 93) { - effects.consume(code); - size++; - return labelInside + let columnIndex = -1; + if (typeof align === 'object' && 'length' in align) { + while (++columnIndex < mostCellsPerRow) { + alignments[columnIndex] = toAlignment(align[columnIndex]); + } + } else { + const code = toAlignment(align); + while (++columnIndex < mostCellsPerRow) { + alignments[columnIndex] = code; } - return labelInside(code) } - function labelAfter(code) { - if (code === 58) { - effects.enter('definitionMarker'); - effects.consume(code); - effects.exit('definitionMarker'); - if (!defined.includes(identifier)) { - defined.push(identifier); + columnIndex = -1; + const row = []; + const sizes = []; + while (++columnIndex < mostCellsPerRow) { + const code = alignments[columnIndex]; + let before = ''; + let after = ''; + if (code === 99 ) { + before = ':'; + after = ':'; + } else if (code === 108 ) { + before = ':'; + } else if (code === 114 ) { + after = ':'; + } + let size = + options.alignDelimiters === false + ? 1 + : Math.max( + 1, + longestCellByColumn[columnIndex] - before.length - after.length + ); + const cell = before + '-'.repeat(size) + after; + if (options.alignDelimiters !== false) { + size = before.length + size + after.length; + if (size > longestCellByColumn[columnIndex]) { + longestCellByColumn[columnIndex] = size; } - return factorySpace( - effects, - whitespaceAfter, - 'gfmFootnoteDefinitionWhitespace' - ) + sizes[columnIndex] = size; } - return nok(code) + row[columnIndex] = cell; } - function whitespaceAfter(code) { - return ok(code) + cellMatrix.splice(1, 0, row); + sizeMatrix.splice(1, 0, sizes); + rowIndex = -1; + const lines = []; + while (++rowIndex < cellMatrix.length) { + const row = cellMatrix[rowIndex]; + const sizes = sizeMatrix[rowIndex]; + columnIndex = -1; + const line = []; + while (++columnIndex < mostCellsPerRow) { + const cell = row[columnIndex] || ''; + let before = ''; + let after = ''; + if (options.alignDelimiters !== false) { + const size = + longestCellByColumn[columnIndex] - (sizes[columnIndex] || 0); + const code = alignments[columnIndex]; + if (code === 114 ) { + before = ' '.repeat(size); + } else if (code === 99 ) { + if (size % 2) { + before = ' '.repeat(size / 2 + 0.5); + after = ' '.repeat(size / 2 - 0.5); + } else { + before = ' '.repeat(size / 2); + after = before; + } + } else { + after = ' '.repeat(size); + } + } + if (options.delimiterStart !== false && !columnIndex) { + line.push('|'); + } + if ( + options.padding !== false && + !(options.alignDelimiters === false && cell === '') && + (options.delimiterStart !== false || columnIndex) + ) { + line.push(' '); + } + if (options.alignDelimiters !== false) { + line.push(before); + } + line.push(cell); + if (options.alignDelimiters !== false) { + line.push(after); + } + if (options.padding !== false) { + line.push(' '); + } + if ( + options.delimiterEnd !== false || + columnIndex !== mostCellsPerRow - 1 + ) { + line.push('|'); + } + } + lines.push( + options.delimiterEnd === false + ? line.join('').replace(/ +$/, '') + : line.join('') + ); } + return lines.join('\n') } -function tokenizeDefinitionContinuation(effects, ok, nok) { - return effects.check(blankLine, ok, effects.attempt(indent, ok, nok)) +function serialize(value) { + return value === null || value === undefined ? '' : String(value) } -function gfmFootnoteDefinitionEnd(effects) { - effects.exit('gfmFootnoteDefinition'); +function defaultStringLength(value) { + return value.length } -function tokenizeIndent(effects, ok, nok) { - const self = this; - return factorySpace( - effects, - afterPrefix, - 'gfmFootnoteDefinitionIndent', - 4 + 1 - ) - function afterPrefix(code) { - const tail = self.events[self.events.length - 1]; - return tail && - tail[1].type === 'gfmFootnoteDefinitionIndent' && - tail[2].sliceSerialize(tail[1], true).length === 4 - ? ok(code) - : nok(code) - } +function toAlignment(value) { + const code = typeof value === 'string' ? value.codePointAt(0) : 0; + return code === 67 || code === 99 + ? 99 + : code === 76 || code === 108 + ? 108 + : code === 82 || code === 114 + ? 114 + : 0 } -function gfmStrikethrough(options) { - const options_ = options || {}; - let single = options_.singleTilde; - const tokenizer = { - tokenize: tokenizeStrikethrough, - resolveAll: resolveAllStrikethrough - }; - if (single === null || single === undefined) { - single = true; - } +function gfmTableFromMarkdown() { return { - text: { - [126]: tokenizer - }, - insideSpan: { - null: [tokenizer] + enter: { + table: enterTable, + tableData: enterCell, + tableHeader: enterCell, + tableRow: enterRow }, - attentionMarkers: { - null: [126] + exit: { + codeText: exitCodeText, + table: exitTable, + tableData: exit, + tableHeader: exit, + tableRow: exit } } - function resolveAllStrikethrough(events, context) { - let index = -1; - while (++index < events.length) { - if ( - events[index][0] === 'enter' && - events[index][1].type === 'strikethroughSequenceTemporary' && - events[index][1]._close - ) { - let open = index; - while (open--) { - if ( - events[open][0] === 'exit' && - events[open][1].type === 'strikethroughSequenceTemporary' && - events[open][1]._open && - events[index][1].end.offset - events[index][1].start.offset === - events[open][1].end.offset - events[open][1].start.offset - ) { - events[index][1].type = 'strikethroughSequence'; - events[open][1].type = 'strikethroughSequence'; - const strikethrough = { - type: 'strikethrough', - start: Object.assign({}, events[open][1].start), - end: Object.assign({}, events[index][1].end) - }; - const text = { - type: 'strikethroughText', - start: Object.assign({}, events[open][1].end), - end: Object.assign({}, events[index][1].start) - }; - const nextEvents = [ - ['enter', strikethrough, context], - ['enter', events[open][1], context], - ['exit', events[open][1], context], - ['enter', text, context] - ]; - const insideSpan = context.parser.constructs.insideSpan.null; - if (insideSpan) { - splice( - nextEvents, - nextEvents.length, - 0, - resolveAll(insideSpan, events.slice(open + 1, index), context) - ); - } - splice(nextEvents, nextEvents.length, 0, [ - ['exit', text, context], - ['enter', events[index][1], context], - ['exit', events[index][1], context], - ['exit', strikethrough, context] - ]); - splice(events, open - 1, index - open + 3, nextEvents); - index = open + nextEvents.length - 2; - break - } - } - } +} +function enterTable(token) { + const align = token._align; + this.enter( + { + type: 'table', + align: align.map(function (d) { + return d === 'none' ? null : d + }), + children: [] + }, + token + ); + this.data.inTable = true; +} +function exitTable(token) { + this.exit(token); + this.data.inTable = undefined; +} +function enterRow(token) { + this.enter({type: 'tableRow', children: []}, token); +} +function exit(token) { + this.exit(token); +} +function enterCell(token) { + this.enter({type: 'tableCell', children: []}, token); +} +function exitCodeText(token) { + let value = this.resume(); + if (this.data.inTable) { + value = value.replace(/\\([\\|])/g, replace); + } + const node = this.stack[this.stack.length - 1]; + ok$B(node.type === 'inlineCode'); + node.value = value; + this.exit(token); +} +function replace($0, $1) { + return $1 === '|' ? $1 : $0 +} +function gfmTableToMarkdown(options) { + const settings = options || {}; + const padding = settings.tableCellPadding; + const alignDelimiters = settings.tablePipeAlign; + const stringLength = settings.stringLength; + const around = padding ? ' ' : '|'; + return { + unsafe: [ + {character: '\r', inConstruct: 'tableCell'}, + {character: '\n', inConstruct: 'tableCell'}, + {atBreak: true, character: '|', after: '[\t :-]'}, + {character: '|', inConstruct: 'tableCell'}, + {atBreak: true, character: ':', after: '-'}, + {atBreak: true, character: '-', after: '[:|-]'} + ], + handlers: { + inlineCode: inlineCodeWithTable, + table: handleTable, + tableCell: handleTableCell, + tableRow: handleTableRow } - index = -1; - while (++index < events.length) { - if (events[index][1].type === 'strikethroughSequenceTemporary') { - events[index][1].type = 'data'; - } + } + function handleTable(node, _, state, info) { + return serializeData(handleTableAsData(node, state, info), node.align) + } + function handleTableRow(node, _, state, info) { + const row = handleTableRowAsData(node, state, info); + const value = serializeData([row]); + return value.slice(0, value.indexOf('\n')) + } + function handleTableCell(node, _, state, info) { + const exit = state.enter('tableCell'); + const subexit = state.enter('phrasing'); + const value = state.containerPhrasing(node, { + ...info, + before: around, + after: around + }); + subexit(); + exit(); + return value + } + function serializeData(matrix, align) { + return markdownTable(matrix, { + align, + alignDelimiters, + padding, + stringLength + }) + } + function handleTableAsData(node, state, info) { + const children = node.children; + let index = -1; + const result = []; + const subexit = state.enter('table'); + while (++index < children.length) { + result[index] = handleTableRowAsData(children[index], state, info); } - return events + subexit(); + return result } - function tokenizeStrikethrough(effects, ok, nok) { - const previous = this.previous; - const events = this.events; - let size = 0; - return start - function start(code) { - if ( - previous === 126 && - events[events.length - 1][1].type !== 'characterEscape' - ) { - return nok(code) - } - effects.enter('strikethroughSequenceTemporary'); - return more(code) + function handleTableRowAsData(node, state, info) { + const children = node.children; + let index = -1; + const result = []; + const subexit = state.enter('tableRow'); + while (++index < children.length) { + result[index] = handleTableCell(children[index], node, state, info); } - function more(code) { - const before = classifyCharacter(previous); - if (code === 126) { - if (size > 1) return nok(code) - effects.consume(code); - size++; - return more - } - if (size < 2 && !single) return nok(code) - const token = effects.exit('strikethroughSequenceTemporary'); - const after = classifyCharacter(code); - token._open = !after || (after === 2 && Boolean(before)); - token._close = !before || (before === 2 && Boolean(after)); - return ok(code) + subexit(); + return result + } + function inlineCodeWithTable(node, parent, state) { + let value = handle.inlineCode(node, parent, state); + if (state.stack.includes('tableCell')) { + value = value.replace(/\|/g, '\\$&'); } + return value } } -class EditMap { - constructor() { - this.map = []; +function gfmTaskListItemFromMarkdown() { + return { + exit: { + taskListCheckValueChecked: exitCheck, + taskListCheckValueUnchecked: exitCheck, + paragraph: exitParagraphWithTaskListItem + } } - add(index, remove, add) { - addImpl(this, index, remove, add); +} +function gfmTaskListItemToMarkdown() { + return { + unsafe: [{atBreak: true, character: '-', after: '[:|-]'}], + handlers: {listItem: listItemWithTaskListItem} } - consume(events) { - this.map.sort((a, b) => a[0] - b[0]); - if (this.map.length === 0) { - return - } - let index = this.map.length; - const vecs = []; - while (index > 0) { - index -= 1; - vecs.push(events.slice(this.map[index][0] + this.map[index][1])); - vecs.push(this.map[index][2]); - events.length = this.map[index][0]; - } - vecs.push([...events]); - events.length = 0; - let slice = vecs.pop(); - while (slice) { - events.push(...slice); - slice = vecs.pop(); +} +function exitCheck(token) { + const node = this.stack[this.stack.length - 2]; + ok$B(node.type === 'listItem'); + node.checked = token.type === 'taskListCheckValueChecked'; +} +function exitParagraphWithTaskListItem(token) { + const parent = this.stack[this.stack.length - 2]; + if ( + parent && + parent.type === 'listItem' && + typeof parent.checked === 'boolean' + ) { + const node = this.stack[this.stack.length - 1]; + ok$B(node.type === 'paragraph'); + const head = node.children[0]; + if (head && head.type === 'text') { + const siblings = parent.children; + let index = -1; + let firstParaghraph; + while (++index < siblings.length) { + const sibling = siblings[index]; + if (sibling.type === 'paragraph') { + firstParaghraph = sibling; + break + } + } + if (firstParaghraph === node) { + head.value = head.value.slice(1); + if (head.value.length === 0) { + node.children.shift(); + } else if ( + node.position && + head.position && + typeof head.position.start.offset === 'number' + ) { + head.position.start.column++; + head.position.start.offset++; + node.position.start = Object.assign({}, head.position.start); + } + } } - this.map.length = 0; } + this.exit(token); } -function addImpl(editMap, at, remove, add) { - let index = 0; - if (remove === 0 && add.length === 0) { - return +function listItemWithTaskListItem(node, parent, state, info) { + const head = node.children[0]; + const checkable = + typeof node.checked === 'boolean' && head && head.type === 'paragraph'; + const checkbox = '[' + (node.checked ? 'x' : ' ') + '] '; + const tracker = state.createTracker(info); + if (checkable) { + tracker.move(checkbox); + } + let value = handle.listItem(node, parent, state, { + ...info, + ...tracker.current() + }); + if (checkable) { + value = value.replace(/^(?:[*+-]|\d+\.)([\r\n]| {1,3})/, check); + } + return value + function check($0) { + return $0 + checkbox + } +} + +function gfmFromMarkdown() { + return [ + gfmAutolinkLiteralFromMarkdown(), + gfmFootnoteFromMarkdown(), + gfmStrikethroughFromMarkdown(), + gfmTableFromMarkdown(), + gfmTaskListItemFromMarkdown() + ] +} +function gfmToMarkdown(options) { + return { + extensions: [ + gfmAutolinkLiteralToMarkdown(), + gfmFootnoteToMarkdown(), + gfmStrikethroughToMarkdown(), + gfmTableToMarkdown(options), + gfmTaskListItemToMarkdown() + ] + } +} + +const wwwPrefix = { + tokenize: tokenizeWwwPrefix, + partial: true +}; +const domain = { + tokenize: tokenizeDomain, + partial: true +}; +const path = { + tokenize: tokenizePath, + partial: true +}; +const trail = { + tokenize: tokenizeTrail, + partial: true +}; +const emailDomainDotTrail = { + tokenize: tokenizeEmailDomainDotTrail, + partial: true +}; +const wwwAutolink = { + tokenize: tokenizeWwwAutolink, + previous: previousWww +}; +const protocolAutolink = { + tokenize: tokenizeProtocolAutolink, + previous: previousProtocol +}; +const emailAutolink = { + tokenize: tokenizeEmailAutolink, + previous: previousEmail +}; +const text = {}; +function gfmAutolinkLiteral() { + return { + text + } +} +let code = 48; +while (code < 123) { + text[code] = emailAutolink; + code++; + if (code === 58) code = 65; + else if (code === 91) code = 97; +} +text[43] = emailAutolink; +text[45] = emailAutolink; +text[46] = emailAutolink; +text[95] = emailAutolink; +text[72] = [emailAutolink, protocolAutolink]; +text[104] = [emailAutolink, protocolAutolink]; +text[87] = [emailAutolink, wwwAutolink]; +text[119] = [emailAutolink, wwwAutolink]; +function tokenizeEmailAutolink(effects, ok, nok) { + const self = this; + let dot; + let data; + return start + function start(code) { + if ( + !gfmAtext(code) || + !previousEmail.call(self, self.previous) || + previousUnbalanced(self.events) + ) { + return nok(code) + } + effects.enter('literalAutolink'); + effects.enter('literalAutolinkEmail'); + return atext(code) } - while (index < editMap.map.length) { - if (editMap.map[index][0] === at) { - editMap.map[index][1] += remove; - editMap.map[index][2].push(...add); - return + function atext(code) { + if (gfmAtext(code)) { + effects.consume(code); + return atext } - index += 1; + if (code === 64) { + effects.consume(code); + return emailDomain + } + return nok(code) } - editMap.map.push([at, remove, add]); -} - -function gfmTableAlign(events, index) { - let inDelimiterRow = false; - const align = []; - while (index < events.length) { - const event = events[index]; - if (inDelimiterRow) { - if (event[0] === 'enter') { - if (event[1].type === 'tableContent') { - align.push( - events[index + 1][1].type === 'tableDelimiterMarker' - ? 'left' - : 'none' - ); - } - } - else if (event[1].type === 'tableContent') { - if (events[index - 1][1].type === 'tableDelimiterMarker') { - const alignIndex = align.length - 1; - align[alignIndex] = align[alignIndex] === 'left' ? 'center' : 'right'; - } - } - else if (event[1].type === 'tableDelimiterRow') { - break - } - } else if (event[0] === 'enter' && event[1].type === 'tableDelimiterRow') { - inDelimiterRow = true; + function emailDomain(code) { + if (code === 46) { + return effects.check( + emailDomainDotTrail, + emailDomainAfter, + emailDomainDot + )(code) } - index += 1; + if (code === 45 || code === 95 || asciiAlphanumeric(code)) { + data = true; + effects.consume(code); + return emailDomain + } + return emailDomainAfter(code) } - return align -} - -const gfmTable = { - flow: { - null: { - tokenize: tokenizeTable, - resolveAll: resolveTable + function emailDomainDot(code) { + effects.consume(code); + dot = true; + return emailDomain + } + function emailDomainAfter(code) { + if (data && dot && asciiAlpha(self.previous)) { + effects.exit('literalAutolinkEmail'); + effects.exit('literalAutolink'); + return ok(code) } + return nok(code) } -}; -function tokenizeTable(effects, ok, nok) { +} +function tokenizeWwwAutolink(effects, ok, nok) { const self = this; - let size = 0; - let sizeB = 0; - let seen; - return start - function start(code) { - let index = self.events.length - 1; - while (index > -1) { - const type = self.events[index][1].type; - if ( - type === 'lineEnding' || - type === 'linePrefix' - ) - index--; - else break - } - const tail = index > -1 ? self.events[index][1].type : null; - const next = - tail === 'tableHead' || tail === 'tableRow' ? bodyRowStart : headRowBefore; - if (next === bodyRowStart && self.parser.lazy[self.now().line]) { + return wwwStart + function wwwStart(code) { + if ( + (code !== 87 && code !== 119) || + !previousWww.call(self, self.previous) || + previousUnbalanced(self.events) + ) { return nok(code) } - return next(code) + effects.enter('literalAutolink'); + effects.enter('literalAutolinkWww'); + return effects.check( + wwwPrefix, + effects.attempt(domain, effects.attempt(path, wwwAfter), nok), + nok + )(code) } - function headRowBefore(code) { - effects.enter('tableHead'); - effects.enter('tableRow'); - return headRowStart(code) + function wwwAfter(code) { + effects.exit('literalAutolinkWww'); + effects.exit('literalAutolink'); + return ok(code) } - function headRowStart(code) { - if (code === 124) { - return headRowBreak(code) +} +function tokenizeProtocolAutolink(effects, ok, nok) { + const self = this; + let buffer = ''; + let seen = false; + return protocolStart + function protocolStart(code) { + if ( + (code === 72 || code === 104) && + previousProtocol.call(self, self.previous) && + !previousUnbalanced(self.events) + ) { + effects.enter('literalAutolink'); + effects.enter('literalAutolinkHttp'); + buffer += String.fromCodePoint(code); + effects.consume(code); + return protocolPrefixInside } - seen = true; - sizeB += 1; - return headRowBreak(code) + return nok(code) } - function headRowBreak(code) { - if (code === null) { - return nok(code) + function protocolPrefixInside(code) { + if (asciiAlpha(code) && buffer.length < 5) { + buffer += String.fromCodePoint(code); + effects.consume(code); + return protocolPrefixInside } - if (markdownLineEnding(code)) { - if (sizeB > 1) { - sizeB = 0; - self.interrupt = true; - effects.exit('tableRow'); - effects.enter('lineEnding'); + if (code === 58) { + const protocol = buffer.toLowerCase(); + if (protocol === 'http' || protocol === 'https') { effects.consume(code); - effects.exit('lineEnding'); - return headDelimiterStart + return protocolSlashesInside } - return nok(code) - } - if (markdownSpace(code)) { - return factorySpace(effects, headRowBreak, 'whitespace')(code) - } - sizeB += 1; - if (seen) { - seen = false; - size += 1; } - if (code === 124) { - effects.enter('tableCellDivider'); + return nok(code) + } + function protocolSlashesInside(code) { + if (code === 47) { effects.consume(code); - effects.exit('tableCellDivider'); + if (seen) { + return afterProtocol + } seen = true; - return headRowBreak + return protocolSlashesInside } - effects.enter('data'); - return headRowData(code) + return nok(code) } - function headRowData(code) { - if (code === null || code === 124 || markdownLineEndingOrSpace(code)) { - effects.exit('data'); - return headRowBreak(code) - } - effects.consume(code); - return code === 92 ? headRowEscape : headRowData + function afterProtocol(code) { + return code === null || + asciiControl(code) || + markdownLineEndingOrSpace(code) || + unicodeWhitespace(code) || + unicodePunctuation(code) + ? nok(code) + : effects.attempt(domain, effects.attempt(path, protocolAfter), nok)(code) } - function headRowEscape(code) { - if (code === 92 || code === 124) { + function protocolAfter(code) { + effects.exit('literalAutolinkHttp'); + effects.exit('literalAutolink'); + return ok(code) + } +} +function tokenizeWwwPrefix(effects, ok, nok) { + let size = 0; + return wwwPrefixInside + function wwwPrefixInside(code) { + if ((code === 87 || code === 119) && size < 3) { + size++; effects.consume(code); - return headRowData + return wwwPrefixInside } - return headRowData(code) + if (code === 46 && size === 3) { + effects.consume(code); + return wwwPrefixAfter + } + return nok(code) } - function headDelimiterStart(code) { - self.interrupt = false; - if (self.parser.lazy[self.now().line]) { - return nok(code) + function wwwPrefixAfter(code) { + return code === null ? nok(code) : ok(code) + } +} +function tokenizeDomain(effects, ok, nok) { + let underscoreInLastSegment; + let underscoreInLastLastSegment; + let seen; + return domainInside + function domainInside(code) { + if (code === 46 || code === 95) { + return effects.check(trail, domainAfter, domainAtPunctuation)(code) } - effects.enter('tableDelimiterRow'); - seen = false; - if (markdownSpace(code)) { - return factorySpace( - effects, - headDelimiterBefore, - 'linePrefix', - self.parser.constructs.disable.null.includes('codeIndented') - ? undefined - : 4 - )(code) + if ( + code === null || + markdownLineEndingOrSpace(code) || + unicodeWhitespace(code) || + (code !== 45 && unicodePunctuation(code)) + ) { + return domainAfter(code) } - return headDelimiterBefore(code) + seen = true; + effects.consume(code); + return domainInside } - function headDelimiterBefore(code) { - if (code === 45 || code === 58) { - return headDelimiterValueBefore(code) + function domainAtPunctuation(code) { + if (code === 95) { + underscoreInLastSegment = true; } - if (code === 124) { - seen = true; - effects.enter('tableCellDivider'); - effects.consume(code); - effects.exit('tableCellDivider'); - return headDelimiterCellBefore + else { + underscoreInLastLastSegment = underscoreInLastSegment; + underscoreInLastSegment = undefined; } - return headDelimiterNok(code) + effects.consume(code); + return domainInside } - function headDelimiterCellBefore(code) { - if (markdownSpace(code)) { - return factorySpace(effects, headDelimiterValueBefore, 'whitespace')(code) + function domainAfter(code) { + if (underscoreInLastLastSegment || underscoreInLastSegment || !seen) { + return nok(code) } - return headDelimiterValueBefore(code) + return ok(code) } - function headDelimiterValueBefore(code) { - if (code === 58) { - sizeB += 1; - seen = true; - effects.enter('tableDelimiterMarker'); +} +function tokenizePath(effects, ok) { + let sizeOpen = 0; + let sizeClose = 0; + return pathInside + function pathInside(code) { + if (code === 40) { + sizeOpen++; effects.consume(code); - effects.exit('tableDelimiterMarker'); - return headDelimiterLeftAlignmentAfter + return pathInside } - if (code === 45) { - sizeB += 1; - return headDelimiterLeftAlignmentAfter(code) + if (code === 41 && sizeClose < sizeOpen) { + return pathAtPunctuation(code) } - if (code === null || markdownLineEnding(code)) { - return headDelimiterCellAfter(code) + if ( + code === 33 || + code === 34 || + code === 38 || + code === 39 || + code === 41 || + code === 42 || + code === 44 || + code === 46 || + code === 58 || + code === 59 || + code === 60 || + code === 63 || + code === 93 || + code === 95 || + code === 126 + ) { + return effects.check(trail, ok, pathAtPunctuation)(code) } - return headDelimiterNok(code) + if ( + code === null || + markdownLineEndingOrSpace(code) || + unicodeWhitespace(code) + ) { + return ok(code) + } + effects.consume(code); + return pathInside } - function headDelimiterLeftAlignmentAfter(code) { - if (code === 45) { - effects.enter('tableDelimiterFiller'); - return headDelimiterFiller(code) + function pathAtPunctuation(code) { + if (code === 41) { + sizeClose++; } - return headDelimiterNok(code) + effects.consume(code); + return pathInside } - function headDelimiterFiller(code) { - if (code === 45) { +} +function tokenizeTrail(effects, ok, nok) { + return trail + function trail(code) { + if ( + code === 33 || + code === 34 || + code === 39 || + code === 41 || + code === 42 || + code === 44 || + code === 46 || + code === 58 || + code === 59 || + code === 63 || + code === 95 || + code === 126 + ) { effects.consume(code); - return headDelimiterFiller + return trail } - if (code === 58) { - seen = true; - effects.exit('tableDelimiterFiller'); - effects.enter('tableDelimiterMarker'); + if (code === 38) { effects.consume(code); - effects.exit('tableDelimiterMarker'); - return headDelimiterRightAlignmentAfter + return trailCharRefStart } - effects.exit('tableDelimiterFiller'); - return headDelimiterRightAlignmentAfter(code) - } - function headDelimiterRightAlignmentAfter(code) { - if (markdownSpace(code)) { - return factorySpace(effects, headDelimiterCellAfter, 'whitespace')(code) + if (code === 93) { + effects.consume(code); + return trailBracketAfter } - return headDelimiterCellAfter(code) - } - function headDelimiterCellAfter(code) { - if (code === 124) { - return headDelimiterBefore(code) + if ( + code === 60 || + code === null || + markdownLineEndingOrSpace(code) || + unicodeWhitespace(code) + ) { + return ok(code) } - if (code === null || markdownLineEnding(code)) { - if (!seen || size !== sizeB) { - return headDelimiterNok(code) - } - effects.exit('tableDelimiterRow'); - effects.exit('tableHead'); + return nok(code) + } + function trailBracketAfter(code) { + if ( + code === null || + code === 40 || + code === 91 || + markdownLineEndingOrSpace(code) || + unicodeWhitespace(code) + ) { return ok(code) } - return headDelimiterNok(code) + return trail(code) } - function headDelimiterNok(code) { + function trailCharRefStart(code) { + return asciiAlpha(code) ? trailCharRefInside(code) : nok(code) + } + function trailCharRefInside(code) { + if (code === 59) { + effects.consume(code); + return trail + } + if (asciiAlpha(code)) { + effects.consume(code); + return trailCharRefInside + } return nok(code) } - function bodyRowStart(code) { - effects.enter('tableRow'); - return bodyRowBreak(code) +} +function tokenizeEmailDomainDotTrail(effects, ok, nok) { + return start + function start(code) { + effects.consume(code); + return after } - function bodyRowBreak(code) { - if (code === 124) { - effects.enter('tableCellDivider'); - effects.consume(code); - effects.exit('tableCellDivider'); - return bodyRowBreak + function after(code) { + return asciiAlphanumeric(code) ? nok(code) : ok(code) + } +} +function previousWww(code) { + return ( + code === null || + code === 40 || + code === 42 || + code === 95 || + code === 91 || + code === 93 || + code === 126 || + markdownLineEndingOrSpace(code) + ) +} +function previousProtocol(code) { + return !asciiAlpha(code) +} +function previousEmail(code) { + return !(code === 47 || gfmAtext(code)) +} +function gfmAtext(code) { + return ( + code === 43 || + code === 45 || + code === 46 || + code === 95 || + asciiAlphanumeric(code) + ) +} +function previousUnbalanced(events) { + let index = events.length; + let result = false; + while (index--) { + const token = events[index][1]; + if ( + (token.type === 'labelLink' || token.type === 'labelImage') && + !token._balanced + ) { + result = true; + break + } + if (token._gfmAutolinkLiteralWalkedInto) { + result = false; + break + } + } + if (events.length > 0 && !result) { + events[events.length - 1][1]._gfmAutolinkLiteralWalkedInto = true; + } + return result +} + +const indent = { + tokenize: tokenizeIndent, + partial: true +}; +function gfmFootnote() { + return { + document: { + [91]: { + tokenize: tokenizeDefinitionStart, + continuation: { + tokenize: tokenizeDefinitionContinuation + }, + exit: gfmFootnoteDefinitionEnd + } + }, + text: { + [91]: { + tokenize: tokenizeGfmFootnoteCall + }, + [93]: { + add: 'after', + tokenize: tokenizePotentialGfmFootnoteCall, + resolveTo: resolveToPotentialGfmFootnoteCall + } } - if (code === null || markdownLineEnding(code)) { - effects.exit('tableRow'); - return ok(code) + } +} +function tokenizePotentialGfmFootnoteCall(effects, ok, nok) { + const self = this; + let index = self.events.length; + const defined = self.parser.gfmFootnotes || (self.parser.gfmFootnotes = []); + let labelStart; + while (index--) { + const token = self.events[index][1]; + if (token.type === 'labelImage') { + labelStart = token; + break } - if (markdownSpace(code)) { - return factorySpace(effects, bodyRowBreak, 'whitespace')(code) + if ( + token.type === 'gfmFootnoteCall' || + token.type === 'labelLink' || + token.type === 'label' || + token.type === 'image' || + token.type === 'link' + ) { + break } - effects.enter('data'); - return bodyRowData(code) } - function bodyRowData(code) { - if (code === null || code === 124 || markdownLineEndingOrSpace(code)) { - effects.exit('data'); - return bodyRowBreak(code) + return start + function start(code) { + if (!labelStart || !labelStart._balanced) { + return nok(code) + } + const id = normalizeIdentifier$1( + self.sliceSerialize({ + start: labelStart.end, + end: self.now() + }) + ); + if (id.codePointAt(0) !== 94 || !defined.includes(id.slice(1))) { + return nok(code) } + effects.enter('gfmFootnoteCallLabelMarker'); effects.consume(code); - return code === 92 ? bodyRowEscape : bodyRowData + effects.exit('gfmFootnoteCallLabelMarker'); + return ok(code) } - function bodyRowEscape(code) { - if (code === 92 || code === 124) { - effects.consume(code); - return bodyRowData +} +function resolveToPotentialGfmFootnoteCall(events, context) { + let index = events.length; + while (index--) { + if ( + events[index][1].type === 'labelImage' && + events[index][0] === 'enter' + ) { + events[index][1]; + break } - return bodyRowData(code) } + events[index + 1][1].type = 'data'; + events[index + 3][1].type = 'gfmFootnoteCallLabelMarker'; + const call = { + type: 'gfmFootnoteCall', + start: Object.assign({}, events[index + 3][1].start), + end: Object.assign({}, events[events.length - 1][1].end) + }; + const marker = { + type: 'gfmFootnoteCallMarker', + start: Object.assign({}, events[index + 3][1].end), + end: Object.assign({}, events[index + 3][1].end) + }; + marker.end.column++; + marker.end.offset++; + marker.end._bufferIndex++; + const string = { + type: 'gfmFootnoteCallString', + start: Object.assign({}, marker.end), + end: Object.assign({}, events[events.length - 1][1].start) + }; + const chunk = { + type: 'chunkString', + contentType: 'string', + start: Object.assign({}, string.start), + end: Object.assign({}, string.end) + }; + const replacement = [ + events[index + 1], + events[index + 2], + ['enter', call, context], + events[index + 3], + events[index + 4], + ['enter', marker, context], + ['exit', marker, context], + ['enter', string, context], + ['enter', chunk, context], + ['exit', chunk, context], + ['exit', string, context], + events[events.length - 2], + events[events.length - 1], + ['exit', call, context] + ]; + events.splice(index, events.length - index + 1, ...replacement); + return events } -function resolveTable(events, context) { - let index = -1; - let inFirstCellAwaitingPipe = true; - let rowKind = 0; - let lastCell = [0, 0, 0, 0]; - let cell = [0, 0, 0, 0]; - let afterHeadAwaitingFirstBodyRow = false; - let lastTableEnd = 0; - let currentTable; - let currentBody; - let currentCell; - const map = new EditMap(); - while (++index < events.length) { - const event = events[index]; - const token = event[1]; - if (event[0] === 'enter') { - if (token.type === 'tableHead') { - afterHeadAwaitingFirstBodyRow = false; - if (lastTableEnd !== 0) { - flushTableEnd(map, context, lastTableEnd, currentTable, currentBody); - currentBody = undefined; - lastTableEnd = 0; - } - currentTable = { - type: 'table', - start: Object.assign({}, token.start), - end: Object.assign({}, token.end) - }; - map.add(index, 0, [['enter', currentTable, context]]); - } else if ( - token.type === 'tableRow' || - token.type === 'tableDelimiterRow' - ) { - inFirstCellAwaitingPipe = true; - currentCell = undefined; - lastCell = [0, 0, 0, 0]; - cell = [0, index + 1, 0, 0]; - if (afterHeadAwaitingFirstBodyRow) { - afterHeadAwaitingFirstBodyRow = false; - currentBody = { - type: 'tableBody', - start: Object.assign({}, token.start), - end: Object.assign({}, token.end) - }; - map.add(index, 0, [['enter', currentBody, context]]); - } - rowKind = token.type === 'tableDelimiterRow' ? 2 : currentBody ? 3 : 1; - } - else if ( - rowKind && - (token.type === 'data' || - token.type === 'tableDelimiterMarker' || - token.type === 'tableDelimiterFiller') - ) { - inFirstCellAwaitingPipe = false; - if (cell[2] === 0) { - if (lastCell[1] !== 0) { - cell[0] = cell[1]; - currentCell = flushCell( - map, - context, - lastCell, - rowKind, - undefined, - currentCell - ); - lastCell = [0, 0, 0, 0]; - } - cell[2] = index; - } - } else if (token.type === 'tableCellDivider') { - if (inFirstCellAwaitingPipe) { - inFirstCellAwaitingPipe = false; - } else { - if (lastCell[1] !== 0) { - cell[0] = cell[1]; - currentCell = flushCell( - map, - context, - lastCell, - rowKind, - undefined, - currentCell - ); - } - lastCell = cell; - cell = [lastCell[1], index, 0, 0]; - } - } - } - else if (token.type === 'tableHead') { - afterHeadAwaitingFirstBodyRow = true; - lastTableEnd = index; - } else if ( - token.type === 'tableRow' || - token.type === 'tableDelimiterRow' +function tokenizeGfmFootnoteCall(effects, ok, nok) { + const self = this; + const defined = self.parser.gfmFootnotes || (self.parser.gfmFootnotes = []); + let size = 0; + let data; + return start + function start(code) { + effects.enter('gfmFootnoteCall'); + effects.enter('gfmFootnoteCallLabelMarker'); + effects.consume(code); + effects.exit('gfmFootnoteCallLabelMarker'); + return callStart + } + function callStart(code) { + if (code !== 94) return nok(code) + effects.enter('gfmFootnoteCallMarker'); + effects.consume(code); + effects.exit('gfmFootnoteCallMarker'); + effects.enter('gfmFootnoteCallString'); + effects.enter('chunkString').contentType = 'string'; + return callData + } + function callData(code) { + if ( + size > 999 || + (code === 93 && !data) || + code === null || + code === 91 || + markdownLineEndingOrSpace(code) ) { - lastTableEnd = index; - if (lastCell[1] !== 0) { - cell[0] = cell[1]; - currentCell = flushCell( - map, - context, - lastCell, - rowKind, - index, - currentCell - ); - } else if (cell[1] !== 0) { - currentCell = flushCell(map, context, cell, rowKind, index, currentCell); + return nok(code) + } + if (code === 93) { + effects.exit('chunkString'); + const token = effects.exit('gfmFootnoteCallString'); + if (!defined.includes(normalizeIdentifier$1(self.sliceSerialize(token)))) { + return nok(code) } - rowKind = 0; - } else if ( - rowKind && - (token.type === 'data' || - token.type === 'tableDelimiterMarker' || - token.type === 'tableDelimiterFiller') + effects.enter('gfmFootnoteCallLabelMarker'); + effects.consume(code); + effects.exit('gfmFootnoteCallLabelMarker'); + effects.exit('gfmFootnoteCall'); + return ok + } + if (!markdownLineEndingOrSpace(code)) { + data = true; + } + size++; + effects.consume(code); + return code === 92 ? callEscape : callData + } + function callEscape(code) { + if (code === 91 || code === 92 || code === 93) { + effects.consume(code); + size++; + return callData + } + return callData(code) + } +} +function tokenizeDefinitionStart(effects, ok, nok) { + const self = this; + const defined = self.parser.gfmFootnotes || (self.parser.gfmFootnotes = []); + let identifier; + let size = 0; + let data; + return start + function start(code) { + effects.enter('gfmFootnoteDefinition')._container = true; + effects.enter('gfmFootnoteDefinitionLabel'); + effects.enter('gfmFootnoteDefinitionLabelMarker'); + effects.consume(code); + effects.exit('gfmFootnoteDefinitionLabelMarker'); + return labelAtMarker + } + function labelAtMarker(code) { + if (code === 94) { + effects.enter('gfmFootnoteDefinitionMarker'); + effects.consume(code); + effects.exit('gfmFootnoteDefinitionMarker'); + effects.enter('gfmFootnoteDefinitionLabelString'); + effects.enter('chunkString').contentType = 'string'; + return labelInside + } + return nok(code) + } + function labelInside(code) { + if ( + size > 999 || + (code === 93 && !data) || + code === null || + code === 91 || + markdownLineEndingOrSpace(code) ) { - cell[3] = index; + return nok(code) + } + if (code === 93) { + effects.exit('chunkString'); + const token = effects.exit('gfmFootnoteDefinitionLabelString'); + identifier = normalizeIdentifier$1(self.sliceSerialize(token)); + effects.enter('gfmFootnoteDefinitionLabelMarker'); + effects.consume(code); + effects.exit('gfmFootnoteDefinitionLabelMarker'); + effects.exit('gfmFootnoteDefinitionLabel'); + return labelAfter + } + if (!markdownLineEndingOrSpace(code)) { + data = true; } + size++; + effects.consume(code); + return code === 92 ? labelEscape : labelInside } - if (lastTableEnd !== 0) { - flushTableEnd(map, context, lastTableEnd, currentTable, currentBody); + function labelEscape(code) { + if (code === 91 || code === 92 || code === 93) { + effects.consume(code); + size++; + return labelInside + } + return labelInside(code) } - map.consume(context.events); - index = -1; - while (++index < context.events.length) { - const event = context.events[index]; - if (event[0] === 'enter' && event[1].type === 'table') { - event[1]._align = gfmTableAlign(context.events, index); + function labelAfter(code) { + if (code === 58) { + effects.enter('definitionMarker'); + effects.consume(code); + effects.exit('definitionMarker'); + if (!defined.includes(identifier)) { + defined.push(identifier); + } + return factorySpace( + effects, + whitespaceAfter, + 'gfmFootnoteDefinitionWhitespace' + ) } + return nok(code) + } + function whitespaceAfter(code) { + return ok(code) } - return events } -function flushCell(map, context, range, rowKind, rowEnd, previousCell) { - const groupName = - rowKind === 1 - ? 'tableHeader' - : rowKind === 2 - ? 'tableDelimiter' - : 'tableData'; - const valueName = 'tableContent'; - if (range[0] !== 0) { - previousCell.end = Object.assign({}, getPoint(context.events, range[0])); - map.add(range[0], 0, [['exit', previousCell, context]]); +function tokenizeDefinitionContinuation(effects, ok, nok) { + return effects.check(blankLine, ok, effects.attempt(indent, ok, nok)) +} +function gfmFootnoteDefinitionEnd(effects) { + effects.exit('gfmFootnoteDefinition'); +} +function tokenizeIndent(effects, ok, nok) { + const self = this; + return factorySpace( + effects, + afterPrefix, + 'gfmFootnoteDefinitionIndent', + 4 + 1 + ) + function afterPrefix(code) { + const tail = self.events[self.events.length - 1]; + return tail && + tail[1].type === 'gfmFootnoteDefinitionIndent' && + tail[2].sliceSerialize(tail[1], true).length === 4 + ? ok(code) + : nok(code) } - const now = getPoint(context.events, range[1]); - previousCell = { - type: groupName, - start: Object.assign({}, now), - end: Object.assign({}, now) +} + +function gfmStrikethrough(options) { + const options_ = options || {}; + let single = options_.singleTilde; + const tokenizer = { + tokenize: tokenizeStrikethrough, + resolveAll: resolveAllStrikethrough }; - map.add(range[1], 0, [['enter', previousCell, context]]); - if (range[2] !== 0) { - const relatedStart = getPoint(context.events, range[2]); - const relatedEnd = getPoint(context.events, range[3]); - const valueToken = { - type: valueName, - start: Object.assign({}, relatedStart), - end: Object.assign({}, relatedEnd) - }; - map.add(range[2], 0, [['enter', valueToken, context]]); - if (rowKind !== 2) { - const start = context.events[range[2]]; - const end = context.events[range[3]]; - start[1].end = Object.assign({}, end[1].end); - start[1].type = 'chunkText'; - start[1].contentType = 'text'; - if (range[3] > range[2] + 1) { - const a = range[2] + 1; - const b = range[3] - range[2] - 1; - map.add(a, b, []); + if (single === null || single === undefined) { + single = true; + } + return { + text: { + [126]: tokenizer + }, + insideSpan: { + null: [tokenizer] + }, + attentionMarkers: { + null: [126] + } + } + function resolveAllStrikethrough(events, context) { + let index = -1; + while (++index < events.length) { + if ( + events[index][0] === 'enter' && + events[index][1].type === 'strikethroughSequenceTemporary' && + events[index][1]._close + ) { + let open = index; + while (open--) { + if ( + events[open][0] === 'exit' && + events[open][1].type === 'strikethroughSequenceTemporary' && + events[open][1]._open && + events[index][1].end.offset - events[index][1].start.offset === + events[open][1].end.offset - events[open][1].start.offset + ) { + events[index][1].type = 'strikethroughSequence'; + events[open][1].type = 'strikethroughSequence'; + const strikethrough = { + type: 'strikethrough', + start: Object.assign({}, events[open][1].start), + end: Object.assign({}, events[index][1].end) + }; + const text = { + type: 'strikethroughText', + start: Object.assign({}, events[open][1].end), + end: Object.assign({}, events[index][1].start) + }; + const nextEvents = [ + ['enter', strikethrough, context], + ['enter', events[open][1], context], + ['exit', events[open][1], context], + ['enter', text, context] + ]; + const insideSpan = context.parser.constructs.insideSpan.null; + if (insideSpan) { + splice( + nextEvents, + nextEvents.length, + 0, + resolveAll(insideSpan, events.slice(open + 1, index), context) + ); + } + splice(nextEvents, nextEvents.length, 0, [ + ['exit', text, context], + ['enter', events[index][1], context], + ['exit', events[index][1], context], + ['exit', strikethrough, context] + ]); + splice(events, open - 1, index - open + 3, nextEvents); + index = open + nextEvents.length - 2; + break + } + } + } + } + index = -1; + while (++index < events.length) { + if (events[index][1].type === 'strikethroughSequenceTemporary') { + events[index][1].type = 'data'; } } - map.add(range[3] + 1, 0, [['exit', valueToken, context]]); - } - if (rowEnd !== undefined) { - previousCell.end = Object.assign({}, getPoint(context.events, rowEnd)); - map.add(rowEnd, 0, [['exit', previousCell, context]]); - previousCell = undefined; + return events } - return previousCell -} -function flushTableEnd(map, context, index, table, tableBody) { - const exits = []; - const related = getPoint(context.events, index); - if (tableBody) { - tableBody.end = Object.assign({}, related); - exits.push(['exit', tableBody, context]); + function tokenizeStrikethrough(effects, ok, nok) { + const previous = this.previous; + const events = this.events; + let size = 0; + return start + function start(code) { + if ( + previous === 126 && + events[events.length - 1][1].type !== 'characterEscape' + ) { + return nok(code) + } + effects.enter('strikethroughSequenceTemporary'); + return more(code) + } + function more(code) { + const before = classifyCharacter(previous); + if (code === 126) { + if (size > 1) return nok(code) + effects.consume(code); + size++; + return more + } + if (size < 2 && !single) return nok(code) + const token = effects.exit('strikethroughSequenceTemporary'); + const after = classifyCharacter(code); + token._open = !after || (after === 2 && Boolean(before)); + token._close = !before || (before === 2 && Boolean(after)); + return ok(code) + } } - table.end = Object.assign({}, related); - exits.push(['exit', table, context]); - map.add(index + 1, 0, exits); -} -function getPoint(events, index) { - const event = events[index]; - const side = event[0] === 'enter' ? 'start' : 'end'; - return event[1][side] } -const tasklistCheck = { - tokenize: tokenizeTasklistCheck -}; -const gfmTaskListItem = { - text: { - [91]: tasklistCheck - } -}; -function tokenizeTasklistCheck(effects, ok, nok) { - const self = this; - return open - function open(code) { - if ( - self.previous !== null || - !self._gfmTasklistFirstContentOfListItem - ) { - return nok(code) - } - effects.enter('taskListCheck'); - effects.enter('taskListCheckMarker'); - effects.consume(code); - effects.exit('taskListCheckMarker'); - return inside +class EditMap { + constructor() { + this.map = []; } - function inside(code) { - if (markdownLineEndingOrSpace(code)) { - effects.enter('taskListCheckValueUnchecked'); - effects.consume(code); - effects.exit('taskListCheckValueUnchecked'); - return close - } - if (code === 88 || code === 120) { - effects.enter('taskListCheckValueChecked'); - effects.consume(code); - effects.exit('taskListCheckValueChecked'); - return close - } - return nok(code) + add(index, remove, add) { + addImpl(this, index, remove, add); } - function close(code) { - if (code === 93) { - effects.enter('taskListCheckMarker'); - effects.consume(code); - effects.exit('taskListCheckMarker'); - effects.exit('taskListCheck'); - return after + consume(events) { + this.map.sort(function (a, b) { + return a[0] - b[0] + }); + if (this.map.length === 0) { + return } - return nok(code) - } - function after(code) { - if (markdownLineEnding(code)) { - return ok(code) + let index = this.map.length; + const vecs = []; + while (index > 0) { + index -= 1; + vecs.push( + events.slice(this.map[index][0] + this.map[index][1]), + this.map[index][2] + ); + events.length = this.map[index][0]; } - if (markdownSpace(code)) { - return effects.check( - { - tokenize: spaceThenNonSpace - }, - ok, - nok - )(code) + vecs.push([...events]); + events.length = 0; + let slice = vecs.pop(); + while (slice) { + events.push(...slice); + slice = vecs.pop(); } - return nok(code) - } -} -function spaceThenNonSpace(effects, ok, nok) { - return factorySpace(effects, after, 'whitespace') - function after(code) { - return code === null ? nok(code) : ok(code) + this.map.length = 0; } } - -function gfm(options) { - return combineExtensions([ - gfmAutolinkLiteral, - gfmFootnote(), - gfmStrikethrough(options), - gfmTable, - gfmTaskListItem - ]) -} - -function ccount(value, character) { - const source = String(value); - if (typeof character !== 'string') { - throw new TypeError('Expected character') +function addImpl(editMap, at, remove, add) { + let index = 0; + if (remove === 0 && add.length === 0) { + return } - let count = 0; - let index = source.indexOf(character); - while (index !== -1) { - count++; - index = source.indexOf(character, index + character.length); + while (index < editMap.map.length) { + if (editMap.map[index][0] === at) { + editMap.map[index][1] += remove; + editMap.map[index][2].push(...add); + return + } + index += 1; } - return count -} - -function escapeStringRegexp(string) { - if (typeof string !== 'string') { - throw new TypeError('Expected a string'); - } - return string - .replace(/[|\\{}()[\]^$+*?.]/g, '\\$&') - .replace(/-/g, '\\x2d'); + editMap.map.push([at, remove, add]); } -const own$2 = {}.hasOwnProperty; -const findAndReplace = - ( - function (tree, find, replace, options) { - let settings; - let schema; - if (typeof find === 'string' || find instanceof RegExp) { - schema = [[find, replace]]; - settings = options; - } else { - schema = find; - settings = replace; - } - if (!settings) { - settings = {}; - } - const ignored = convert(settings.ignore || []); - const pairs = toPairs(schema); - let pairIndex = -1; - while (++pairIndex < pairs.length) { - visitParents$1(tree, 'text', visitor); - } - return tree - function visitor(node, parents) { - let index = -1; - let grandparent; - while (++index < parents.length) { - const parent = parents[index]; - if ( - ignored( - parent, - grandparent ? grandparent.children.indexOf(parent) : undefined, - grandparent - ) - ) { - return - } - grandparent = parent; - } - if (grandparent) { - return handler(node, parents) +function gfmTableAlign(events, index) { + let inDelimiterRow = false; + const align = []; + while (index < events.length) { + const event = events[index]; + if (inDelimiterRow) { + if (event[0] === 'enter') { + if (event[1].type === 'tableContent') { + align.push( + events[index + 1][1].type === 'tableDelimiterMarker' + ? 'left' + : 'none' + ); } } - function handler(node, parents) { - const parent = parents[parents.length - 1]; - const find = pairs[pairIndex][0]; - const replace = pairs[pairIndex][1]; - let start = 0; - const index = parent.children.indexOf(node); - let change = false; - let nodes = []; - find.lastIndex = 0; - let match = find.exec(node.value); - while (match) { - const position = match.index; - const matchObject = { - index: match.index, - input: match.input, - stack: [...parents, node] - }; - let value = replace(...match, matchObject); - if (typeof value === 'string') { - value = value.length > 0 ? {type: 'text', value} : undefined; - } - if (value !== false) { - if (start !== position) { - nodes.push({ - type: 'text', - value: node.value.slice(start, position) - }); - } - if (Array.isArray(value)) { - nodes.push(...value); - } else if (value) { - nodes.push(value); - } - start = position + match[0].length; - change = true; - } - if (!find.global) { - break - } - match = find.exec(node.value); - } - if (change) { - if (start < node.value.length) { - nodes.push({type: 'text', value: node.value.slice(start)}); - } - parent.children.splice(index, 1, ...nodes); - } else { - nodes = [node]; + else if (event[1].type === 'tableContent') { + if (events[index - 1][1].type === 'tableDelimiterMarker') { + const alignIndex = align.length - 1; + align[alignIndex] = align[alignIndex] === 'left' ? 'center' : 'right'; } - return index + nodes.length } + else if (event[1].type === 'tableDelimiterRow') { + break + } + } else if (event[0] === 'enter' && event[1].type === 'tableDelimiterRow') { + inDelimiterRow = true; + } + index += 1; + } + return align +} + +function gfmTable() { + return { + flow: { + null: { + tokenize: tokenizeTable, + resolveAll: resolveTable + } + } + } +} +function tokenizeTable(effects, ok, nok) { + const self = this; + let size = 0; + let sizeB = 0; + let seen; + return start + function start(code) { + let index = self.events.length - 1; + while (index > -1) { + const type = self.events[index][1].type; + if ( + type === 'lineEnding' || + type === 'linePrefix' + ) + index--; + else break + } + const tail = index > -1 ? self.events[index][1].type : null; + const next = + tail === 'tableHead' || tail === 'tableRow' ? bodyRowStart : headRowBefore; + if (next === bodyRowStart && self.parser.lazy[self.now().line]) { + return nok(code) + } + return next(code) + } + function headRowBefore(code) { + effects.enter('tableHead'); + effects.enter('tableRow'); + return headRowStart(code) + } + function headRowStart(code) { + if (code === 124) { + return headRowBreak(code) } - ); -function toPairs(schema) { - const result = []; - if (typeof schema !== 'object') { - throw new TypeError('Expected array or object as schema') + seen = true; + sizeB += 1; + return headRowBreak(code) } - if (Array.isArray(schema)) { - let index = -1; - while (++index < schema.length) { - result.push([ - toExpression(schema[index][0]), - toFunction(schema[index][1]) - ]); + function headRowBreak(code) { + if (code === null) { + return nok(code) } - } else { - let key; - for (key in schema) { - if (own$2.call(schema, key)) { - result.push([toExpression(key), toFunction(schema[key])]); + if (markdownLineEnding(code)) { + if (sizeB > 1) { + sizeB = 0; + self.interrupt = true; + effects.exit('tableRow'); + effects.enter('lineEnding'); + effects.consume(code); + effects.exit('lineEnding'); + return headDelimiterStart } + return nok(code) } + if (markdownSpace(code)) { + return factorySpace(effects, headRowBreak, 'whitespace')(code) + } + sizeB += 1; + if (seen) { + seen = false; + size += 1; + } + if (code === 124) { + effects.enter('tableCellDivider'); + effects.consume(code); + effects.exit('tableCellDivider'); + seen = true; + return headRowBreak + } + effects.enter('data'); + return headRowData(code) } - return result -} -function toExpression(find) { - return typeof find === 'string' ? new RegExp(escapeStringRegexp(find), 'g') : find -} -function toFunction(replace) { - return typeof replace === 'function' ? replace : () => replace -} - -const inConstruct = 'phrasing'; -const notInConstruct = ['autolink', 'link', 'image', 'label']; -const gfmAutolinkLiteralFromMarkdown = { - transforms: [transformGfmAutolinkLiterals], - enter: { - literalAutolink: enterLiteralAutolink, - literalAutolinkEmail: enterLiteralAutolinkValue, - literalAutolinkHttp: enterLiteralAutolinkValue, - literalAutolinkWww: enterLiteralAutolinkValue - }, - exit: { - literalAutolink: exitLiteralAutolink, - literalAutolinkEmail: exitLiteralAutolinkEmail, - literalAutolinkHttp: exitLiteralAutolinkHttp, - literalAutolinkWww: exitLiteralAutolinkWww - } -}; -const gfmAutolinkLiteralToMarkdown = { - unsafe: [ - { - character: '@', - before: '[+\\-.\\w]', - after: '[\\-.\\w]', - inConstruct, - notInConstruct - }, - { - character: '.', - before: '[Ww]', - after: '[\\-.\\w]', - inConstruct, - notInConstruct - }, - {character: ':', before: '[ps]', after: '\\/', inConstruct, notInConstruct} - ] -}; -function enterLiteralAutolink(token) { - this.enter({type: 'link', title: null, url: '', children: []}, token); -} -function enterLiteralAutolinkValue(token) { - this.config.enter.autolinkProtocol.call(this, token); -} -function exitLiteralAutolinkHttp(token) { - this.config.exit.autolinkProtocol.call(this, token); -} -function exitLiteralAutolinkWww(token) { - this.config.exit.data.call(this, token); - const node = (this.stack[this.stack.length - 1]); - node.url = 'http://' + this.sliceSerialize(token); -} -function exitLiteralAutolinkEmail(token) { - this.config.exit.autolinkEmail.call(this, token); -} -function exitLiteralAutolink(token) { - this.exit(token); -} -function transformGfmAutolinkLiterals(tree) { - findAndReplace( - tree, - [ - [/(https?:\/\/|www(?=\.))([-.\w]+)([^ \t\r\n]*)/gi, findUrl], - [/([-.\w+]+)@([-\w]+(?:\.[-\w]+)+)/g, findEmail] - ], - {ignore: ['link', 'linkReference']} - ); -} -function findUrl(_, protocol, domain, path, match) { - let prefix = ''; - if (!previous(match)) { - return false - } - if (/^w/i.test(protocol)) { - domain = protocol + domain; - protocol = ''; - prefix = 'http://'; - } - if (!isCorrectDomain(domain)) { - return false - } - const parts = splitUrl(domain + path); - if (!parts[0]) return false - const result = { - type: 'link', - title: null, - url: prefix + protocol + parts[0], - children: [{type: 'text', value: protocol + parts[0]}] - }; - if (parts[1]) { - return [result, {type: 'text', value: parts[1]}] + function headRowData(code) { + if (code === null || code === 124 || markdownLineEndingOrSpace(code)) { + effects.exit('data'); + return headRowBreak(code) + } + effects.consume(code); + return code === 92 ? headRowEscape : headRowData } - return result -} -function findEmail(_, atext, label, match) { - if ( - !previous(match, true) || - /[-\d_]$/.test(label) - ) { - return false + function headRowEscape(code) { + if (code === 92 || code === 124) { + effects.consume(code); + return headRowData + } + return headRowData(code) } - return { - type: 'link', - title: null, - url: 'mailto:' + atext + '@' + label, - children: [{type: 'text', value: atext + '@' + label}] + function headDelimiterStart(code) { + self.interrupt = false; + if (self.parser.lazy[self.now().line]) { + return nok(code) + } + effects.enter('tableDelimiterRow'); + seen = false; + if (markdownSpace(code)) { + return factorySpace( + effects, + headDelimiterBefore, + 'linePrefix', + self.parser.constructs.disable.null.includes('codeIndented') + ? undefined + : 4 + )(code) + } + return headDelimiterBefore(code) } -} -function isCorrectDomain(domain) { - const parts = domain.split('.'); - if ( - parts.length < 2 || - (parts[parts.length - 1] && - (/_/.test(parts[parts.length - 1]) || - !/[a-zA-Z\d]/.test(parts[parts.length - 1]))) || - (parts[parts.length - 2] && - (/_/.test(parts[parts.length - 2]) || - !/[a-zA-Z\d]/.test(parts[parts.length - 2]))) - ) { - return false + function headDelimiterBefore(code) { + if (code === 45 || code === 58) { + return headDelimiterValueBefore(code) + } + if (code === 124) { + seen = true; + effects.enter('tableCellDivider'); + effects.consume(code); + effects.exit('tableCellDivider'); + return headDelimiterCellBefore + } + return headDelimiterNok(code) } - return true -} -function splitUrl(url) { - const trailExec = /[!"&'),.:;<>?\]}]+$/.exec(url); - if (!trailExec) { - return [url, undefined] + function headDelimiterCellBefore(code) { + if (markdownSpace(code)) { + return factorySpace(effects, headDelimiterValueBefore, 'whitespace')(code) + } + return headDelimiterValueBefore(code) } - url = url.slice(0, trailExec.index); - let trail = trailExec[0]; - let closingParenIndex = trail.indexOf(')'); - const openingParens = ccount(url, '('); - let closingParens = ccount(url, ')'); - while (closingParenIndex !== -1 && openingParens > closingParens) { - url += trail.slice(0, closingParenIndex + 1); - trail = trail.slice(closingParenIndex + 1); - closingParenIndex = trail.indexOf(')'); - closingParens++; + function headDelimiterValueBefore(code) { + if (code === 58) { + sizeB += 1; + seen = true; + effects.enter('tableDelimiterMarker'); + effects.consume(code); + effects.exit('tableDelimiterMarker'); + return headDelimiterLeftAlignmentAfter + } + if (code === 45) { + sizeB += 1; + return headDelimiterLeftAlignmentAfter(code) + } + if (code === null || markdownLineEnding(code)) { + return headDelimiterCellAfter(code) + } + return headDelimiterNok(code) } - return [url, trail] -} -function previous(match, email) { - const code = match.input.charCodeAt(match.index - 1); - return ( - (match.index === 0 || - unicodeWhitespace(code) || - unicodePunctuation(code)) && - (!email || code !== 47) - ) -} - -footnoteReference.peek = footnoteReferencePeek; -function gfmFootnoteFromMarkdown() { - return { - enter: { - gfmFootnoteDefinition: enterFootnoteDefinition, - gfmFootnoteDefinitionLabelString: enterFootnoteDefinitionLabelString, - gfmFootnoteCall: enterFootnoteCall, - gfmFootnoteCallString: enterFootnoteCallString - }, - exit: { - gfmFootnoteDefinition: exitFootnoteDefinition, - gfmFootnoteDefinitionLabelString: exitFootnoteDefinitionLabelString, - gfmFootnoteCall: exitFootnoteCall, - gfmFootnoteCallString: exitFootnoteCallString + function headDelimiterLeftAlignmentAfter(code) { + if (code === 45) { + effects.enter('tableDelimiterFiller'); + return headDelimiterFiller(code) } + return headDelimiterNok(code) } -} -function gfmFootnoteToMarkdown() { - return { - unsafe: [{character: '[', inConstruct: ['phrasing', 'label', 'reference']}], - handlers: {footnoteDefinition, footnoteReference} - } -} -function enterFootnoteDefinition(token) { - this.enter( - {type: 'footnoteDefinition', identifier: '', label: '', children: []}, - token - ); -} -function enterFootnoteDefinitionLabelString() { - this.buffer(); -} -function exitFootnoteDefinitionLabelString(token) { - const label = this.resume(); - const node = ( - this.stack[this.stack.length - 1] - ); - node.label = label; - node.identifier = normalizeIdentifier( - this.sliceSerialize(token) - ).toLowerCase(); -} -function exitFootnoteDefinition(token) { - this.exit(token); -} -function enterFootnoteCall(token) { - this.enter({type: 'footnoteReference', identifier: '', label: ''}, token); -} -function enterFootnoteCallString() { - this.buffer(); -} -function exitFootnoteCallString(token) { - const label = this.resume(); - const node = ( - this.stack[this.stack.length - 1] - ); - node.label = label; - node.identifier = normalizeIdentifier( - this.sliceSerialize(token) - ).toLowerCase(); -} -function exitFootnoteCall(token) { - this.exit(token); -} -function footnoteReference(node, _, context, safeOptions) { - const tracker = track(safeOptions); - let value = tracker.move('[^'); - const exit = context.enter('footnoteReference'); - const subexit = context.enter('reference'); - value += tracker.move( - safe(context, association(node), { - ...tracker.current(), - before: value, - after: ']' - }) - ); - subexit(); - exit(); - value += tracker.move(']'); - return value -} -function footnoteReferencePeek() { - return '[' -} -function footnoteDefinition(node, _, context, safeOptions) { - const tracker = track(safeOptions); - let value = tracker.move('[^'); - const exit = context.enter('footnoteDefinition'); - const subexit = context.enter('label'); - value += tracker.move( - safe(context, association(node), { - ...tracker.current(), - before: value, - after: ']' - }) - ); - subexit(); - value += tracker.move( - ']:' + (node.children && node.children.length > 0 ? ' ' : '') - ); - tracker.shift(4); - value += tracker.move( - indentLines(containerFlow(node, context, tracker.current()), map$1) - ); - exit(); - return value -} -function map$1(line, index, blank) { - if (index === 0) { - return line + function headDelimiterFiller(code) { + if (code === 45) { + effects.consume(code); + return headDelimiterFiller + } + if (code === 58) { + seen = true; + effects.exit('tableDelimiterFiller'); + effects.enter('tableDelimiterMarker'); + effects.consume(code); + effects.exit('tableDelimiterMarker'); + return headDelimiterRightAlignmentAfter + } + effects.exit('tableDelimiterFiller'); + return headDelimiterRightAlignmentAfter(code) } - return (blank ? '' : ' ') + line -} - -const constructsWithoutStrikethrough = [ - 'autolink', - 'destinationLiteral', - 'destinationRaw', - 'reference', - 'titleQuote', - 'titleApostrophe' -]; -handleDelete.peek = peekDelete; -const gfmStrikethroughFromMarkdown = { - canContainEols: ['delete'], - enter: {strikethrough: enterStrikethrough}, - exit: {strikethrough: exitStrikethrough} -}; -const gfmStrikethroughToMarkdown = { - unsafe: [ - { - character: '~', - inConstruct: 'phrasing', - notInConstruct: constructsWithoutStrikethrough + function headDelimiterRightAlignmentAfter(code) { + if (markdownSpace(code)) { + return factorySpace(effects, headDelimiterCellAfter, 'whitespace')(code) } - ], - handlers: {delete: handleDelete} -}; -function enterStrikethrough(token) { - this.enter({type: 'delete', children: []}, token); -} -function exitStrikethrough(token) { - this.exit(token); -} -function handleDelete(node, _, context, safeOptions) { - const tracker = track(safeOptions); - const exit = context.enter('strikethrough'); - let value = tracker.move('~~'); - value += containerPhrasing(node, context, { - ...tracker.current(), - before: value, - after: '~' - }); - value += tracker.move('~~'); - exit(); - return value -} -function peekDelete() { - return '~' -} - -function markdownTable(table, options = {}) { - const align = (options.align || []).concat(); - const stringLength = options.stringLength || defaultStringLength; - const alignments = []; - const cellMatrix = []; - const sizeMatrix = []; - const longestCellByColumn = []; - let mostCellsPerRow = 0; - let rowIndex = -1; - while (++rowIndex < table.length) { - const row = []; - const sizes = []; - let columnIndex = -1; - if (table[rowIndex].length > mostCellsPerRow) { - mostCellsPerRow = table[rowIndex].length; + return headDelimiterCellAfter(code) + } + function headDelimiterCellAfter(code) { + if (code === 124) { + return headDelimiterBefore(code) } - while (++columnIndex < table[rowIndex].length) { - const cell = serialize(table[rowIndex][columnIndex]); - if (options.alignDelimiters !== false) { - const size = stringLength(cell); - sizes[columnIndex] = size; - if ( - longestCellByColumn[columnIndex] === undefined || - size > longestCellByColumn[columnIndex] - ) { - longestCellByColumn[columnIndex] = size; - } + if (code === null || markdownLineEnding(code)) { + if (!seen || size !== sizeB) { + return headDelimiterNok(code) } - row.push(cell); + effects.exit('tableDelimiterRow'); + effects.exit('tableHead'); + return ok(code) } - cellMatrix[rowIndex] = row; - sizeMatrix[rowIndex] = sizes; + return headDelimiterNok(code) } - let columnIndex = -1; - if (typeof align === 'object' && 'length' in align) { - while (++columnIndex < mostCellsPerRow) { - alignments[columnIndex] = toAlignment(align[columnIndex]); + function headDelimiterNok(code) { + return nok(code) + } + function bodyRowStart(code) { + effects.enter('tableRow'); + return bodyRowBreak(code) + } + function bodyRowBreak(code) { + if (code === 124) { + effects.enter('tableCellDivider'); + effects.consume(code); + effects.exit('tableCellDivider'); + return bodyRowBreak } - } else { - const code = toAlignment(align); - while (++columnIndex < mostCellsPerRow) { - alignments[columnIndex] = code; + if (code === null || markdownLineEnding(code)) { + effects.exit('tableRow'); + return ok(code) } + if (markdownSpace(code)) { + return factorySpace(effects, bodyRowBreak, 'whitespace')(code) + } + effects.enter('data'); + return bodyRowData(code) } - columnIndex = -1; - const row = []; - const sizes = []; - while (++columnIndex < mostCellsPerRow) { - const code = alignments[columnIndex]; - let before = ''; - let after = ''; - if (code === 99 ) { - before = ':'; - after = ':'; - } else if (code === 108 ) { - before = ':'; - } else if (code === 114 ) { - after = ':'; + function bodyRowData(code) { + if (code === null || code === 124 || markdownLineEndingOrSpace(code)) { + effects.exit('data'); + return bodyRowBreak(code) } - let size = - options.alignDelimiters === false - ? 1 - : Math.max( - 1, - longestCellByColumn[columnIndex] - before.length - after.length - ); - const cell = before + '-'.repeat(size) + after; - if (options.alignDelimiters !== false) { - size = before.length + size + after.length; - if (size > longestCellByColumn[columnIndex]) { - longestCellByColumn[columnIndex] = size; + effects.consume(code); + return code === 92 ? bodyRowEscape : bodyRowData + } + function bodyRowEscape(code) { + if (code === 92 || code === 124) { + effects.consume(code); + return bodyRowData + } + return bodyRowData(code) + } +} +function resolveTable(events, context) { + let index = -1; + let inFirstCellAwaitingPipe = true; + let rowKind = 0; + let lastCell = [0, 0, 0, 0]; + let cell = [0, 0, 0, 0]; + let afterHeadAwaitingFirstBodyRow = false; + let lastTableEnd = 0; + let currentTable; + let currentBody; + let currentCell; + const map = new EditMap(); + while (++index < events.length) { + const event = events[index]; + const token = event[1]; + if (event[0] === 'enter') { + if (token.type === 'tableHead') { + afterHeadAwaitingFirstBodyRow = false; + if (lastTableEnd !== 0) { + flushTableEnd(map, context, lastTableEnd, currentTable, currentBody); + currentBody = undefined; + lastTableEnd = 0; + } + currentTable = { + type: 'table', + start: Object.assign({}, token.start), + end: Object.assign({}, token.end) + }; + map.add(index, 0, [['enter', currentTable, context]]); + } else if ( + token.type === 'tableRow' || + token.type === 'tableDelimiterRow' + ) { + inFirstCellAwaitingPipe = true; + currentCell = undefined; + lastCell = [0, 0, 0, 0]; + cell = [0, index + 1, 0, 0]; + if (afterHeadAwaitingFirstBodyRow) { + afterHeadAwaitingFirstBodyRow = false; + currentBody = { + type: 'tableBody', + start: Object.assign({}, token.start), + end: Object.assign({}, token.end) + }; + map.add(index, 0, [['enter', currentBody, context]]); + } + rowKind = token.type === 'tableDelimiterRow' ? 2 : currentBody ? 3 : 1; } - sizes[columnIndex] = size; - } - row[columnIndex] = cell; - } - cellMatrix.splice(1, 0, row); - sizeMatrix.splice(1, 0, sizes); - rowIndex = -1; - const lines = []; - while (++rowIndex < cellMatrix.length) { - const row = cellMatrix[rowIndex]; - const sizes = sizeMatrix[rowIndex]; - columnIndex = -1; - const line = []; - while (++columnIndex < mostCellsPerRow) { - const cell = row[columnIndex] || ''; - let before = ''; - let after = ''; - if (options.alignDelimiters !== false) { - const size = - longestCellByColumn[columnIndex] - (sizes[columnIndex] || 0); - const code = alignments[columnIndex]; - if (code === 114 ) { - before = ' '.repeat(size); - } else if (code === 99 ) { - if (size % 2) { - before = ' '.repeat(size / 2 + 0.5); - after = ' '.repeat(size / 2 - 0.5); - } else { - before = ' '.repeat(size / 2); - after = before; + else if ( + rowKind && + (token.type === 'data' || + token.type === 'tableDelimiterMarker' || + token.type === 'tableDelimiterFiller') + ) { + inFirstCellAwaitingPipe = false; + if (cell[2] === 0) { + if (lastCell[1] !== 0) { + cell[0] = cell[1]; + currentCell = flushCell( + map, + context, + lastCell, + rowKind, + undefined, + currentCell + ); + lastCell = [0, 0, 0, 0]; } + cell[2] = index; + } + } else if (token.type === 'tableCellDivider') { + if (inFirstCellAwaitingPipe) { + inFirstCellAwaitingPipe = false; } else { - after = ' '.repeat(size); + if (lastCell[1] !== 0) { + cell[0] = cell[1]; + currentCell = flushCell( + map, + context, + lastCell, + rowKind, + undefined, + currentCell + ); + } + lastCell = cell; + cell = [lastCell[1], index, 0, 0]; } } - if (options.delimiterStart !== false && !columnIndex) { - line.push('|'); - } - if ( - options.padding !== false && - !(options.alignDelimiters === false && cell === '') && - (options.delimiterStart !== false || columnIndex) - ) { - line.push(' '); - } - if (options.alignDelimiters !== false) { - line.push(before); - } - line.push(cell); - if (options.alignDelimiters !== false) { - line.push(after); - } - if (options.padding !== false) { - line.push(' '); - } - if ( - options.delimiterEnd !== false || - columnIndex !== mostCellsPerRow - 1 - ) { - line.push('|'); + } + else if (token.type === 'tableHead') { + afterHeadAwaitingFirstBodyRow = true; + lastTableEnd = index; + } else if ( + token.type === 'tableRow' || + token.type === 'tableDelimiterRow' + ) { + lastTableEnd = index; + if (lastCell[1] !== 0) { + cell[0] = cell[1]; + currentCell = flushCell( + map, + context, + lastCell, + rowKind, + index, + currentCell + ); + } else if (cell[1] !== 0) { + currentCell = flushCell(map, context, cell, rowKind, index, currentCell); } + rowKind = 0; + } else if ( + rowKind && + (token.type === 'data' || + token.type === 'tableDelimiterMarker' || + token.type === 'tableDelimiterFiller') + ) { + cell[3] = index; } - lines.push( - options.delimiterEnd === false - ? line.join('').replace(/ +$/, '') - : line.join('') - ); } - return lines.join('\n') -} -function serialize(value) { - return value === null || value === undefined ? '' : String(value) -} -function defaultStringLength(value) { - return value.length -} -function toAlignment(value) { - const code = typeof value === 'string' ? value.codePointAt(0) : 0; - return code === 67 || code === 99 - ? 99 - : code === 76 || code === 108 - ? 108 - : code === 82 || code === 114 - ? 114 - : 0 -} - -const gfmTableFromMarkdown = { - enter: { - table: enterTable, - tableData: enterCell, - tableHeader: enterCell, - tableRow: enterRow - }, - exit: { - codeText: exitCodeText, - table: exitTable, - tableData: exit, - tableHeader: exit, - tableRow: exit + if (lastTableEnd !== 0) { + flushTableEnd(map, context, lastTableEnd, currentTable, currentBody); } -}; -function enterTable(token) { - const align = token._align; - this.enter( - { - type: 'table', - align: align.map((d) => (d === 'none' ? null : d)), - children: [] - }, - token - ); - this.setData('inTable', true); -} -function exitTable(token) { - this.exit(token); - this.setData('inTable'); -} -function enterRow(token) { - this.enter({type: 'tableRow', children: []}, token); -} -function exit(token) { - this.exit(token); + map.consume(context.events); + index = -1; + while (++index < context.events.length) { + const event = context.events[index]; + if (event[0] === 'enter' && event[1].type === 'table') { + event[1]._align = gfmTableAlign(context.events, index); + } + } + return events } -function enterCell(token) { - this.enter({type: 'tableCell', children: []}, token); +function flushCell(map, context, range, rowKind, rowEnd, previousCell) { + const groupName = + rowKind === 1 + ? 'tableHeader' + : rowKind === 2 + ? 'tableDelimiter' + : 'tableData'; + const valueName = 'tableContent'; + if (range[0] !== 0) { + previousCell.end = Object.assign({}, getPoint(context.events, range[0])); + map.add(range[0], 0, [['exit', previousCell, context]]); + } + const now = getPoint(context.events, range[1]); + previousCell = { + type: groupName, + start: Object.assign({}, now), + end: Object.assign({}, now) + }; + map.add(range[1], 0, [['enter', previousCell, context]]); + if (range[2] !== 0) { + const relatedStart = getPoint(context.events, range[2]); + const relatedEnd = getPoint(context.events, range[3]); + const valueToken = { + type: valueName, + start: Object.assign({}, relatedStart), + end: Object.assign({}, relatedEnd) + }; + map.add(range[2], 0, [['enter', valueToken, context]]); + if (rowKind !== 2) { + const start = context.events[range[2]]; + const end = context.events[range[3]]; + start[1].end = Object.assign({}, end[1].end); + start[1].type = 'chunkText'; + start[1].contentType = 'text'; + if (range[3] > range[2] + 1) { + const a = range[2] + 1; + const b = range[3] - range[2] - 1; + map.add(a, b, []); + } + } + map.add(range[3] + 1, 0, [['exit', valueToken, context]]); + } + if (rowEnd !== undefined) { + previousCell.end = Object.assign({}, getPoint(context.events, rowEnd)); + map.add(rowEnd, 0, [['exit', previousCell, context]]); + previousCell = undefined; + } + return previousCell } -function exitCodeText(token) { - let value = this.resume(); - if (this.getData('inTable')) { - value = value.replace(/\\([\\|])/g, replace); +function flushTableEnd(map, context, index, table, tableBody) { + const exits = []; + const related = getPoint(context.events, index); + if (tableBody) { + tableBody.end = Object.assign({}, related); + exits.push(['exit', tableBody, context]); } - const node = (this.stack[this.stack.length - 1]); - node.value = value; - this.exit(token); + table.end = Object.assign({}, related); + exits.push(['exit', table, context]); + map.add(index + 1, 0, exits); } -function replace($0, $1) { - return $1 === '|' ? $1 : $0 +function getPoint(events, index) { + const event = events[index]; + const side = event[0] === 'enter' ? 'start' : 'end'; + return event[1][side] } -function gfmTableToMarkdown(options) { - const settings = options || {}; - const padding = settings.tableCellPadding; - const alignDelimiters = settings.tablePipeAlign; - const stringLength = settings.stringLength; - const around = padding ? ' ' : '|'; + +const tasklistCheck = { + tokenize: tokenizeTasklistCheck +}; +function gfmTaskListItem() { return { - unsafe: [ - {character: '\r', inConstruct: 'tableCell'}, - {character: '\n', inConstruct: 'tableCell'}, - {atBreak: true, character: '|', after: '[\t :-]'}, - {character: '|', inConstruct: 'tableCell'}, - {atBreak: true, character: ':', after: '-'}, - {atBreak: true, character: '-', after: '[:|-]'} - ], - handlers: { - table: handleTable, - tableRow: handleTableRow, - tableCell: handleTableCell, - inlineCode: inlineCodeWithTable + text: { + [91]: tasklistCheck } } - function handleTable(node, _, context, safeOptions) { - return serializeData( - handleTableAsData(node, context, safeOptions), - node.align - ) - } - function handleTableRow(node, _, context, safeOptions) { - const row = handleTableRowAsData(node, context, safeOptions); - const value = serializeData([row]); - return value.slice(0, value.indexOf('\n')) - } - function handleTableCell(node, _, context, safeOptions) { - const exit = context.enter('tableCell'); - const subexit = context.enter('phrasing'); - const value = containerPhrasing(node, context, { - ...safeOptions, - before: around, - after: around - }); - subexit(); - exit(); - return value - } - function serializeData(matrix, align) { - return markdownTable(matrix, { - align, - alignDelimiters, - padding, - stringLength - }) - } - function handleTableAsData(node, context, safeOptions) { - const children = node.children; - let index = -1; - const result = []; - const subexit = context.enter('table'); - while (++index < children.length) { - result[index] = handleTableRowAsData( - children[index], - context, - safeOptions - ); +} +function tokenizeTasklistCheck(effects, ok, nok) { + const self = this; + return open + function open(code) { + if ( + self.previous !== null || + !self._gfmTasklistFirstContentOfListItem + ) { + return nok(code) } - subexit(); - return result + effects.enter('taskListCheck'); + effects.enter('taskListCheckMarker'); + effects.consume(code); + effects.exit('taskListCheckMarker'); + return inside } - function handleTableRowAsData(node, context, safeOptions) { - const children = node.children; - let index = -1; - const result = []; - const subexit = context.enter('tableRow'); - while (++index < children.length) { - result[index] = handleTableCell( - children[index], - node, - context, - safeOptions - ); + function inside(code) { + if (markdownLineEndingOrSpace(code)) { + effects.enter('taskListCheckValueUnchecked'); + effects.consume(code); + effects.exit('taskListCheckValueUnchecked'); + return close } - subexit(); - return result - } - function inlineCodeWithTable(node, parent, context) { - let value = inlineCode(node, parent, context); - if (context.stack.includes('tableCell')) { - value = value.replace(/\|/g, '\\$&'); + if (code === 88 || code === 120) { + effects.enter('taskListCheckValueChecked'); + effects.consume(code); + effects.exit('taskListCheckValueChecked'); + return close } - return value + return nok(code) } -} - -const gfmTaskListItemFromMarkdown = { - exit: { - taskListCheckValueChecked: exitCheck, - taskListCheckValueUnchecked: exitCheck, - paragraph: exitParagraphWithTaskListItem + function close(code) { + if (code === 93) { + effects.enter('taskListCheckMarker'); + effects.consume(code); + effects.exit('taskListCheckMarker'); + effects.exit('taskListCheck'); + return after + } + return nok(code) } -}; -const gfmTaskListItemToMarkdown = { - unsafe: [{atBreak: true, character: '-', after: '[:|-]'}], - handlers: {listItem: listItemWithTaskListItem} -}; -function exitCheck(token) { - const node = (this.stack[this.stack.length - 2]); - node.checked = token.type === 'taskListCheckValueChecked'; -} -function exitParagraphWithTaskListItem(token) { - const parent = (this.stack[this.stack.length - 2]); - if ( - parent && - parent.type === 'listItem' && - typeof parent.checked === 'boolean' - ) { - const node = (this.stack[this.stack.length - 1]); - const head = node.children[0]; - if (head && head.type === 'text') { - const siblings = parent.children; - let index = -1; - let firstParaghraph; - while (++index < siblings.length) { - const sibling = siblings[index]; - if (sibling.type === 'paragraph') { - firstParaghraph = sibling; - break - } - } - if (firstParaghraph === node) { - head.value = head.value.slice(1); - if (head.value.length === 0) { - node.children.shift(); - } else if ( - node.position && - head.position && - typeof head.position.start.offset === 'number' - ) { - head.position.start.column++; - head.position.start.offset++; - node.position.start = Object.assign({}, head.position.start); - } - } + function after(code) { + if (markdownLineEnding(code)) { + return ok(code) + } + if (markdownSpace(code)) { + return effects.check( + { + tokenize: spaceThenNonSpace + }, + ok, + nok + )(code) } + return nok(code) } - this.exit(token); } -function listItemWithTaskListItem(node, parent, context, safeOptions) { - const head = node.children[0]; - const checkable = - typeof node.checked === 'boolean' && head && head.type === 'paragraph'; - const checkbox = '[' + (node.checked ? 'x' : ' ') + '] '; - const tracker = track(safeOptions); - if (checkable) { - tracker.move(checkbox); - } - let value = listItem(node, parent, context, { - ...safeOptions, - ...tracker.current() - }); - if (checkable) { - value = value.replace(/^(?:[*+-]|\d+\.)([\r\n]| {1,3})/, check); - } - return value - function check($0) { - return $0 + checkbox +function spaceThenNonSpace(effects, ok, nok) { + return factorySpace(effects, after, 'whitespace') + function after(code) { + return code === null ? nok(code) : ok(code) } } -function gfmFromMarkdown() { - return [ - gfmAutolinkLiteralFromMarkdown, - gfmFootnoteFromMarkdown(), - gfmStrikethroughFromMarkdown, - gfmTableFromMarkdown, - gfmTaskListItemFromMarkdown - ] -} -function gfmToMarkdown(options) { - return { - extensions: [ - gfmAutolinkLiteralToMarkdown, - gfmFootnoteToMarkdown(), - gfmStrikethroughToMarkdown, - gfmTableToMarkdown(options), - gfmTaskListItemToMarkdown - ] - } +function gfm(options) { + return combineExtensions([ + gfmAutolinkLiteral(), + gfmFootnote(), + gfmStrikethrough(options), + gfmTable(), + gfmTaskListItem() + ]) } -function remarkGfm(options = {}) { - const data = this.data(); - add('micromarkExtensions', gfm(options)); - add('fromMarkdownExtensions', gfmFromMarkdown()); - add('toMarkdownExtensions', gfmToMarkdown(options)); - function add(field, value) { - const list = ( - data[field] ? data[field] : (data[field] = []) - ); - list.push(value); - } +const emptyOptions$2 = {}; +function remarkGfm(options) { + const self = (this); + const settings = options || emptyOptions$2; + const data = self.data(); + const micromarkExtensions = + data.micromarkExtensions || (data.micromarkExtensions = []); + const fromMarkdownExtensions = + data.fromMarkdownExtensions || (data.fromMarkdownExtensions = []); + const toMarkdownExtensions = + data.toMarkdownExtensions || (data.toMarkdownExtensions = []); + micromarkExtensions.push(gfm(settings)); + fromMarkdownExtensions.push(gfmFromMarkdown()); + toMarkdownExtensions.push(gfmToMarkdown(settings)); } function location(file) { @@ -11822,14 +11912,78 @@ function location(file) { } } -function color$1(d) { +const convert$z = + ( + function (test) { + if (test === undefined || test === null) { + return ok$z + } + if (typeof test === 'string') { + return typeFactory$z(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$z(test) : propsFactory$z(test) + } + if (typeof test === 'function') { + return castFactory$z(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$z(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$z(tests[index]); + } + return castFactory$z(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$z(check) { + return castFactory$z(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$z(check) { + return castFactory$z(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$z(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$z() { + return true +} + +function color$A(d) { return '\u001B[33m' + d + '\u001B[39m' } -const CONTINUE = true; -const SKIP = 'skip'; -const EXIT = false; -const visitParents = +const CONTINUE$z = true; +const SKIP$z = 'skip'; +const EXIT$z = false; +const visitParents$z = ( function (tree, test, visitor, reverse) { if (typeof test === 'function' && typeof visitor !== 'function') { @@ -11837,7 +11991,7 @@ const visitParents = visitor = test; test = null; } - var is = convert(test); + var is = convert$z(test); var step = reverse ? -1 : 1; factory(tree, null, [])(); function factory(node, index, parents) { @@ -11853,7 +12007,7 @@ const visitParents = Object.defineProperty(visit, 'name', { value: 'node (' + - color$1(value.type + (name ? '<' + name + '>' : '')) + + color$A(value.type + (name ? '<' + name + '>' : '')) + ')' }); } @@ -11864,17 +12018,17 @@ const visitParents = var offset; var grandparents; if (!test || is(node, index, parents[parents.length - 1] || null)) { - result = toResult(visitor(node, parents)); - if (result[0] === EXIT) { + result = toResult$z(visitor(node, parents)); + if (result[0] === EXIT$z) { return result } } - if (node.children && result[0] !== SKIP) { + if (node.children && result[0] !== SKIP$z) { offset = (reverse ? node.children.length : -1) + step; grandparents = parents.concat(node); while (offset > -1 && offset < node.children.length) { subresult = factory(node.children[offset], offset, grandparents)(); - if (subresult[0] === EXIT) { + if (subresult[0] === EXIT$z) { return subresult } offset = @@ -11886,17 +12040,17 @@ const visitParents = } } ); -function toResult(value) { +function toResult$z(value) { if (Array.isArray(value)) { return value } if (typeof value === 'number') { - return [CONTINUE, value] + return [CONTINUE$z, value] } return [value] } -const visit = +const visit$z = ( function (tree, test, visitor, reverse) { if (typeof test === 'function' && typeof visitor !== 'function') { @@ -11904,7 +12058,7 @@ const visit = visitor = test; test = null; } - visitParents(tree, test, overload, reverse); + visitParents$z(tree, test, overload, reverse); function overload(node, parents) { var parent = parents[parents.length - 1]; return visitor( @@ -11942,7 +12096,7 @@ function messageControl(options) { const gaps = detectGaps(tree, file); const scope = {}; const globals = []; - visit(tree, options.test, visitor); + visit$z(tree, options.test, visitor); file.messages = file.messages.filter((m) => filter(m)); function visitor(node, position, parent) { const mark = options.marker(node); @@ -12077,7 +12231,7 @@ function detectGaps(tree, file) { const gaps = []; let offset = 0; let gap; - visit(tree, one); + visit$z(tree, one); if ( lastNode && lastNode.position && @@ -12672,615 +12826,1833 @@ var pluralize = {exports: {}}; var pluralizeExports = pluralize.exports; var plural = getDefaultExportFromCjs(pluralizeExports); +const convert$y = + ( + function (test) { + if (test === undefined || test === null) { + return ok$y + } + if (typeof test === 'string') { + return typeFactory$y(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$y(test) : propsFactory$y(test) + } + if (typeof test === 'function') { + return castFactory$y(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$y(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$y(tests[index]); + } + return castFactory$y(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$y(check) { + return castFactory$y(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$y(check) { + return castFactory$y(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$y(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$y() { + return true +} + +function color$z(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$y = true; +const EXIT$y = false; +const SKIP$y = 'skip'; +const visitParents$y = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$y(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$z(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$y(visitor(node, parents)); + if (result[0] === EXIT$y) { + return result + } + } + if (node.children && result[0] !== SKIP$y) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$y) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$y(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$y, value] + } + return [value] +} + +const visit$y = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$y(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); + +/** + * ## When should I use this? + * + * You can use this package to check that list items are not indented. + * + * ## API + * + * There are no options. + * + * ## Recommendation + * + * There is no specific handling of indented list items (or anything else) in + * markdown. + * While it is possible to use an indent to align ordered lists on their marker: + * + * ```markdown + * 1. One + * 10. Ten + * 100. Hundred + * ``` + * + * …such a style is uncommon and a bit hard to maintain: adding a 10th item + * means 9 other items have to change (more arduous, while unlikely, would be + * the 100th item). + * Hence, it’s recommended to not indent items and to turn this rule on. + * + * ## Fix + * + * [`remark-stringify`](https://github.com/remarkjs/remark/tree/main/packages/remark-stringify) + * formats all items without indent. + * + * @module list-item-bullet-indent + * @summary + * remark-lint rule to warn when list items are indented. + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @example + * {"name": "ok.md"} + * + * Paragraph. + * + * * List item + * * List item + * + * @example + * {"name": "not-ok.md", "label": "input"} + * + * Paragraph. + * + * ·* List item + * ·* List item + * + * @example + * {"name": "not-ok.md", "label": "output"} + * + * 3:2: Incorrect indentation before bullet: remove 1 space + * 4:2: Incorrect indentation before bullet: remove 1 space + */ +const remarkLintListItemBulletIndent = lintRule( + { + origin: 'remark-lint:list-item-bullet-indent', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-list-item-bullet-indent#readme' + }, + (tree, file) => { + visit$y(tree, 'list', (list, _, grandparent) => { + let index = -1; + while (++index < list.children.length) { + const item = list.children[index]; + if ( + grandparent && + grandparent.type === 'root' && + grandparent.position && + typeof grandparent.position.start.column === 'number' && + item.position && + typeof item.position.start.column === 'number' + ) { + const indent = + item.position.start.column - grandparent.position.start.column; + if (indent) { + file.message( + 'Incorrect indentation before bullet: remove ' + + indent + + ' ' + + plural('space', indent), + item.position.start + ); + } + } + } + }); + } +); +var remarkLintListItemBulletIndent$1 = remarkLintListItemBulletIndent; + +const convert$x = + ( + function (test) { + if (test === undefined || test === null) { + return ok$x + } + if (typeof test === 'string') { + return typeFactory$x(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$x(test) : propsFactory$x(test) + } + if (typeof test === 'function') { + return castFactory$x(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$x(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$x(tests[index]); + } + return castFactory$x(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$x(check) { + return castFactory$x(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$x(check) { + return castFactory$x(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$x(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$x() { + return true +} + +function color$y(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$x = true; +const EXIT$x = false; +const SKIP$x = 'skip'; +const visitParents$x = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$x(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$y(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$x(visitor(node, parents)); + if (result[0] === EXIT$x) { + return result + } + } + if (node.children && result[0] !== SKIP$x) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$x) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$x(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$x, value] + } + return [value] +} + +const visit$x = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$x(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); + +const pointStart = point$2('start'); +const pointEnd = point$2('end'); +function point$2(type) { + return point + function point(node) { + const point = (node && node.position && node.position[type]) || {}; + return { + line: point.line || null, + column: point.column || null, + offset: point.offset > -1 ? point.offset : null + } + } +} + +function generated(node) { + return ( + !node || + !node.position || + !node.position.start || + !node.position.start.line || + !node.position.start.column || + !node.position.end || + !node.position.end.line || + !node.position.end.column + ) +} + /** * ## When should I use this? * - * You can use this package to check that list items are not indented. + * You can use this package to check that the spacing between list item markers + * and content is inconsistent. * * ## API * - * There are no options. + * The following options (default: `'tab-size'`) are accepted: + * + * * `'space'` + * — prefer a single space + * * `'tab-size'` + * — prefer spaces the size of the next tab stop + * * `'mixed'` + * — prefer `'space'` for tight lists and `'tab-size'` for loose lists * * ## Recommendation * - * There is no specific handling of indented list items (or anything else) in - * markdown. - * While it is possible to use an indent to align ordered lists on their marker: + * First, some background. + * The number of spaces that occur after list markers (`*`, `-`, and `+` for + * unordered lists, or `.` and `)` for unordered lists) and before the content + * on the first line, defines how much indentation can be used for further + * lines. + * At least one space is required and up to 4 spaces are allowed (if there is no + * further content after the marker then it’s a blank line which is handled as + * if there was one space; if there are 5 or more spaces and then content, it’s + * also seen as one space and the rest is seen as indented code). * - * ```markdown - * 1. One - * 10. Ten - * 100. Hundred - * ``` + * There are two types of lists in markdown (other than ordered and unordered): + * tight and loose lists. + * Lists are tight by default but if there is a blank line between two list + * items or between two blocks inside an item, that turns the whole list into a + * loose list. + * When turning markdown into HTML, paragraphs in tight lists are not wrapped + * in `

` tags. * - * …such a style is uncommon and a bit hard to maintain: adding a 10th item - * means 9 other items have to change (more arduous, while unlikely, would be - * the 100th item). - * Hence, it’s recommended to not indent items and to turn this rule on. + * Historically, how indentation of lists works in markdown has been a mess, + * especially with how they interact with indented code. + * CommonMark made that a *lot* better, but there remain (documented but + * complex) edge cases and some behavior intuitive. + * Due to this, the default of this list is `'tab-size'`, which worked the best + * in most markdown parsers. + * Currently, the situation between markdown parsers is better, so choosing + * `'space'` (which seems to be the most common style used by authors) should + * be okay. + * + * ## Fix + * + * [`remark-stringify`](https://github.com/remarkjs/remark/tree/main/packages/remark-stringify) + * uses `'tab-size'` (named `'tab'` there) by default. + * [`listItemIndent: '1'` (for `'space'`) or `listItemIndent: 'mixed'`](https://github.com/remarkjs/remark/tree/main/packages/remark-stringify#optionslistitemindent) + * is supported. + * + * @module list-item-indent + * @summary + * remark-lint rule to warn when spacing between list item markers and + * content is inconsistent. + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT + * @example + * {"name": "ok.md"} + * + * *···List + * ····item. + * + * Paragraph. + * + * 11.·List + * ····item. + * + * Paragraph. + * + * *···List + * ····item. + * + * *···List + * ····item. + * + * @example + * {"name": "ok.md", "config": "mixed"} + * + * *·List item. + * + * Paragraph. + * + * 11.·List item + * + * Paragraph. + * + * *···List + * ····item. + * + * *···List + * ····item. + * + * @example + * {"name": "ok.md", "config": "space"} + * + * *·List item. + * + * Paragraph. + * + * 11.·List item + * + * Paragraph. + * + * *·List + * ··item. + * + * *·List + * ··item. + * + * @example + * {"name": "not-ok.md", "config": "space", "label": "input"} + * + * *···List + * ····item. * - * ## Fix + * @example + * {"name": "not-ok.md", "config": "space", "label": "output"} * - * [`remark-stringify`](https://github.com/remarkjs/remark/tree/main/packages/remark-stringify) - * formats all items without indent. + * 1:5: Incorrect list-item indent: remove 2 spaces * - * @module list-item-bullet-indent - * @summary - * remark-lint rule to warn when list items are indented. - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT * @example - * {"name": "ok.md"} + * {"name": "not-ok.md", "config": "tab-size", "label": "input"} * - * Paragraph. + * *·List + * ··item. * - * * List item - * * List item + * @example + * {"name": "not-ok.md", "config": "tab-size", "label": "output"} + * + * 1:3: Incorrect list-item indent: add 2 spaces * * @example - * {"name": "not-ok.md", "label": "input"} + * {"name": "not-ok.md", "config": "mixed", "label": "input"} * - * Paragraph. + * *···List item. * - * ·* List item - * ·* List item + * @example + * {"name": "not-ok.md", "config": "mixed", "label": "output"} + * + * 1:5: Incorrect list-item indent: remove 2 spaces * * @example - * {"name": "not-ok.md", "label": "output"} + * {"name": "not-ok.md", "config": "💩", "label": "output", "positionless": true} * - * 3:2: Incorrect indentation before bullet: remove 1 space - * 4:2: Incorrect indentation before bullet: remove 1 space + * 1:1: Incorrect list-item indent style `💩`: use either `'tab-size'`, `'space'`, or `'mixed'` */ -const remarkLintListItemBulletIndent = lintRule( +const remarkLintListItemIndent = lintRule( { - origin: 'remark-lint:list-item-bullet-indent', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-list-item-bullet-indent#readme' + origin: 'remark-lint:list-item-indent', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-list-item-indent#readme' }, - (tree, file) => { - visit$1(tree, 'list', (list, _, grandparent) => { + (tree, file, option = 'tab-size') => { + const value = String(file); + if (option !== 'tab-size' && option !== 'space' && option !== 'mixed') { + file.fail( + 'Incorrect list-item indent style `' + + option + + "`: use either `'tab-size'`, `'space'`, or `'mixed'`" + ); + } + visit$x(tree, 'list', (node) => { + if (generated(node)) return + const spread = node.spread; let index = -1; - while (++index < list.children.length) { - const item = list.children[index]; - if ( - grandparent && - grandparent.type === 'root' && - grandparent.position && - typeof grandparent.position.start.column === 'number' && - item.position && - typeof item.position.start.column === 'number' - ) { - const indent = - item.position.start.column - grandparent.position.start.column; - if (indent) { - file.message( - 'Incorrect indentation before bullet: remove ' + - indent + - ' ' + - plural('space', indent), - item.position.start - ); - } + while (++index < node.children.length) { + const item = node.children[index]; + const head = item.children[0]; + const final = pointStart(head); + const marker = value + .slice(pointStart(item).offset, final.offset) + .replace(/\[[x ]?]\s*$/i, ''); + const bulletSize = marker.replace(/\s+$/, '').length; + const style = + option === 'tab-size' || (option === 'mixed' && spread) + ? Math.ceil(bulletSize / 4) * 4 + : bulletSize + 1; + if (marker.length !== style) { + const diff = style - marker.length; + const abs = Math.abs(diff); + file.message( + 'Incorrect list-item indent: ' + + (diff > 0 ? 'add' : 'remove') + + ' ' + + abs + + ' ' + + plural('space', abs), + final + ); } } }); } ); -var remarkLintListItemBulletIndent$1 = remarkLintListItemBulletIndent; +var remarkLintListItemIndent$1 = remarkLintListItemIndent; -const pointStart = point$1('start'); -const pointEnd = point$1('end'); -function point$1(type) { - return point - function point(node) { - const point = (node && node.position && node.position[type]) || {}; - return { - line: point.line || null, - column: point.column || null, - offset: point.offset > -1 ? point.offset : null +const convert$w = + ( + function (test) { + if (test === undefined || test === null) { + return ok$w + } + if (typeof test === 'string') { + return typeFactory$w(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$w(test) : propsFactory$w(test) + } + if (typeof test === 'function') { + return castFactory$w(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$w(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$w(tests[index]); + } + return castFactory$w(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$w(check) { + return castFactory$w(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false } + return true + } +} +function typeFactory$w(check) { + return castFactory$w(type) + function type(node) { + return node && node.type === check } } +function castFactory$w(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$w() { + return true +} -function generated(node) { - return ( - !node || - !node.position || - !node.position.start || - !node.position.start.line || - !node.position.start.column || - !node.position.end || - !node.position.end.line || - !node.position.end.column - ) +function color$x(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$w = true; +const EXIT$w = false; +const SKIP$w = 'skip'; +const visitParents$w = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$w(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$x(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$w(visitor(node, parents)); + if (result[0] === EXIT$w) { + return result + } + } + if (node.children && result[0] !== SKIP$w) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$w) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$w(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$w, value] + } + return [value] } +const visit$w = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$w(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); + /** * ## When should I use this? * - * You can use this package to check that the spacing between list item markers - * and content is inconsistent. + * You can use this package to check that lines in block quotes start with `>`. * * ## API * - * The following options (default: `'tab-size'`) are accepted: - * - * * `'space'` - * — prefer a single space - * * `'tab-size'` - * — prefer spaces the size of the next tab stop - * * `'mixed'` - * — prefer `'space'` for tight lists and `'tab-size'` for loose lists - * - * ## Recommendation - * - * First, some background. - * The number of spaces that occur after list markers (`*`, `-`, and `+` for - * unordered lists, or `.` and `)` for unordered lists) and before the content - * on the first line, defines how much indentation can be used for further - * lines. - * At least one space is required and up to 4 spaces are allowed (if there is no - * further content after the marker then it’s a blank line which is handled as - * if there was one space; if there are 5 or more spaces and then content, it’s - * also seen as one space and the rest is seen as indented code). + * There are no options. * - * There are two types of lists in markdown (other than ordered and unordered): - * tight and loose lists. - * Lists are tight by default but if there is a blank line between two list - * items or between two blocks inside an item, that turns the whole list into a - * loose list. - * When turning markdown into HTML, paragraphs in tight lists are not wrapped - * in `

` tags. + * ## Recommendation * - * Historically, how indentation of lists works in markdown has been a mess, - * especially with how they interact with indented code. - * CommonMark made that a *lot* better, but there remain (documented but - * complex) edge cases and some behavior intuitive. - * Due to this, the default of this list is `'tab-size'`, which worked the best - * in most markdown parsers. - * Currently, the situation between markdown parsers is better, so choosing - * `'space'` (which seems to be the most common style used by authors) should - * be okay. + * Rules around “lazy” lines are not straightforward and visually confusing, + * so it’s recommended to start each line with a `>`. * * ## Fix * * [`remark-stringify`](https://github.com/remarkjs/remark/tree/main/packages/remark-stringify) - * uses `'tab-size'` (named `'tab'` there) by default. - * [`listItemIndent: '1'` (for `'space'`) or `listItemIndent: 'mixed'`](https://github.com/remarkjs/remark/tree/main/packages/remark-stringify#optionslistitemindent) - * is supported. + * adds `>` markers to every line in a block quote. * - * @module list-item-indent + * @module no-blockquote-without-marker * @summary - * remark-lint rule to warn when spacing between list item markers and - * content is inconsistent. + * remark-lint rule to warn when lines in block quotes start without `>`. * @author Titus Wormer * @copyright 2015 Titus Wormer * @license MIT * @example * {"name": "ok.md"} * - * *···List - * ····item. - * - * Paragraph. - * - * 11.·List - * ····item. - * - * Paragraph. - * - * *···List - * ····item. - * - * *···List - * ····item. + * > Foo… + * > …bar… + * > …baz. * * @example - * {"name": "ok.md", "config": "mixed"} - * - * *·List item. - * - * Paragraph. - * - * 11.·List item - * - * Paragraph. - * - * *···List - * ····item. + * {"name": "ok-tabs.md"} * - * *···List - * ····item. + * >»Foo… + * >»…bar… + * >»…baz. * * @example - * {"name": "ok.md", "config": "space"} - * - * *·List item. + * {"name": "not-ok.md", "label": "input"} * - * Paragraph. + * > Foo… + * …bar… + * > …baz. * - * 11.·List item + * @example + * {"name": "not-ok.md", "label": "output"} * - * Paragraph. + * 2:1: Missing marker in block quote * - * *·List - * ··item. + * @example + * {"name": "not-ok-tabs.md", "label": "input"} * - * *·List - * ··item. + * >»Foo… + * »…bar… + * …baz. * * @example - * {"name": "not-ok.md", "config": "space", "label": "input"} + * {"name": "not-ok-tabs.md", "label": "output"} + * + * 2:1: Missing marker in block quote + * 3:1: Missing marker in block quote + */ +const remarkLintNoBlockquoteWithoutMarker = lintRule( + { + origin: 'remark-lint:no-blockquote-without-marker', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-blockquote-without-marker#readme' + }, + (tree, file) => { + const value = String(file); + const loc = location(file); + visit$w(tree, 'blockquote', (node) => { + let index = -1; + while (++index < node.children.length) { + const child = node.children[index]; + if (child.type === 'paragraph' && !generated(child)) { + const end = pointEnd(child).line; + const column = pointStart(child).column; + let line = pointStart(child).line; + while (++line <= end) { + const offset = loc.toOffset({line, column}); + if (/>[\t ]+$/.test(value.slice(offset - 5, offset))) { + continue + } + file.message('Missing marker in block quote', { + line, + column: column - 2 + }); + } + } + } + }); + } +); +var remarkLintNoBlockquoteWithoutMarker$1 = remarkLintNoBlockquoteWithoutMarker; + +const convert$v = + ( + function (test) { + if (test === undefined || test === null) { + return ok$v + } + if (typeof test === 'string') { + return typeFactory$v(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$v(test) : propsFactory$v(test) + } + if (typeof test === 'function') { + return castFactory$v(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$v(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$v(tests[index]); + } + return castFactory$v(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$v(check) { + return castFactory$v(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$v(check) { + return castFactory$v(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$v(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$v() { + return true +} + +function color$w(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$v = true; +const EXIT$v = false; +const SKIP$v = 'skip'; +const visitParents$v = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$v(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$w(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$v(visitor(node, parents)); + if (result[0] === EXIT$v) { + return result + } + } + if (node.children && result[0] !== SKIP$v) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$v) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$v(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$v, value] + } + return [value] +} + +const visit$v = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$v(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); + +const emptyOptions$1 = {}; +function toString$1(value, options) { + const settings = options || emptyOptions$1; + const includeImageAlt = + typeof settings.includeImageAlt === 'boolean' + ? settings.includeImageAlt + : true; + const includeHtml = + typeof settings.includeHtml === 'boolean' ? settings.includeHtml : true; + return one$1(value, includeImageAlt, includeHtml) +} +function one$1(value, includeImageAlt, includeHtml) { + if (node$1(value)) { + if ('value' in value) { + return value.type === 'html' && !includeHtml ? '' : value.value + } + if (includeImageAlt && 'alt' in value && value.alt) { + return value.alt + } + if ('children' in value) { + return all$1(value.children, includeImageAlt, includeHtml) + } + } + if (Array.isArray(value)) { + return all$1(value, includeImageAlt, includeHtml) + } + return '' +} +function all$1(values, includeImageAlt, includeHtml) { + const result = []; + let index = -1; + while (++index < values.length) { + result[index] = one$1(values[index], includeImageAlt, includeHtml); + } + return result.join('') +} +function node$1(value) { + return Boolean(value && typeof value === 'object') +} + +/** + * ## When should I use this? * - * *···List - * ····item. + * You can use this package to check that autolink literal URLs are not used. * - * @example - * {"name": "not-ok.md", "config": "space", "label": "output"} + * ## API * - * 1:5: Incorrect list-item indent: remove 2 spaces + * There are no options. * - * @example - * {"name": "not-ok.md", "config": "tab-size", "label": "input"} + * ## Recommendation * - * *·List - * ··item. + * Autolink literal URLs (just a URL) are a feature enabled by GFM. + * They don’t work everywhere. + * Due to this, it’s recommended to instead use normal autolinks + * (``) or links (`[text](url)`). * - * @example - * {"name": "not-ok.md", "config": "tab-size", "label": "output"} + * ## Fix * - * 1:3: Incorrect list-item indent: add 2 spaces + * [`remark-stringify`](https://github.com/remarkjs/remark/tree/main/packages/remark-stringify) + * never creates autolink literals and always uses normal autolinks (``). * + * @module no-literal-urls + * @summary + * remark-lint rule to warn for autolink literals. + * @author Titus Wormer + * @copyright 2015 Titus Wormer + * @license MIT * @example - * {"name": "not-ok.md", "config": "mixed", "label": "input"} + * {"name": "ok.md"} * - * *···List item. + * * * @example - * {"name": "not-ok.md", "config": "mixed", "label": "output"} + * {"name": "not-ok.md", "label": "input", "gfm": true} * - * 1:5: Incorrect list-item indent: remove 2 spaces + * http://foo.bar/baz * * @example - * {"name": "not-ok.md", "config": "💩", "label": "output", "positionless": true} + * {"name": "not-ok.md", "label": "output", "gfm": true} * - * 1:1: Incorrect list-item indent style `💩`: use either `'tab-size'`, `'space'`, or `'mixed'` + * 1:1-1:19: Don’t use literal URLs without angle brackets */ -const remarkLintListItemIndent = lintRule( +const remarkLintNoLiteralUrls = lintRule( { - origin: 'remark-lint:list-item-indent', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-list-item-indent#readme' + origin: 'remark-lint:no-literal-urls', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-literal-urls#readme' }, - (tree, file, option = 'tab-size') => { - const value = String(file); - if (option !== 'tab-size' && option !== 'space' && option !== 'mixed') { - file.fail( - 'Incorrect list-item indent style `' + - option + - "`: use either `'tab-size'`, `'space'`, or `'mixed'`" - ); - } - visit$1(tree, 'list', (node) => { - if (generated(node)) return - const spread = node.spread; - let index = -1; - while (++index < node.children.length) { - const item = node.children[index]; - const head = item.children[0]; - const final = pointStart(head); - const marker = value - .slice(pointStart(item).offset, final.offset) - .replace(/\[[x ]?]\s*$/i, ''); - const bulletSize = marker.replace(/\s+$/, '').length; - const style = - option === 'tab-size' || (option === 'mixed' && spread) - ? Math.ceil(bulletSize / 4) * 4 - : bulletSize + 1; - if (marker.length !== style) { - const diff = style - marker.length; - const abs = Math.abs(diff); - file.message( - 'Incorrect list-item indent: ' + - (diff > 0 ? 'add' : 'remove') + - ' ' + - abs + - ' ' + - plural('space', abs), - final - ); - } + (tree, file) => { + visit$v(tree, 'link', (node) => { + const value = toString$1(node); + if ( + !generated(node) && + pointStart(node).column === pointStart(node.children[0]).column && + pointEnd(node).column === + pointEnd(node.children[node.children.length - 1]).column && + (node.url === 'mailto:' + value || node.url === value) + ) { + file.message('Don’t use literal URLs without angle brackets', node); } }); } ); -var remarkLintListItemIndent$1 = remarkLintListItemIndent; +var remarkLintNoLiteralUrls$1 = remarkLintNoLiteralUrls; + +const convert$u = + ( + function (test) { + if (test === undefined || test === null) { + return ok$u + } + if (typeof test === 'string') { + return typeFactory$u(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$u(test) : propsFactory$u(test) + } + if (typeof test === 'function') { + return castFactory$u(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$u(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$u(tests[index]); + } + return castFactory$u(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$u(check) { + return castFactory$u(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$u(check) { + return castFactory$u(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$u(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$u() { + return true +} + +function color$v(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$u = true; +const EXIT$u = false; +const SKIP$u = 'skip'; +const visitParents$u = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$u(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$v(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$u(visitor(node, parents)); + if (result[0] === EXIT$u) { + return result + } + } + if (node.children && result[0] !== SKIP$u) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$u) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$u(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$u, value] + } + return [value] +} + +const visit$u = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$u(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); /** * ## When should I use this? * - * You can use this package to check that lines in block quotes start with `>`. + * You can use this package to check that ordered list markers are consistent. * * ## API * - * There are no options. + * The following options (default: `'consistent'`) are accepted: + * + * * `'.'` + * — prefer dots + * * `')'` + * — prefer parens + * * `'consistent'` + * — detect the first used style and warn when further markers differ * * ## Recommendation * - * Rules around “lazy” lines are not straightforward and visually confusing, - * so it’s recommended to start each line with a `>`. + * Parens for list markers were not supported in markdown before CommonMark. + * While they should work in most places now, not all markdown parsers follow + * CommonMark. + * Due to this, it’s recommended to prefer dots. * * ## Fix * * [`remark-stringify`](https://github.com/remarkjs/remark/tree/main/packages/remark-stringify) - * adds `>` markers to every line in a block quote. + * formats ordered lists with dots by default. + * Pass + * [`bulletOrdered: ')'`](https://github.com/remarkjs/remark/tree/main/packages/remark-stringify#optionsbulletordered) + * to always use parens. * - * @module no-blockquote-without-marker + * @module ordered-list-marker-style * @summary - * remark-lint rule to warn when lines in block quotes start without `>`. + * remark-lint rule to warn when ordered list markers are inconsistent. * @author Titus Wormer * @copyright 2015 Titus Wormer * @license MIT * @example * {"name": "ok.md"} * - * > Foo… - * > …bar… - * > …baz. + * 1. Foo + * + * + * 1. Bar + * + * Unordered lists are not affected by this rule. + * + * * Foo * * @example - * {"name": "ok-tabs.md"} + * {"name": "ok.md", "config": "."} * - * >»Foo… - * >»…bar… - * >»…baz. + * 1. Foo + * + * 2. Bar * * @example - * {"name": "not-ok.md", "label": "input"} + * {"name": "ok.md", "config": ")"} * - * > Foo… - * …bar… - * > …baz. + * 1) Foo + * + * 2) Bar * * @example - * {"name": "not-ok.md", "label": "output"} + * {"name": "not-ok.md", "label": "input"} * - * 2:1: Missing marker in block quote + * 1. Foo + * + * 2) Bar * * @example - * {"name": "not-ok-tabs.md", "label": "input"} + * {"name": "not-ok.md", "label": "output"} * - * >»Foo… - * »…bar… - * …baz. + * 3:1-3:8: Marker style should be `.` * * @example - * {"name": "not-ok-tabs.md", "label": "output"} + * {"name": "not-ok.md", "label": "output", "config": "💩", "positionless": true} * - * 2:1: Missing marker in block quote - * 3:1: Missing marker in block quote + * 1:1: Incorrect ordered list item marker style `💩`: use either `'.'` or `')'` */ -const remarkLintNoBlockquoteWithoutMarker = lintRule( +const remarkLintOrderedListMarkerStyle = lintRule( { - origin: 'remark-lint:no-blockquote-without-marker', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-blockquote-without-marker#readme' + origin: 'remark-lint:ordered-list-marker-style', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-ordered-list-marker-style#readme' }, - (tree, file) => { + (tree, file, option = 'consistent') => { const value = String(file); - const loc = location(file); - visit$1(tree, 'blockquote', (node) => { + if (option !== 'consistent' && option !== '.' && option !== ')') { + file.fail( + 'Incorrect ordered list item marker style `' + + option + + "`: use either `'.'` or `')'`" + ); + } + visit$u(tree, 'list', (node) => { let index = -1; + if (!node.ordered) return while (++index < node.children.length) { const child = node.children[index]; - if (child.type === 'paragraph' && !generated(child)) { - const end = pointEnd(child).line; - const column = pointStart(child).column; - let line = pointStart(child).line; - while (++line <= end) { - const offset = loc.toOffset({line, column}); - if (/>[\t ]+$/.test(value.slice(offset - 5, offset))) { - continue - } - file.message('Missing marker in block quote', { - line, - column: column - 2 - }); + if (!generated(child)) { + const marker = ( + value + .slice( + pointStart(child).offset, + pointStart(child.children[0]).offset + ) + .replace(/\s|\d/g, '') + .replace(/\[[x ]?]\s*$/i, '') + ); + if (option === 'consistent') { + option = marker; + } else if (marker !== option) { + file.message('Marker style should be `' + option + '`', child); } } } }); } ); -var remarkLintNoBlockquoteWithoutMarker$1 = remarkLintNoBlockquoteWithoutMarker; +var remarkLintOrderedListMarkerStyle$1 = remarkLintOrderedListMarkerStyle; -/** - * ## When should I use this? - * - * You can use this package to check that autolink literal URLs are not used. - * - * ## API - * - * There are no options. - * - * ## Recommendation - * - * Autolink literal URLs (just a URL) are a feature enabled by GFM. - * They don’t work everywhere. - * Due to this, it’s recommended to instead use normal autolinks - * (``) or links (`[text](url)`). - * - * ## Fix - * - * [`remark-stringify`](https://github.com/remarkjs/remark/tree/main/packages/remark-stringify) - * never creates autolink literals and always uses normal autolinks (``). - * - * @module no-literal-urls - * @summary - * remark-lint rule to warn for autolink literals. - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @example - * {"name": "ok.md"} - * - * - * - * @example - * {"name": "not-ok.md", "label": "input", "gfm": true} - * - * http://foo.bar/baz - * - * @example - * {"name": "not-ok.md", "label": "output", "gfm": true} - * - * 1:1-1:19: Don’t use literal URLs without angle brackets - */ -const remarkLintNoLiteralUrls = lintRule( - { - origin: 'remark-lint:no-literal-urls', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-literal-urls#readme' - }, - (tree, file) => { - visit$1(tree, 'link', (node) => { - const value = toString(node); - if ( - !generated(node) && - pointStart(node).column === pointStart(node.children[0]).column && - pointEnd(node).column === - pointEnd(node.children[node.children.length - 1]).column && - (node.url === 'mailto:' + value || node.url === value) - ) { - file.message('Don’t use literal URLs without angle brackets', node); +const convert$t = + ( + function (test) { + if (test === undefined || test === null) { + return ok$t + } + if (typeof test === 'string') { + return typeFactory$t(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$t(test) : propsFactory$t(test) + } + if (typeof test === 'function') { + return castFactory$t(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$t(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$t(tests[index]); + } + return castFactory$t(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$t(check) { + return castFactory$t(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$t(check) { + return castFactory$t(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$t(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$t() { + return true +} + +function color$u(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$t = true; +const EXIT$t = false; +const SKIP$t = 'skip'; +const visitParents$t = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$t(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$u(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$t(visitor(node, parents)); + if (result[0] === EXIT$t) { + return result + } + } + if (node.children && result[0] !== SKIP$t) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$t) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } } - }); + } + ); +function toResult$t(value) { + if (Array.isArray(value)) { + return value } -); -var remarkLintNoLiteralUrls$1 = remarkLintNoLiteralUrls; + if (typeof value === 'number') { + return [CONTINUE$t, value] + } + return [value] +} + +const visit$t = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$t(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); /** * ## When should I use this? * - * You can use this package to check that ordered list markers are consistent. + * You can use this package to check that hard breaks use two spaces and + * not more. * * ## API * - * The following options (default: `'consistent'`) are accepted: - * - * * `'.'` - * — prefer dots - * * `')'` - * — prefer parens - * * `'consistent'` - * — detect the first used style and warn when further markers differ + * There are no options. * * ## Recommendation * - * Parens for list markers were not supported in markdown before CommonMark. - * While they should work in most places now, not all markdown parsers follow - * CommonMark. - * Due to this, it’s recommended to prefer dots. - * - * ## Fix - * - * [`remark-stringify`](https://github.com/remarkjs/remark/tree/main/packages/remark-stringify) - * formats ordered lists with dots by default. - * Pass - * [`bulletOrdered: ')'`](https://github.com/remarkjs/remark/tree/main/packages/remark-stringify#optionsbulletordered) - * to always use parens. + * Less than two spaces do not create a hard breaks and more than two spaces + * have no effect. + * Due to this, it’s recommended to turn this rule on. * - * @module ordered-list-marker-style + * @module hard-break-spaces * @summary - * remark-lint rule to warn when ordered list markers are inconsistent. + * remark-lint rule to warn when more spaces are used than needed + * for hard breaks. * @author Titus Wormer * @copyright 2015 Titus Wormer * @license MIT * @example * {"name": "ok.md"} * - * 1. Foo - * - * - * 1. Bar - * - * Unordered lists are not affected by this rule. - * - * * Foo - * - * @example - * {"name": "ok.md", "config": "."} - * - * 1. Foo - * - * 2. Bar - * - * @example - * {"name": "ok.md", "config": ")"} - * - * 1) Foo - * - * 2) Bar + * Lorem ipsum·· + * dolor sit amet * * @example * {"name": "not-ok.md", "label": "input"} * - * 1. Foo - * - * 2) Bar + * Lorem ipsum··· + * dolor sit amet. * * @example * {"name": "not-ok.md", "label": "output"} * - * 3:1-3:8: Marker style should be `.` - * - * @example - * {"name": "not-ok.md", "label": "output", "config": "💩", "positionless": true} - * - * 1:1: Incorrect ordered list item marker style `💩`: use either `'.'` or `')'` + * 1:12-2:1: Use two spaces for hard line breaks */ -const remarkLintOrderedListMarkerStyle = lintRule( +const remarkLintHardBreakSpaces = lintRule( { - origin: 'remark-lint:ordered-list-marker-style', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-ordered-list-marker-style#readme' + origin: 'remark-lint:hard-break-spaces', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-hard-break-spaces#readme' }, - (tree, file, option = 'consistent') => { + (tree, file) => { const value = String(file); - if (option !== 'consistent' && option !== '.' && option !== ')') { - file.fail( - 'Incorrect ordered list item marker style `' + - option + - "`: use either `'.'` or `')'`" - ); + visit$t(tree, 'break', (node) => { + if (!generated(node)) { + const slice = value + .slice(pointStart(node).offset, pointEnd(node).offset) + .split('\n', 1)[0] + .replace(/\r$/, ''); + if (slice.length > 2) { + file.message('Use two spaces for hard line breaks', node); + } + } + }); + } +); +var remarkLintHardBreakSpaces$1 = remarkLintHardBreakSpaces; + +function stringifyPosition$1(value) { + if (!value || typeof value !== 'object') { + return '' + } + if ('position' in value || 'type' in value) { + return position$1(value.position) + } + if ('start' in value || 'end' in value) { + return position$1(value) + } + if ('line' in value || 'column' in value) { + return point$1(value) + } + return '' +} +function point$1(point) { + return index$1(point && point.line) + ':' + index$1(point && point.column) +} +function position$1(pos) { + return point$1(pos && pos.start) + '-' + point$1(pos && pos.end) +} +function index$1(value) { + return value && typeof value === 'number' ? value : 1 +} + +const convert$s = + ( + function (test) { + if (test === undefined || test === null) { + return ok$s + } + if (typeof test === 'string') { + return typeFactory$s(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$s(test) : propsFactory$s(test) + } + if (typeof test === 'function') { + return castFactory$s(test) + } + throw new Error('Expected function, string, or object as test') } - visit$1(tree, 'list', (node) => { - let index = -1; - if (!node.ordered) return - while (++index < node.children.length) { - const child = node.children[index]; - if (!generated(child)) { - const marker = ( - value - .slice( - pointStart(child).offset, - pointStart(child.children[0]).offset - ) - .replace(/\s|\d/g, '') - .replace(/\[[x ]?]\s*$/i, '') - ); - if (option === 'consistent') { - option = marker; - } else if (marker !== option) { - file.message('Marker style should be `' + option + '`', child); + ); +function anyFactory$s(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$s(tests[index]); + } + return castFactory$s(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$s(check) { + return castFactory$s(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$s(check) { + return castFactory$s(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$s(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$s() { + return true +} + +function color$t(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$s = true; +const EXIT$s = false; +const SKIP$s = 'skip'; +const visitParents$s = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$s(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$t(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$s(visitor(node, parents)); + if (result[0] === EXIT$s) { + return result + } + } + if (node.children && result[0] !== SKIP$s) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$s) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } } + return result } } - }); + } + ); +function toResult$s(value) { + if (Array.isArray(value)) { + return value } -); -var remarkLintOrderedListMarkerStyle$1 = remarkLintOrderedListMarkerStyle; + if (typeof value === 'number') { + return [CONTINUE$s, value] + } + return [value] +} + +const visit$s = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$s(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); /** * ## When should I use this? * - * You can use this package to check that hard breaks use two spaces and - * not more. + * You can use this package to check that identifiers are defined once. * * ## API * @@ -13288,60 +14660,251 @@ var remarkLintOrderedListMarkerStyle$1 = remarkLintOrderedListMarkerStyle; * * ## Recommendation * - * Less than two spaces do not create a hard breaks and more than two spaces - * have no effect. - * Due to this, it’s recommended to turn this rule on. + * It’s a mistake when the same identifier is defined multiple times. * - * @module hard-break-spaces + * @module no-duplicate-definitions * @summary - * remark-lint rule to warn when more spaces are used than needed - * for hard breaks. + * remark-lint rule to warn when identifiers are defined multiple times. * @author Titus Wormer * @copyright 2015 Titus Wormer * @license MIT * @example * {"name": "ok.md"} * - * Lorem ipsum·· - * dolor sit amet + * [foo]: bar + * [baz]: qux * * @example * {"name": "not-ok.md", "label": "input"} * - * Lorem ipsum··· - * dolor sit amet. + * [foo]: bar + * [foo]: qux * * @example * {"name": "not-ok.md", "label": "output"} * - * 1:12-2:1: Use two spaces for hard line breaks + * 2:1-2:11: Do not use definitions with the same identifier (1:1) */ -const remarkLintHardBreakSpaces = lintRule( +const remarkLintNoDuplicateDefinitions = lintRule( { - origin: 'remark-lint:hard-break-spaces', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-hard-break-spaces#readme' + origin: 'remark-lint:no-duplicate-definitions', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-duplicate-definitions#readme' }, (tree, file) => { - const value = String(file); - visit$1(tree, 'break', (node) => { - if (!generated(node)) { - const slice = value - .slice(pointStart(node).offset, pointEnd(node).offset) - .split('\n', 1)[0] - .replace(/\r$/, ''); - if (slice.length > 2) { - file.message('Use two spaces for hard line breaks', node); + const map = Object.create(null); + visit$s(tree, (node) => { + if ( + (node.type === 'definition' || node.type === 'footnoteDefinition') && + !generated(node) + ) { + const identifier = node.identifier; + const duplicate = map[identifier]; + if (duplicate) { + file.message( + 'Do not use definitions with the same identifier (' + + duplicate + + ')', + node + ); } + map[identifier] = stringifyPosition$1(pointStart(node)); } }); } ); -var remarkLintHardBreakSpaces$1 = remarkLintHardBreakSpaces; +var remarkLintNoDuplicateDefinitions$1 = remarkLintNoDuplicateDefinitions; + +const convert$r = + ( + function (test) { + if (test === undefined || test === null) { + return ok$r + } + if (typeof test === 'string') { + return typeFactory$r(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$r(test) : propsFactory$r(test) + } + if (typeof test === 'function') { + return castFactory$r(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$r(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$r(tests[index]); + } + return castFactory$r(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$r(check) { + return castFactory$r(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$r(check) { + return castFactory$r(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$r(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$r() { + return true +} + +function color$s(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$r = true; +const EXIT$r = false; +const SKIP$r = 'skip'; +const visitParents$r = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$r(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$s(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$r(visitor(node, parents)); + if (result[0] === EXIT$r) { + return result + } + } + if (node.children && result[0] !== SKIP$r) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$r) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$r(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$r, value] + } + return [value] +} + +const visit$r = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$r(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); + +function headingStyle(node, relative) { + const last = node.children[node.children.length - 1]; + const depth = node.depth; + const pos = node.position && node.position.end; + const final = last && last.position && last.position.end; + if (!pos) { + return null + } + if (!last) { + if (pos.column - 1 <= depth * 2) { + return consolidate(depth, relative) + } + return 'atx-closed' + } + if (final && final.line + 1 === pos.line) { + return 'setext' + } + if (final && final.column + depth < pos.column) { + return 'atx-closed' + } + return consolidate(depth, relative) +} +function consolidate(depth, relative) { + return depth < 3 + ? 'atx' + : relative === 'atx' || relative === 'setext' + ? relative + : null +} /** * ## When should I use this? * - * You can use this package to check that identifiers are defined once. + * You can use this package to check that there is on space between `#` + * characters and the content in headings. * * ## API * @@ -13349,257 +14912,727 @@ var remarkLintHardBreakSpaces$1 = remarkLintHardBreakSpaces; * * ## Recommendation * - * It’s a mistake when the same identifier is defined multiple times. + * One space is required and more than one space has no effect. + * Due to this, it’s recommended to turn this rule on. * - * @module no-duplicate-definitions + * ## Fix + * + * [`remark-stringify`](https://github.com/remarkjs/remark/tree/main/packages/remark-stringify) + * formats headings with exactly one space. + * + * @module no-heading-content-indent * @summary - * remark-lint rule to warn when identifiers are defined multiple times. + * remark-lint rule to warn when there are too many spaces between + * hashes and content in headings. * @author Titus Wormer * @copyright 2015 Titus Wormer * @license MIT * @example * {"name": "ok.md"} * - * [foo]: bar - * [baz]: qux + * #·Foo + * + * ## Bar·## + * + * ##·Baz + * + * Setext headings are not affected. + * + * Baz + * === * * @example * {"name": "not-ok.md", "label": "input"} * - * [foo]: bar - * [foo]: qux + * #··Foo + * + * ## Bar··## + * + * ##··Baz * * @example * {"name": "not-ok.md", "label": "output"} * - * 2:1-2:11: Do not use definitions with the same identifier (1:1) + * 1:4: Remove 1 space before this heading’s content + * 3:7: Remove 1 space after this heading’s content + * 5:7: Remove 1 space before this heading’s content + * + * @example + * {"name": "empty-heading.md"} + * + * #·· */ -const remarkLintNoDuplicateDefinitions = lintRule( +const remarkLintNoHeadingContentIndent = lintRule( { - origin: 'remark-lint:no-duplicate-definitions', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-duplicate-definitions#readme' + origin: 'remark-lint:no-heading-content-indent', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-heading-content-indent#readme' }, (tree, file) => { - const map = Object.create(null); - visit$1(tree, (node) => { - if ( - (node.type === 'definition' || node.type === 'footnoteDefinition') && - !generated(node) - ) { - const identifier = node.identifier; - const duplicate = map[identifier]; - if (duplicate) { + visit$r(tree, 'heading', (node) => { + if (generated(node)) { + return + } + const type = headingStyle(node, 'atx'); + if (type === 'atx' || type === 'atx-closed') { + const head = pointStart(node.children[0]).column; + if (!head) { + return + } + const diff = head - pointStart(node).column - 1 - node.depth; + if (diff) { file.message( - 'Do not use definitions with the same identifier (' + - duplicate + - ')', - node + 'Remove ' + + Math.abs(diff) + + ' ' + + plural('space', Math.abs(diff)) + + ' before this heading’s content', + pointStart(node.children[0]) + ); + } + } + if (type === 'atx-closed') { + const final = pointEnd(node.children[node.children.length - 1]); + const diff = pointEnd(node).column - final.column - 1 - node.depth; + if (diff) { + file.message( + 'Remove ' + + diff + + ' ' + + plural('space', diff) + + ' after this heading’s content', + final ); } - map[identifier] = stringifyPosition$1(pointStart(node)); } }); } ); -var remarkLintNoDuplicateDefinitions$1 = remarkLintNoDuplicateDefinitions; +var remarkLintNoHeadingContentIndent$1 = remarkLintNoHeadingContentIndent; -function headingStyle(node, relative) { - const last = node.children[node.children.length - 1]; - const depth = node.depth; - const pos = node.position && node.position.end; - const final = last && last.position && last.position.end; - if (!pos) { - return null +const convert$q = + ( + function (test) { + if (test === undefined || test === null) { + return ok$q + } + if (typeof test === 'string') { + return typeFactory$q(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$q(test) : propsFactory$q(test) + } + if (typeof test === 'function') { + return castFactory$q(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$q(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$q(tests[index]); } - if (!last) { - if (pos.column - 1 <= depth * 2) { - return consolidate(depth, relative) + return castFactory$q(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$q(check) { + return castFactory$q(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$q(check) { + return castFactory$q(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$q(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$q() { + return true +} + +function color$r(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$q = true; +const EXIT$q = false; +const SKIP$q = 'skip'; +const visitParents$q = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$q(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$r(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$q(visitor(node, parents)); + if (result[0] === EXIT$q) { + return result + } + } + if (node.children && result[0] !== SKIP$q) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$q) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$q(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$q, value] + } + return [value] +} + +const visit$q = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$q(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); + +const emptyOptions = {}; +function toString(value, options) { + const settings = options || emptyOptions; + const includeImageAlt = + typeof settings.includeImageAlt === 'boolean' + ? settings.includeImageAlt + : true; + const includeHtml = + typeof settings.includeHtml === 'boolean' ? settings.includeHtml : true; + return one(value, includeImageAlt, includeHtml) +} +function one(value, includeImageAlt, includeHtml) { + if (node(value)) { + if ('value' in value) { + return value.type === 'html' && !includeHtml ? '' : value.value + } + if (includeImageAlt && 'alt' in value && value.alt) { + return value.alt + } + if ('children' in value) { + return all(value.children, includeImageAlt, includeHtml) } - return 'atx-closed' } - if (final && final.line + 1 === pos.line) { - return 'setext' + if (Array.isArray(value)) { + return all(value, includeImageAlt, includeHtml) } - if (final && final.column + depth < pos.column) { - return 'atx-closed' + return '' +} +function all(values, includeImageAlt, includeHtml) { + const result = []; + let index = -1; + while (++index < values.length) { + result[index] = one(values[index], includeImageAlt, includeHtml); } - return consolidate(depth, relative) + return result.join('') } -function consolidate(depth, relative) { - return depth < 3 - ? 'atx' - : relative === 'atx' || relative === 'setext' - ? relative - : null +function node(value) { + return Boolean(value && typeof value === 'object') } /** * ## When should I use this? * - * You can use this package to check that there is on space between `#` - * characters and the content in headings. + * You can use this package to check that inline constructs (links) are + * not padded. + * Historically, it was possible to pad emphasis, strong, and strikethrough + * too, but this was removed in CommonMark, making this rule much less useful. * * ## API * * There are no options. * - * ## Recommendation - * - * One space is required and more than one space has no effect. - * Due to this, it’s recommended to turn this rule on. - * - * ## Fix - * - * [`remark-stringify`](https://github.com/remarkjs/remark/tree/main/packages/remark-stringify) - * formats headings with exactly one space. - * - * @module no-heading-content-indent + * @module no-inline-padding * @summary - * remark-lint rule to warn when there are too many spaces between - * hashes and content in headings. + * remark-lint rule to warn when inline constructs are padded. * @author Titus Wormer * @copyright 2015 Titus Wormer * @license MIT * @example * {"name": "ok.md"} * - * #·Foo - * - * ## Bar·## - * - * ##·Baz - * - * Setext headings are not affected. - * - * Baz - * === + * Alpha [bravo](http://echo.fox/trot) * * @example * {"name": "not-ok.md", "label": "input"} * - * #··Foo - * - * ## Bar··## - * - * ##··Baz + * Alpha [ bravo ](http://echo.fox/trot) * * @example * {"name": "not-ok.md", "label": "output"} * - * 1:4: Remove 1 space before this heading’s content - * 3:7: Remove 1 space after this heading’s content - * 5:7: Remove 1 space before this heading’s content - * - * @example - * {"name": "empty-heading.md"} - * - * #·· + * 1:7-1:38: Don’t pad `link` with inner spaces */ -const remarkLintNoHeadingContentIndent = lintRule( +const remarkLintNoInlinePadding = lintRule( { - origin: 'remark-lint:no-heading-content-indent', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-heading-content-indent#readme' + origin: 'remark-lint:no-inline-padding', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-inline-padding#readme' }, (tree, file) => { - visit$1(tree, 'heading', (node) => { - if (generated(node)) { - return - } - const type = headingStyle(node, 'atx'); - if (type === 'atx' || type === 'atx-closed') { - const head = pointStart(node.children[0]).column; - if (!head) { - return - } - const diff = head - pointStart(node).column - 1 - node.depth; - if (diff) { - file.message( - 'Remove ' + - Math.abs(diff) + - ' ' + - plural('space', Math.abs(diff)) + - ' before this heading’s content', - pointStart(node.children[0]) - ); - } - } - if (type === 'atx-closed') { - const final = pointEnd(node.children[node.children.length - 1]); - const diff = pointEnd(node).column - final.column - 1 - node.depth; - if (diff) { - file.message( - 'Remove ' + - diff + - ' ' + - plural('space', diff) + - ' after this heading’s content', - final - ); + visit$q(tree, (node) => { + if ( + (node.type === 'link' || node.type === 'linkReference') && + !generated(node) + ) { + const value = toString(node); + if (value.charAt(0) === ' ' || value.charAt(value.length - 1) === ' ') { + file.message('Don’t pad `' + node.type + '` with inner spaces', node); } } }); } ); -var remarkLintNoHeadingContentIndent$1 = remarkLintNoHeadingContentIndent; +var remarkLintNoInlinePadding$1 = remarkLintNoInlinePadding; + +const convert$p = + ( + function (test) { + if (test === undefined || test === null) { + return ok$p + } + if (typeof test === 'string') { + return typeFactory$p(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$p(test) : propsFactory$p(test) + } + if (typeof test === 'function') { + return castFactory$p(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$p(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$p(tests[index]); + } + return castFactory$p(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$p(check) { + return castFactory$p(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$p(check) { + return castFactory$p(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$p(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$p() { + return true +} + +function color$q(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$p = true; +const EXIT$p = false; +const SKIP$p = 'skip'; +const visitParents$p = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$p(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$q(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$p(visitor(node, parents)); + if (result[0] === EXIT$p) { + return result + } + } + if (node.children && result[0] !== SKIP$p) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$p) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$p(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$p, value] + } + return [value] +} + +const visit$p = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$p(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); /** * ## When should I use this? * - * You can use this package to check that inline constructs (links) are - * not padded. - * Historically, it was possible to pad emphasis, strong, and strikethrough - * too, but this was removed in CommonMark, making this rule much less useful. + * You can use this package to check that collapsed or full reference images + * are used. * * ## API * - * There are no options. + * There are no options. + * + * ## Recommendation + * + * Shortcut references use an implicit style that looks a lot like something + * that could occur as plain text instead of syntax. + * In some cases, plain text is intended instead of an image. + * Due to this, it’s recommended to use collapsed (or full) references + * instead. * - * @module no-inline-padding + * @module no-shortcut-reference-image * @summary - * remark-lint rule to warn when inline constructs are padded. + * remark-lint rule to warn when shortcut reference images are used. * @author Titus Wormer * @copyright 2015 Titus Wormer * @license MIT * @example * {"name": "ok.md"} * - * Alpha [bravo](http://echo.fox/trot) + * ![foo][] + * + * [foo]: http://foo.bar/baz.png * * @example * {"name": "not-ok.md", "label": "input"} * - * Alpha [ bravo ](http://echo.fox/trot) + * ![foo] + * + * [foo]: http://foo.bar/baz.png * * @example * {"name": "not-ok.md", "label": "output"} * - * 1:7-1:38: Don’t pad `link` with inner spaces + * 1:1-1:7: Use the trailing [] on reference images */ -const remarkLintNoInlinePadding = lintRule( +const remarkLintNoShortcutReferenceImage = lintRule( { - origin: 'remark-lint:no-inline-padding', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-inline-padding#readme' + origin: 'remark-lint:no-shortcut-reference-image', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-shortcut-reference-image#readme' }, (tree, file) => { - visit$1(tree, (node) => { - if ( - (node.type === 'link' || node.type === 'linkReference') && - !generated(node) - ) { - const value = toString(node); - if (value.charAt(0) === ' ' || value.charAt(value.length - 1) === ' ') { - file.message('Don’t pad `' + node.type + '` with inner spaces', node); - } + visit$p(tree, 'imageReference', (node) => { + if (!generated(node) && node.referenceType === 'shortcut') { + file.message('Use the trailing [] on reference images', node); } }); } ); -var remarkLintNoInlinePadding$1 = remarkLintNoInlinePadding; +var remarkLintNoShortcutReferenceImage$1 = remarkLintNoShortcutReferenceImage; + +const convert$o = + ( + function (test) { + if (test === undefined || test === null) { + return ok$o + } + if (typeof test === 'string') { + return typeFactory$o(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$o(test) : propsFactory$o(test) + } + if (typeof test === 'function') { + return castFactory$o(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$o(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$o(tests[index]); + } + return castFactory$o(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$o(check) { + return castFactory$o(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$o(check) { + return castFactory$o(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$o(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$o() { + return true +} + +function color$p(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$o = true; +const EXIT$o = false; +const SKIP$o = 'skip'; +const visitParents$o = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$o(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$p(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$o(visitor(node, parents)); + if (result[0] === EXIT$o) { + return result + } + } + if (node.children && result[0] !== SKIP$o) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$o) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$o(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$o, value] + } + return [value] +} + +const visit$o = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$o(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); /** * ## When should I use this? * - * You can use this package to check that collapsed or full reference images + * You can use this package to check that collapsed or full reference links * are used. * * ## API @@ -13610,107 +15643,215 @@ var remarkLintNoInlinePadding$1 = remarkLintNoInlinePadding; * * Shortcut references use an implicit style that looks a lot like something * that could occur as plain text instead of syntax. - * In some cases, plain text is intended instead of an image. + * In some cases, plain text is intended instead of a link. * Due to this, it’s recommended to use collapsed (or full) references * instead. * - * @module no-shortcut-reference-image + * @module no-shortcut-reference-link * @summary - * remark-lint rule to warn when shortcut reference images are used. + * remark-lint rule to warn when shortcut reference links are used. * @author Titus Wormer * @copyright 2015 Titus Wormer * @license MIT * @example * {"name": "ok.md"} * - * ![foo][] + * [foo][] * - * [foo]: http://foo.bar/baz.png + * [foo]: http://foo.bar/baz * * @example * {"name": "not-ok.md", "label": "input"} * - * ![foo] + * [foo] * - * [foo]: http://foo.bar/baz.png + * [foo]: http://foo.bar/baz * * @example * {"name": "not-ok.md", "label": "output"} * - * 1:1-1:7: Use the trailing [] on reference images + * 1:1-1:6: Use the trailing `[]` on reference links */ -const remarkLintNoShortcutReferenceImage = lintRule( +const remarkLintNoShortcutReferenceLink = lintRule( { - origin: 'remark-lint:no-shortcut-reference-image', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-shortcut-reference-image#readme' + origin: 'remark-lint:no-shortcut-reference-link', + url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-shortcut-reference-link#readme' }, (tree, file) => { - visit$1(tree, 'imageReference', (node) => { + visit$o(tree, 'linkReference', (node) => { if (!generated(node) && node.referenceType === 'shortcut') { - file.message('Use the trailing [] on reference images', node); + file.message('Use the trailing `[]` on reference links', node); + } + }); + } +); +var remarkLintNoShortcutReferenceLink$1 = remarkLintNoShortcutReferenceLink; + +function normalizeIdentifier(value) { + return ( + value + .replace(/[\t\n\r ]+/g, ' ') + .replace(/^ | $/g, '') + .toLowerCase() + .toUpperCase() + ) +} + +const convert$n = + ( + function (test) { + if (test === undefined || test === null) { + return ok$n + } + if (typeof test === 'string') { + return typeFactory$n(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$n(test) : propsFactory$n(test) + } + if (typeof test === 'function') { + return castFactory$n(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$n(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$n(tests[index]); + } + return castFactory$n(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$n(check) { + return castFactory$n(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$n(check) { + return castFactory$n(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$n(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$n() { + return true +} + +function color$o(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$n = true; +const EXIT$n = false; +const SKIP$n = 'skip'; +const visitParents$n = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; } - }); + const is = convert$n(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$o(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$n(visitor(node, parents)); + if (result[0] === EXIT$n) { + return result + } + } + if (node.children && result[0] !== SKIP$n) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$n) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$n(value) { + if (Array.isArray(value)) { + return value } -); -var remarkLintNoShortcutReferenceImage$1 = remarkLintNoShortcutReferenceImage; + if (typeof value === 'number') { + return [CONTINUE$n, value] + } + return [value] +} -/** - * ## When should I use this? - * - * You can use this package to check that collapsed or full reference links - * are used. - * - * ## API - * - * There are no options. - * - * ## Recommendation - * - * Shortcut references use an implicit style that looks a lot like something - * that could occur as plain text instead of syntax. - * In some cases, plain text is intended instead of a link. - * Due to this, it’s recommended to use collapsed (or full) references - * instead. - * - * @module no-shortcut-reference-link - * @summary - * remark-lint rule to warn when shortcut reference links are used. - * @author Titus Wormer - * @copyright 2015 Titus Wormer - * @license MIT - * @example - * {"name": "ok.md"} - * - * [foo][] - * - * [foo]: http://foo.bar/baz - * - * @example - * {"name": "not-ok.md", "label": "input"} - * - * [foo] - * - * [foo]: http://foo.bar/baz - * - * @example - * {"name": "not-ok.md", "label": "output"} - * - * 1:1-1:6: Use the trailing `[]` on reference links - */ -const remarkLintNoShortcutReferenceLink = lintRule( - { - origin: 'remark-lint:no-shortcut-reference-link', - url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-shortcut-reference-link#readme' - }, - (tree, file) => { - visit$1(tree, 'linkReference', (node) => { - if (!generated(node) && node.referenceType === 'shortcut') { - file.message('Use the trailing `[]` on reference links', node); +const visit$n = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; } - }); - } -); -var remarkLintNoShortcutReferenceLink$1 = remarkLintNoShortcutReferenceLink; + visitParents$n(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); /** * ## When should I use this? @@ -13857,7 +15998,7 @@ const remarkLintNoUndefinedReferences = lintRule( regexes.push(new RegExp(value.source, 'i')); } } - visit$1(tree, (node) => { + visit$n(tree, (node) => { if ( (node.type === 'definition' || node.type === 'footnoteDefinition') && !generated(node) @@ -13865,7 +16006,7 @@ const remarkLintNoUndefinedReferences = lintRule( map[normalizeIdentifier(node.identifier)] = true; } }); - visit$1(tree, (node) => { + visit$n(tree, (node) => { if ( (node.type === 'imageReference' || node.type === 'linkReference' || @@ -13882,17 +16023,17 @@ const remarkLintNoUndefinedReferences = lintRule( }); function findInPhrasing(node) { let ranges = []; - visit$1(node, (child) => { + visit$n(node, (child) => { if (child === node) return if (child.type === 'link' || child.type === 'linkReference') { ranges = []; - return SKIP$1 + return SKIP$n } if (child.type !== 'text') return const start = pointStart(child).offset; const end = pointEnd(child).offset; if (typeof start !== 'number' || typeof end !== 'number') { - return EXIT$1 + return EXIT$n } const source = contents.slice(start, end); const lines = [[start, '']]; @@ -13959,7 +16100,7 @@ const remarkLintNoUndefinedReferences = lintRule( while (++index < ranges.length) { handleRange(ranges[index]); } - return SKIP$1 + return SKIP$n function handleRange(range) { if (range.length === 1) return if (range.length === 3) range.length = 2; @@ -13992,6 +16133,162 @@ const remarkLintNoUndefinedReferences = lintRule( ); var remarkLintNoUndefinedReferences$1 = remarkLintNoUndefinedReferences; +const convert$m = + ( + function (test) { + if (test === undefined || test === null) { + return ok$m + } + if (typeof test === 'string') { + return typeFactory$m(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$m(test) : propsFactory$m(test) + } + if (typeof test === 'function') { + return castFactory$m(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$m(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$m(tests[index]); + } + return castFactory$m(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$m(check) { + return castFactory$m(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$m(check) { + return castFactory$m(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$m(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$m() { + return true +} + +function color$n(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$m = true; +const EXIT$m = false; +const SKIP$m = 'skip'; +const visitParents$m = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$m(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$n(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$m(visitor(node, parents)); + if (result[0] === EXIT$m) { + return result + } + } + if (node.children && result[0] !== SKIP$m) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$m) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$m(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$m, value] + } + return [value] +} + +const visit$m = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$m(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); + /** * ## When should I use this? * @@ -14036,7 +16333,7 @@ const remarkLintNoUnusedDefinitions = lintRule( }, (tree, file) => { const map = Object.create(null); - visit$1(tree, (node) => { + visit$m(tree, (node) => { if ( (node.type === 'definition' || node.type === 'footnoteDefinition') && !generated(node) @@ -14044,7 +16341,7 @@ const remarkLintNoUnusedDefinitions = lintRule( map[node.identifier.toUpperCase()] = {node, used: false}; } }); - visit$1(tree, (node) => { + visit$m(tree, (node) => { if ( node.type === 'imageReference' || node.type === 'linkReference' || @@ -14090,6 +16387,162 @@ const remarkPresetLintRecommended = { }; var remarkPresetLintRecommended$1 = remarkPresetLintRecommended; +const convert$l = + ( + function (test) { + if (test === undefined || test === null) { + return ok$l + } + if (typeof test === 'string') { + return typeFactory$l(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$l(test) : propsFactory$l(test) + } + if (typeof test === 'function') { + return castFactory$l(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$l(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$l(tests[index]); + } + return castFactory$l(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$l(check) { + return castFactory$l(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$l(check) { + return castFactory$l(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$l(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$l() { + return true +} + +function color$m(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$l = true; +const EXIT$l = false; +const SKIP$l = 'skip'; +const visitParents$l = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$l(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$m(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$l(visitor(node, parents)); + if (result[0] === EXIT$l) { + return result + } + } + if (node.children && result[0] !== SKIP$l) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$l) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$l(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$l, value] + } + return [value] +} + +const visit$l = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$l(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); + /** * ## When should I use this? * @@ -14175,7 +16628,7 @@ const remarkLintBlockquoteIndentation = lintRule( url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-blockquote-indentation#readme' }, (tree, file, option = 'consistent') => { - visit$1(tree, 'blockquote', (node) => { + visit$l(tree, 'blockquote', (node) => { if (generated(node) || node.children.length === 0) { return } @@ -14196,13 +16649,169 @@ const remarkLintBlockquoteIndentation = lintRule( ); } } - }); - } -); -var remarkLintBlockquoteIndentation$1 = remarkLintBlockquoteIndentation; -function check(node) { - return pointStart(node.children[0]).column - pointStart(node).column -} + }); + } +); +var remarkLintBlockquoteIndentation$1 = remarkLintBlockquoteIndentation; +function check(node) { + return pointStart(node.children[0]).column - pointStart(node).column +} + +const convert$k = + ( + function (test) { + if (test === undefined || test === null) { + return ok$k + } + if (typeof test === 'string') { + return typeFactory$k(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$k(test) : propsFactory$k(test) + } + if (typeof test === 'function') { + return castFactory$k(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$k(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$k(tests[index]); + } + return castFactory$k(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$k(check) { + return castFactory$k(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$k(check) { + return castFactory$k(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$k(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$k() { + return true +} + +function color$l(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$k = true; +const EXIT$k = false; +const SKIP$k = 'skip'; +const visitParents$k = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$k(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$l(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$k(visitor(node, parents)); + if (result[0] === EXIT$k) { + return result + } + } + if (node.children && result[0] !== SKIP$k) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$k) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$k(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$k, value] + } + return [value] +} + +const visit$k = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$k(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); /** * ## When should I use this? @@ -14319,7 +16928,7 @@ const remarkLintCheckboxCharacterStyle = lintRule( "`: use either `'x'`, or `'X'`" ); } - visit$1(tree, 'listItem', (node) => { + visit$k(tree, 'listItem', (node) => { const head = node.children[0]; const point = pointStart(head); if ( @@ -14356,6 +16965,162 @@ const remarkLintCheckboxCharacterStyle = lintRule( ); var remarkLintCheckboxCharacterStyle$1 = remarkLintCheckboxCharacterStyle; +const convert$j = + ( + function (test) { + if (test === undefined || test === null) { + return ok$j + } + if (typeof test === 'string') { + return typeFactory$j(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$j(test) : propsFactory$j(test) + } + if (typeof test === 'function') { + return castFactory$j(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$j(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$j(tests[index]); + } + return castFactory$j(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$j(check) { + return castFactory$j(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$j(check) { + return castFactory$j(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$j(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$j() { + return true +} + +function color$k(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$j = true; +const EXIT$j = false; +const SKIP$j = 'skip'; +const visitParents$j = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$j(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$k(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$j(visitor(node, parents)); + if (result[0] === EXIT$j) { + return result + } + } + if (node.children && result[0] !== SKIP$j) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$j) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$j(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$j, value] + } + return [value] +} + +const visit$j = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$j(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); + /** * ## When should I use this? * @@ -14426,7 +17191,7 @@ const remarkLintCheckboxContentIndent = lintRule( (tree, file) => { const value = String(file); const loc = location(file); - visit$1(tree, 'listItem', (node) => { + visit$j(tree, 'listItem', (node) => { const head = node.children[0]; const point = pointStart(head); if ( @@ -14449,10 +17214,166 @@ const remarkLintCheckboxContentIndent = lintRule( end: loc.toPoint(final) }); } - }); - } -); -var remarkLintCheckboxContentIndent$1 = remarkLintCheckboxContentIndent; + }); + } +); +var remarkLintCheckboxContentIndent$1 = remarkLintCheckboxContentIndent; + +const convert$i = + ( + function (test) { + if (test === undefined || test === null) { + return ok$i + } + if (typeof test === 'string') { + return typeFactory$i(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$i(test) : propsFactory$i(test) + } + if (typeof test === 'function') { + return castFactory$i(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$i(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$i(tests[index]); + } + return castFactory$i(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$i(check) { + return castFactory$i(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$i(check) { + return castFactory$i(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$i(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$i() { + return true +} + +function color$j(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$i = true; +const EXIT$i = false; +const SKIP$i = 'skip'; +const visitParents$i = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$i(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$j(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$i(visitor(node, parents)); + if (result[0] === EXIT$i) { + return result + } + } + if (node.children && result[0] !== SKIP$i) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$i) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$i(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$i, value] + } + return [value] +} + +const visit$i = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$i(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); /** * ## When should I use this? @@ -14599,7 +17520,7 @@ const remarkLintCodeBlockStyle = lintRule( "`: use either `'consistent'`, `'fenced'`, or `'indented'`" ); } - visit$1(tree, 'code', (node) => { + visit$i(tree, 'code', (node) => { if (generated(node)) { return } @@ -14619,6 +17540,162 @@ const remarkLintCodeBlockStyle = lintRule( ); var remarkLintCodeBlockStyle$1 = remarkLintCodeBlockStyle; +const convert$h = + ( + function (test) { + if (test === undefined || test === null) { + return ok$h + } + if (typeof test === 'string') { + return typeFactory$h(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$h(test) : propsFactory$h(test) + } + if (typeof test === 'function') { + return castFactory$h(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$h(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$h(tests[index]); + } + return castFactory$h(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$h(check) { + return castFactory$h(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$h(check) { + return castFactory$h(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$h(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$h() { + return true +} + +function color$i(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$h = true; +const EXIT$h = false; +const SKIP$h = 'skip'; +const visitParents$h = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$h(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$i(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$h(visitor(node, parents)); + if (result[0] === EXIT$h) { + return result + } + } + if (node.children && result[0] !== SKIP$h) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$h) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$h(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$h, value] + } + return [value] +} + +const visit$h = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$h(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); + /** * ## When should I use this? * @@ -14667,7 +17744,7 @@ const remarkLintDefinitionSpacing = lintRule( }, (tree, file) => { const value = String(file); - visit$1(tree, (node) => { + visit$h(tree, (node) => { if (node.type === 'definition' || node.type === 'footnoteDefinition') { const start = pointStart(node).offset; const end = pointEnd(node).offset; @@ -14683,8 +17760,164 @@ const remarkLintDefinitionSpacing = lintRule( } }); } -); -var remarkLintDefinitionSpacing$1 = remarkLintDefinitionSpacing; +); +var remarkLintDefinitionSpacing$1 = remarkLintDefinitionSpacing; + +const convert$g = + ( + function (test) { + if (test === undefined || test === null) { + return ok$g + } + if (typeof test === 'string') { + return typeFactory$g(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$g(test) : propsFactory$g(test) + } + if (typeof test === 'function') { + return castFactory$g(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$g(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$g(tests[index]); + } + return castFactory$g(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$g(check) { + return castFactory$g(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$g(check) { + return castFactory$g(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$g(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$g() { + return true +} + +function color$h(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$g = true; +const EXIT$g = false; +const SKIP$g = 'skip'; +const visitParents$g = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$g(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$h(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$g(visitor(node, parents)); + if (result[0] === EXIT$g) { + return result + } + } + if (node.children && result[0] !== SKIP$g) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$g) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$g(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$g, value] + } + return [value] +} + +const visit$g = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$g(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); /** * ## When should I use this? @@ -14802,7 +18035,7 @@ const remarkLintFencedCodeFlag = lintRule( } } } - visit$1(tree, 'code', (node) => { + visit$g(tree, 'code', (node) => { if (!generated(node)) { if (node.lang) { if (allowed.length > 0 && !allowed.includes(node.lang)) { @@ -14823,6 +18056,162 @@ const remarkLintFencedCodeFlag = lintRule( ); var remarkLintFencedCodeFlag$1 = remarkLintFencedCodeFlag; +const convert$f = + ( + function (test) { + if (test === undefined || test === null) { + return ok$f + } + if (typeof test === 'string') { + return typeFactory$f(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$f(test) : propsFactory$f(test) + } + if (typeof test === 'function') { + return castFactory$f(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$f(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$f(tests[index]); + } + return castFactory$f(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$f(check) { + return castFactory$f(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$f(check) { + return castFactory$f(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$f(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$f() { + return true +} + +function color$g(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$f = true; +const EXIT$f = false; +const SKIP$f = 'skip'; +const visitParents$f = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$f(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$g(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$f(visitor(node, parents)); + if (result[0] === EXIT$f) { + return result + } + } + if (node.children && result[0] !== SKIP$f) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$f) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$f(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$f, value] + } + return [value] +} + +const visit$f = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$f(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); + /** * ## When should I use this? * @@ -14938,7 +18327,7 @@ const remarkLintFencedCodeMarker = lintRule( "`: use either `'consistent'`, `` '`' ``, or `'~'`" ); } - visit$1(tree, 'code', (node) => { + visit$f(tree, 'code', (node) => { const start = pointStart(node).offset; if (typeof start === 'number') { const marker = contents @@ -15016,8 +18405,164 @@ const remarkLintFileExtension = lintRule( file.message('Incorrect extension: use `' + option + '`'); } } -); -var remarkLintFileExtension$1 = remarkLintFileExtension; +); +var remarkLintFileExtension$1 = remarkLintFileExtension; + +const convert$e = + ( + function (test) { + if (test === undefined || test === null) { + return ok$e + } + if (typeof test === 'string') { + return typeFactory$e(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$e(test) : propsFactory$e(test) + } + if (typeof test === 'function') { + return castFactory$e(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$e(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$e(tests[index]); + } + return castFactory$e(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$e(check) { + return castFactory$e(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$e(check) { + return castFactory$e(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$e(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$e() { + return true +} + +function color$f(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$e = true; +const EXIT$e = false; +const SKIP$e = 'skip'; +const visitParents$e = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$e(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$f(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$e(visitor(node, parents)); + if (result[0] === EXIT$e) { + return result + } + } + if (node.children && result[0] !== SKIP$e) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$e) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$e(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$e, value] + } + return [value] +} + +const visit$e = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$e(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); /** * ## When should I use this? @@ -15081,7 +18626,7 @@ const remarkLintFinalDefinition = lintRule( }, (tree, file) => { let last = 0; - visit$1( + visit$e( tree, (node) => { if ( @@ -15111,6 +18656,162 @@ const remarkLintFinalDefinition = lintRule( ); var remarkLintFinalDefinition$1 = remarkLintFinalDefinition; +const convert$d = + ( + function (test) { + if (test === undefined || test === null) { + return ok$d + } + if (typeof test === 'string') { + return typeFactory$d(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$d(test) : propsFactory$d(test) + } + if (typeof test === 'function') { + return castFactory$d(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$d(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$d(tests[index]); + } + return castFactory$d(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$d(check) { + return castFactory$d(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$d(check) { + return castFactory$d(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$d(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$d() { + return true +} + +function color$e(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$d = true; +const EXIT$d = false; +const SKIP$d = 'skip'; +const visitParents$d = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$d(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$e(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$d(visitor(node, parents)); + if (result[0] === EXIT$d) { + return result + } + } + if (node.children && result[0] !== SKIP$d) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$d) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$d(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$d, value] + } + return [value] +} + +const visit$d = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$d(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); + /** * ## When should I use this? * @@ -15225,7 +18926,7 @@ const remarkLintFirstHeadingLevel = lintRule( url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-first-heading-level#readme' }, (tree, file, option = 1) => { - visit$1(tree, (node) => { + visit$d(tree, (node) => { if (!generated(node)) { let rank; if (node.type === 'heading') { @@ -15237,18 +18938,174 @@ const remarkLintFirstHeadingLevel = lintRule( if (rank !== option) { file.message('First heading level should be `' + option + '`', node); } - return EXIT$1 + return EXIT$d + } + } + }); + } +); +var remarkLintFirstHeadingLevel$1 = remarkLintFirstHeadingLevel; +function infer(node) { + const results = node.value.match(re$2); + return results ? Number(results[1]) : undefined +} + +const convert$c = + ( + function (test) { + if (test === undefined || test === null) { + return ok$c + } + if (typeof test === 'string') { + return typeFactory$c(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$c(test) : propsFactory$c(test) + } + if (typeof test === 'function') { + return castFactory$c(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$c(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$c(tests[index]); + } + return castFactory$c(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$c(check) { + return castFactory$c(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$c(check) { + return castFactory$c(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$c(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$c() { + return true +} + +function color$d(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$c = true; +const EXIT$c = false; +const SKIP$c = 'skip'; +const visitParents$c = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$c(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$d(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$c(visitor(node, parents)); + if (result[0] === EXIT$c) { + return result + } + } + if (node.children && result[0] !== SKIP$c) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$c) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result } } - }); + } + ); +function toResult$c(value) { + if (Array.isArray(value)) { + return value } -); -var remarkLintFirstHeadingLevel$1 = remarkLintFirstHeadingLevel; -function infer(node) { - const results = node.value.match(re$2); - return results ? Number(results[1]) : undefined + if (typeof value === 'number') { + return [CONTINUE$c, value] + } + return [value] } +const visit$c = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$c(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); + /** * ## When should I use this? * @@ -15380,7 +19237,7 @@ const remarkLintHeadingStyle = lintRule( "`: use either `'consistent'`, `'atx'`, `'atx-closed'`, or `'setext'`" ); } - visit$1(tree, 'heading', (node) => { + visit$c(tree, 'heading', (node) => { if (!generated(node)) { if (option === 'consistent') { option = headingStyle(node) || 'consistent'; @@ -15393,6 +19250,162 @@ const remarkLintHeadingStyle = lintRule( ); var remarkLintHeadingStyle$1 = remarkLintHeadingStyle; +const convert$b = + ( + function (test) { + if (test === undefined || test === null) { + return ok$b + } + if (typeof test === 'string') { + return typeFactory$b(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$b(test) : propsFactory$b(test) + } + if (typeof test === 'function') { + return castFactory$b(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$b(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$b(tests[index]); + } + return castFactory$b(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$b(check) { + return castFactory$b(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$b(check) { + return castFactory$b(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$b(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$b() { + return true +} + +function color$c(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$b = true; +const EXIT$b = false; +const SKIP$b = 'skip'; +const visitParents$b = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$b(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$c(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$b(visitor(node, parents)); + if (result[0] === EXIT$b) { + return result + } + } + if (node.children && result[0] !== SKIP$b) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$b) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$b(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$b, value] + } + return [value] +} + +const visit$b = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$b(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); + /** * ## When should I use this? * @@ -15509,7 +19522,7 @@ const remarkLintMaximumLineLength = lintRule( (tree, file, option = 80) => { const value = String(file); const lines = value.split(/\r?\n/); - visit$1(tree, (node) => { + visit$b(tree, (node) => { if ( (node.type === 'heading' || node.type === 'table' || @@ -15529,7 +19542,7 @@ const remarkLintMaximumLineLength = lintRule( allowList(pointStart(node).line - 1, pointEnd(node).line); } }); - visit$1(tree, (node, pos, parent) => { + visit$b(tree, (node, pos, parent) => { if ( (node.type === 'link' || node.type === 'image' || @@ -15543,35 +19556,191 @@ const remarkLintMaximumLineLength = lintRule( if (initial.column > option || final.column < option) { return } - const next = parent.children[pos + 1]; - if ( - next && - pointStart(next).line === initial.line && - (!('value' in next) || /^(.+?[ \t].+?)/.test(next.value)) - ) { - return + const next = parent.children[pos + 1]; + if ( + next && + pointStart(next).line === initial.line && + (!('value' in next) || /^(.+?[ \t].+?)/.test(next.value)) + ) { + return + } + allowList(initial.line - 1, final.line); + } + }); + let index = -1; + while (++index < lines.length) { + const lineLength = lines[index].length; + if (lineLength > option) { + file.message('Line must be at most ' + option + ' characters', { + line: index + 1, + column: lineLength + 1 + }); + } + } + function allowList(initial, final) { + while (initial < final) { + lines[initial++] = ''; + } + } + } +); +var remarkLintMaximumLineLength$1 = remarkLintMaximumLineLength; + +const convert$a = + ( + function (test) { + if (test === undefined || test === null) { + return ok$a + } + if (typeof test === 'string') { + return typeFactory$a(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$a(test) : propsFactory$a(test) + } + if (typeof test === 'function') { + return castFactory$a(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$a(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$a(tests[index]); + } + return castFactory$a(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$a(check) { + return castFactory$a(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$a(check) { + return castFactory$a(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$a(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$a() { + return true +} + +function color$b(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$a = true; +const EXIT$a = false; +const SKIP$a = 'skip'; +const visitParents$a = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$a(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$b(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$a(visitor(node, parents)); + if (result[0] === EXIT$a) { + return result + } + } + if (node.children && result[0] !== SKIP$a) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$a) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result } - allowList(initial.line - 1, final.line); - } - }); - let index = -1; - while (++index < lines.length) { - const lineLength = lines[index].length; - if (lineLength > option) { - file.message('Line must be at most ' + option + ' characters', { - line: index + 1, - column: lineLength + 1 - }); } } - function allowList(initial, final) { - while (initial < final) { - lines[initial++] = ''; + ); +function toResult$a(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$a, value] + } + return [value] +} + +const visit$a = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$a(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) } } - } -); -var remarkLintMaximumLineLength$1 = remarkLintMaximumLineLength; + ); /** * ## When should I use this? @@ -15632,7 +19801,7 @@ const remarkLintNoConsecutiveBlankLines = lintRule( url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-consecutive-blank-lines#readme' }, (tree, file) => { - visit$1(tree, (node) => { + visit$a(tree, (node) => { if (!generated(node) && 'children' in node) { const head = node.children[0]; if (head && !generated(head)) { @@ -15810,6 +19979,162 @@ const remarkLintNofileNameOuterDashes = lintRule( ); var remarkLintNofileNameOuterDashes$1 = remarkLintNofileNameOuterDashes; +const convert$9 = + ( + function (test) { + if (test === undefined || test === null) { + return ok$9 + } + if (typeof test === 'string') { + return typeFactory$9(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$9(test) : propsFactory$9(test) + } + if (typeof test === 'function') { + return castFactory$9(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$9(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$9(tests[index]); + } + return castFactory$9(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$9(check) { + return castFactory$9(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$9(check) { + return castFactory$9(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$9(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$9() { + return true +} + +function color$a(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$9 = true; +const EXIT$9 = false; +const SKIP$9 = 'skip'; +const visitParents$9 = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$9(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$a(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$9(visitor(node, parents)); + if (result[0] === EXIT$9) { + return result + } + } + if (node.children && result[0] !== SKIP$9) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$9) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$9(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$9, value] + } + return [value] +} + +const visit$9 = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$9(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); + /** * ## When should I use this? * @@ -15887,25 +20212,206 @@ const remarkLintNoHeadingIndent = lintRule( url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-heading-indent#readme' }, (tree, file) => { - visit$1(tree, 'heading', (node, _, parent) => { + visit$9(tree, 'heading', (node, _, parent) => { if (generated(node) || (parent && parent.type !== 'root')) { return } - const diff = pointStart(node).column - 1; - if (diff) { - file.message( - 'Remove ' + - diff + - ' ' + - plural('space', diff) + - ' before this heading', - pointStart(node) - ); + const diff = pointStart(node).column - 1; + if (diff) { + file.message( + 'Remove ' + + diff + + ' ' + + plural('space', diff) + + ' before this heading', + pointStart(node) + ); + } + }); + } +); +var remarkLintNoHeadingIndent$1 = remarkLintNoHeadingIndent; + +const convert$8 = + ( + function (test) { + if (test === undefined || test === null) { + return ok$8 + } + if (typeof test === 'string') { + return typeFactory$8(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$8(test) : propsFactory$8(test) + } + if (typeof test === 'function') { + return castFactory$8(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$8(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$8(tests[index]); + } + return castFactory$8(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$8(check) { + return castFactory$8(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$8(check) { + return castFactory$8(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$8(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$8() { + return true +} + +function color$9(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$8 = true; +const EXIT$8 = false; +const SKIP$8 = 'skip'; +const visitParents$8 = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$8(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$9(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$8(visitor(node, parents)); + if (result[0] === EXIT$8) { + return result + } + } + if (node.children && result[0] !== SKIP$8) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$8) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } } - }); + } + ); +function toResult$8(value) { + if (Array.isArray(value)) { + return value } -); -var remarkLintNoHeadingIndent$1 = remarkLintNoHeadingIndent; + if (typeof value === 'number') { + return [CONTINUE$8, value] + } + return [value] +} + +const visit$8 = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$8(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); + +function stringifyPosition(value) { + if (!value || typeof value !== 'object') { + return '' + } + if ('position' in value || 'type' in value) { + return position(value.position) + } + if ('start' in value || 'end' in value) { + return position(value) + } + if ('line' in value || 'column' in value) { + return point(value) + } + return '' +} +function point(point) { + return index(point && point.line) + ':' + index(point && point.column) +} +function position(pos) { + return point(pos && pos.start) + '-' + point(pos && pos.end) +} +function index(value) { + return value && typeof value === 'number' ? value : 1 +} /** * ## When should I use this? @@ -15957,7 +20463,7 @@ const remarkLintNoMultipleToplevelHeadings = lintRule( }, (tree, file, option = 1) => { let duplicate; - visit$1(tree, 'heading', (node) => { + visit$8(tree, 'heading', (node) => { if (!generated(node) && node.depth === option) { if (duplicate) { file.message( @@ -15965,7 +20471,7 @@ const remarkLintNoMultipleToplevelHeadings = lintRule( node ); } else { - duplicate = stringifyPosition$1(pointStart(node)); + duplicate = stringifyPosition(pointStart(node)); } } }); @@ -15973,6 +20479,162 @@ const remarkLintNoMultipleToplevelHeadings = lintRule( ); var remarkLintNoMultipleToplevelHeadings$1 = remarkLintNoMultipleToplevelHeadings; +const convert$7 = + ( + function (test) { + if (test === undefined || test === null) { + return ok$7 + } + if (typeof test === 'string') { + return typeFactory$7(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$7(test) : propsFactory$7(test) + } + if (typeof test === 'function') { + return castFactory$7(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$7(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$7(tests[index]); + } + return castFactory$7(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$7(check) { + return castFactory$7(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$7(check) { + return castFactory$7(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$7(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$7() { + return true +} + +function color$8(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$7 = true; +const EXIT$7 = false; +const SKIP$7 = 'skip'; +const visitParents$7 = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$7(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$8(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$7(visitor(node, parents)); + if (result[0] === EXIT$7) { + return result + } + } + if (node.children && result[0] !== SKIP$7) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$7) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$7(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$7, value] + } + return [value] +} + +const visit$7 = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$7(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); + /** * ## When should I use this? * @@ -16062,7 +20724,7 @@ const remarkLintNoShellDollars = lintRule( url: 'https://github.com/remarkjs/remark-lint/tree/main/packages/remark-lint-no-shell-dollars#readme' }, (tree, file) => { - visit$1(tree, 'code', (node) => { + visit$7(tree, 'code', (node) => { if (!generated(node) && node.lang && flags.has(node.lang)) { const lines = node.value .split('\n') @@ -16084,6 +20746,162 @@ const remarkLintNoShellDollars = lintRule( ); var remarkLintNoShellDollars$1 = remarkLintNoShellDollars; +const convert$6 = + ( + function (test) { + if (test === undefined || test === null) { + return ok$6 + } + if (typeof test === 'string') { + return typeFactory$6(test) + } + if (typeof test === 'object') { + return Array.isArray(test) ? anyFactory$6(test) : propsFactory$6(test) + } + if (typeof test === 'function') { + return castFactory$6(test) + } + throw new Error('Expected function, string, or object as test') + } + ); +function anyFactory$6(tests) { + const checks = []; + let index = -1; + while (++index < tests.length) { + checks[index] = convert$6(tests[index]); + } + return castFactory$6(any) + function any(...parameters) { + let index = -1; + while (++index < checks.length) { + if (checks[index].call(this, ...parameters)) return true + } + return false + } +} +function propsFactory$6(check) { + return castFactory$6(all) + function all(node) { + let key; + for (key in check) { + if (node[key] !== check[key]) return false + } + return true + } +} +function typeFactory$6(check) { + return castFactory$6(type) + function type(node) { + return node && node.type === check + } +} +function castFactory$6(check) { + return assertion + function assertion(node, ...parameters) { + return Boolean( + node && + typeof node === 'object' && + 'type' in node && + Boolean(check.call(this, node, ...parameters)) + ) + } +} +function ok$6() { + return true +} + +function color$7(d) { + return '\u001B[33m' + d + '\u001B[39m' +} + +const CONTINUE$6 = true; +const EXIT$6 = false; +const SKIP$6 = 'skip'; +const visitParents$6 = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + const is = convert$6(test); + const step = reverse ? -1 : 1; + factory(tree, undefined, [])(); + function factory(node, index, parents) { + const value = node && typeof node === 'object' ? node : {}; + if (typeof value.type === 'string') { + const name = + typeof value.tagName === 'string' + ? value.tagName + : + typeof value.name === 'string' + ? value.name + : undefined; + Object.defineProperty(visit, 'name', { + value: + 'node (' + color$7(node.type + (name ? '<' + name + '>' : '')) + ')' + }); + } + return visit + function visit() { + let result = []; + let subresult; + let offset; + let grandparents; + if (!test || is(node, index, parents[parents.length - 1] || null)) { + result = toResult$6(visitor(node, parents)); + if (result[0] === EXIT$6) { + return result + } + } + if (node.children && result[0] !== SKIP$6) { + offset = (reverse ? node.children.length : -1) + step; + grandparents = parents.concat(node); + while (offset > -1 && offset < node.children.length) { + subresult = factory(node.children[offset], offset, grandparents)(); + if (subresult[0] === EXIT$6) { + return subresult + } + offset = + typeof subresult[1] === 'number' ? subresult[1] : offset + step; + } + } + return result + } + } + } + ); +function toResult$6(value) { + if (Array.isArray(value)) { + return value + } + if (typeof value === 'number') { + return [CONTINUE$6, value] + } + return [value] +} + +const visit$6 = + ( + function (tree, test, visitor, reverse) { + if (typeof test === 'function' && typeof visitor !== 'function') { + reverse = visitor; + visitor = test; + test = null; + } + visitParents$6(tree, test, overload, reverse); + function overload(node, parents) { + const parent = parents[parents.length - 1]; + return visitor( + node, + parent ? parent.children.indexOf(node) : null, + parent + ) + } + } + ); + /** * ## When should I use this? * @@ -16169,7 +20987,7 @@ const remarkLintNoTableIndentation = lintRule( (tree, file) => { const value = String(file); const loc = location(value); - visit$1(tree, 'table', (node, _, parent) => { + visit$6(tree, 'table', (node, _, parent) => { const end = pointEnd(node).line; let line = pointStart(node).line; let column = 0; @@ -16203,7 +21021,7 @@ const remarkLintNoTableIndentation = lintRule( } line++; } - return SKIP$1 + return SKIP$6 }); } ); @@ -16662,7 +21480,7 @@ function* getLinksRecursively(node) { } } function validateLinks(tree, vfile) { - const currentFileURL = pathToFileURL(path$1.join(vfile.cwd, vfile.path)); + const currentFileURL = pathToFileURL(path$2.join(vfile.cwd, vfile.path)); let previousDefinitionLabel; for (const node of getLinksRecursively(tree)) { if (node.url[0] !== "#") { @@ -16675,7 +21493,7 @@ function validateLinks(tree, vfile) { : "#"; vfile.message( `Self-reference must start with hash (expected "${expected}", got "${node.url}")`, - node + node, ); } } @@ -16683,7 +21501,7 @@ function validateLinks(tree, vfile) { if (previousDefinitionLabel && previousDefinitionLabel > node.label) { vfile.message( `Unordered reference ("${node.label}" should be before "${previousDefinitionLabel}")`, - node + node, ); } previousDefinitionLabel = node.label; @@ -16692,7 +21510,7 @@ function validateLinks(tree, vfile) { } const remarkLintNodejsLinks = lintRule( "remark-lint:nodejs-links", - validateLinks + validateLinks, ); /*! js-yaml 4.1.0 https://github.com/nodeca/js-yaml @license MIT */ @@ -19980,7 +24798,7 @@ const allowedKeys = [ const changesExpectedKeys = ["version", "pr-url", "description"]; const VERSION_PLACEHOLDER = "REPLACEME"; const MAX_SAFE_SEMVER_VERSION = semverParse( - Array.from({ length: 3 }, () => Number.MAX_SAFE_INTEGER).join(".") + Array.from({ length: 3 }, () => Number.MAX_SAFE_INTEGER).join("."), ); const validVersionNumberRegex = /^v\d+\.\d+\.\d+$/; const prUrlRegex = new RegExp("^https://github.com/nodejs/node/pull/\\d+$"); @@ -19990,7 +24808,7 @@ let invalidVersionMessage = "version(s) must respect the pattern `vx.x.x` or"; if (process.env.NODE_RELEASED_VERSIONS) { console.log("Using release list from env..."); releasedVersions = process.env.NODE_RELEASED_VERSIONS.split(",").map( - (v) => `v${v}` + (v) => `v${v}`, ); invalidVersionMessage = `version not listed in the changelogs, `; } @@ -20028,7 +24846,7 @@ function areVersionsUnordered(versions) { if ( semverLt( getValidSemver(versions[index - 1]), - getValidSemver(versions[index]) + getValidSemver(versions[index]), ) ) { return true; @@ -20048,7 +24866,7 @@ function validateSecurityChange(file, node, change, index) { if (typeof change.commit !== "string" || isNaN(`0x${change.commit}`)) { file.message( `changes[${index}]: Ill-formed security change commit ID`, - node + node, ); } if (Object.keys(change)[1] === "commit") { @@ -20062,7 +24880,7 @@ function validateSecurityChange(file, node, change, index) { file.message( `changes[${index}]: Invalid keys. Expected keys are: ` + securityChangeExpectedKeys.join(", "), - node + node, ); } } @@ -20084,7 +24902,7 @@ function validateChanges(file, node, changes) { file.message( `changes[${index}]: Invalid keys. Expected keys are: ` + changesExpectedKeys.join(", "), - node + node, ); } if (containsInvalidVersionNumber(change.version)) { @@ -20095,22 +24913,22 @@ function validateChanges(file, node, changes) { if (!isAncient && !isSecurityChange && !prUrlRegex.test(change["pr-url"])) { file.message( `changes[${index}]: PR-URL does not match the expected pattern`, - node + node, ); } if (typeof change.description !== "string" || !change.description.length) { file.message( `changes[${index}]: must contain a non-empty description`, - node + node, ); } else if (!change.description.endsWith(".")) { file.message( `changes[${index}]: description must end with a period`, - node + node, ); } changesVersions.push( - Array.isArray(change.version) ? change.version[0] : change.version + Array.isArray(change.version) ? change.version[0] : change.version, ); } if (areVersionsUnordered(changesVersions)) { @@ -20123,14 +24941,14 @@ function validateMeta(node, file, meta) { file.message( "YAML dictionary contains illegal keys. Accepted values are: " + allowedKeys.join(", "), - node + node, ); break; case kWrongKeyOrder: file.message( "YAML dictionary keys should be in this order: " + allowedKeys.join(", "), - node + node, ); break; } @@ -20142,7 +24960,7 @@ function validateMeta(node, file, meta) { if (containsInvalidVersionNumber(meta.deprecated)) { file.message( `Invalid \`deprecated\` value: ${invalidVersionMessage}`, - node + node, ); } else if (areVersionsUnordered(meta.deprecated)) { file.message("Versions in `deprecated` list are not in order", node); @@ -20157,11 +24975,11 @@ function validateMeta(node, file, meta) { } } function validateYAMLComments(tree, file) { - visit$1(tree, "html", function visitor(node) { + visit$A(tree, "html", function visitor(node) { if (node.value.startsWith("